From 118afd458a7e4f529712034047150e902b93f001 Mon Sep 17 00:00:00 2001
From: Ben Mosher <me@benmosher.com>
Date: Wed, 17 Jul 2019 06:57:34 -0400
Subject: [PATCH 001/767] no-deprecated: don't run tests for
 typescript-eslint-parser against ESLint <4

---
 tests/src/rules/no-deprecated.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index 05bd21ef99..eb08d412e6 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -209,7 +209,8 @@ describe('Typescript', function () {
     parsers.push(require.resolve('@typescript-eslint/parser'))
   }
 
-  if (semver.satisfies(eslintPkg.version, '<6.0.0')) {
+  // typescript-eslint-parser doesn't support this rule on ESLint <4 for some reason
+  if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
     parsers.push(require.resolve('typescript-eslint-parser'))
   }
 

From c5078addd9e35fb20f25376148de65de760a5977 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 16 Jul 2019 23:15:22 -0700
Subject: [PATCH 002/767] [Refactor] `importType`: remove use of `cond`

Using normal JS makes for far more understandable and maintainable code.
---
 src/core/importType.js | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/src/core/importType.js b/src/core/importType.js
index 7755bb4a24..b948ea2bb9 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -1,13 +1,8 @@
-import cond from 'lodash/cond'
 import coreModules from 'resolve/lib/core'
 import { join } from 'path'
 
 import resolve from 'eslint-module-utils/resolve'
 
-function constant(value) {
-  return () => value
-}
-
 function baseModule(name) {
   if (isScoped(name)) {
     const [scope, pkg] = name.split('/')
@@ -76,17 +71,17 @@ function isRelativeToSibling(name) {
   return /^\.[\\/]/.test(name)
 }
 
-const typeTest = cond([
-  [isAbsolute, constant('absolute')],
-  [isBuiltIn, constant('builtin')],
-  [isInternalModule, constant('internal')],
-  [isExternalModule, constant('external')],
-  [isScoped, constant('external')],
-  [isRelativeToParent, constant('parent')],
-  [isIndex, constant('index')],
-  [isRelativeToSibling, constant('sibling')],
-  [constant(true), constant('unknown')],
-])
+function typeTest(name, settings, path) {
+  if (isAbsolute(name, settings, path)) { return 'absolute' }
+  if (isBuiltIn(name, settings, path)) { return 'builtin' }
+  if (isInternalModule(name, settings, path)) { return 'internal' }
+  if (isExternalModule(name, settings, path)) { return 'external' }
+  if (isScoped(name, settings, path)) { return 'external' }
+  if (isRelativeToParent(name, settings, path)) { return 'parent' }
+  if (isIndex(name, settings, path)) { return 'index' }
+  if (isRelativeToSibling(name, settings, path)) { return 'sibling' }
+  return 'unknown'
+}
 
 export default function resolveImportType(name, context) {
   return typeTest(name, context.settings, resolve(name, context))

From 8a38fd4a834d116467e47149946688e91fda73ae Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 16 Jul 2019 23:15:34 -0700
Subject: [PATCH 003/767] [Refactor] `no-extraneous-dependencies`: use
 `Array.isArray` instead of lodash

---
 src/rules/no-extraneous-dependencies.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index d2c7cac6ee..d055bcc536 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -1,6 +1,6 @@
 import path from 'path'
 import fs from 'fs'
-import { isArray, isEmpty } from 'lodash'
+import { isEmpty } from 'lodash'
 import readPkgUp from 'read-pkg-up'
 import minimatch from 'minimatch'
 import resolve from 'eslint-module-utils/resolve'
@@ -32,7 +32,7 @@ function getDependencies(context, packageDir) {
     }
 
     if (!isEmpty(packageDir)) {
-      if (!isArray(packageDir)) {
+      if (!Array.isArray(packageDir)) {
         paths = [path.resolve(packageDir)]
       } else {
         paths = packageDir.map(dir => path.resolve(dir))

From d3a3fa5bf747659a07b659d75c6b1d3943bc8b76 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 16 Jul 2019 23:19:33 -0700
Subject: [PATCH 004/767] [Refactor] `no-extraneous-dependencies`: remove the
 last bit of lodash

Using `.length` is clearer than a polymorphic `isEmpty`.
---
 package.json                            | 1 -
 src/rules/no-extraneous-dependencies.js | 7 +++----
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index 7a25c7363f..f7989b2d7a 100644
--- a/package.json
+++ b/package.json
@@ -87,7 +87,6 @@
     "eslint-import-resolver-node": "^0.3.2",
     "eslint-module-utils": "^2.4.0",
     "has": "^1.0.3",
-    "lodash": "^4.17.11",
     "minimatch": "^3.0.4",
     "read-pkg-up": "^2.0.0",
     "resolve": "^1.11.0"
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index d055bcc536..647481a374 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -1,6 +1,5 @@
 import path from 'path'
 import fs from 'fs'
-import { isEmpty } from 'lodash'
 import readPkgUp from 'read-pkg-up'
 import minimatch from 'minimatch'
 import resolve from 'eslint-module-utils/resolve'
@@ -31,7 +30,7 @@ function getDependencies(context, packageDir) {
       peerDependencies: {},
     }
 
-    if (!isEmpty(packageDir)) {
+    if (packageDir && packageDir.length > 0) {
       if (!Array.isArray(packageDir)) {
         paths = [path.resolve(packageDir)]
       } else {
@@ -39,7 +38,7 @@ function getDependencies(context, packageDir) {
       }
     }
 
-    if (!isEmpty(paths)) {
+    if (paths.length > 0) {
       // use rule config to find package.json
       paths.forEach(dir => {
         const _packageContent = extractDepFields(
@@ -70,7 +69,7 @@ function getDependencies(context, packageDir) {
 
     return packageContent
   } catch (e) {
-    if (!isEmpty(paths) && e.code === 'ENOENT') {
+    if (paths.length > 0 && e.code === 'ENOENT') {
       context.report({
         message: 'The package.json file could not be found.',
         loc: { line: 0, column: 0 },

From 752dcd5954ec41a9754c01344bd9c573d676455a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 16 Jul 2019 23:46:20 -0700
Subject: [PATCH 005/767] [Tests] add missing `--no-save` to time travel script

---
 tests/dep-time-travel.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index fcd3cda1dc..996ed0b1cf 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -7,7 +7,7 @@ npm install --no-save eslint@$ESLINT_VERSION --ignore-scripts || true
 # completely remove the new typescript parser for ESLint < v5
 if [[ "$ESLINT_VERSION" -lt "5" ]]; then
   echo "Removing @typescript-eslint/parser..."
-  npm uninstall @typescript-eslint/parser
+  npm uninstall --no-save @typescript-eslint/parser
 fi
 
 # use these alternate typescript dependencies for ESLint < v4

From 5abd5edf20f7e3c2e3531de6547d31701bb3fcff Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 17 Jul 2019 11:36:29 -0700
Subject: [PATCH 006/767] [Tests] temporarily disable these failing tests in
 eslint < 4

---
 tests/src/rules/no-amd.js      | 12 +++++++-----
 tests/src/rules/no-commonjs.js | 10 +++++++---
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/tests/src/rules/no-amd.js b/tests/src/rules/no-amd.js
index d67739f716..62de5ac26a 100644
--- a/tests/src/rules/no-amd.js
+++ b/tests/src/rules/no-amd.js
@@ -1,4 +1,6 @@
 import { RuleTester } from 'eslint'
+import eslintPkg from 'eslint/package.json'
+import semver from 'semver'
 
 var ruleTester = new RuleTester()
 
@@ -25,11 +27,11 @@ ruleTester.run('no-amd', require('rules/no-amd'), {
     'define("a")',
 	],
 
-	invalid: [
-    { code: 'define([], function() {})', errors: [ { message: 'Expected imports instead of AMD define().' }] },
-    { code: 'define(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD define().' }] },
+	invalid: semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
+      { code: 'define([], function() {})', errors: [ { message: 'Expected imports instead of AMD define().' }] },
+      { code: 'define(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD define().' }] },
 
-		{ code: 'require([], function() {})', errors: [ { message: 'Expected imports instead of AMD require().' }] },
-		{ code: 'require(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD require().' }] },
+      { code: 'require([], function() {})', errors: [ { message: 'Expected imports instead of AMD require().' }] },
+      { code: 'require(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD require().' }] },
 	],
 })
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index ae0377f4a1..8ca8fde509 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -1,4 +1,6 @@
 import { RuleTester } from 'eslint'
+import eslintPkg from 'eslint/package.json'
+import semver from 'semver'
 
 const EXPORT_MESSAGE = 'Expected "export" or "export default"'
     , IMPORT_MESSAGE = 'Expected "import" instead of "require()"'
@@ -59,9 +61,11 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
   invalid: [
 
     // imports
-    { code: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
-    { code: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
-    { code: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+    ...(semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
+      { code: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+      { code: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+      { code: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+    ]),
 
     // exports
     { code: 'exports.face = "palm"', errors: [ { message: EXPORT_MESSAGE }] },

From 22d54409f49fe1855546410c9d130f56079ea89e Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Fri, 12 Jul 2019 21:10:54 +0800
Subject: [PATCH 007/767] [fix] `export`: false positive for typescript
 overloads

Fixes #1357.
---
 src/rules/export.js       | 17 +++++++++++++++++
 tests/src/rules/export.js | 10 +++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/src/rules/export.js b/src/rules/export.js
index caa28e119f..a9fba849e0 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -24,6 +24,21 @@ ambient namespaces:
 const rootProgram = 'root'
 const tsTypePrefix = 'type:'
 
+/**
+ * Detect function overloads like:
+ * ```ts
+ * export function foo(a: number);
+ * export function foo(a: string);
+ * export function foo(a: number|string) { return a; }
+ * ```
+ * @param {Set<Object>} nodes
+ * @returns {boolean}
+ */
+function isTypescriptFunctionOverloads(nodes) {
+  const types = new Set(Array.from(nodes, node => node.parent.type))
+  return types.size === 2 && types.has('TSDeclareFunction') && types.has('FunctionDeclaration')
+}
+
 module.exports = {
   meta: {
     type: 'problem',
@@ -123,6 +138,8 @@ module.exports = {
           for (let [name, nodes] of named) {
             if (nodes.size <= 1) continue
 
+            if (isTypescriptFunctionOverloads(nodes)) continue
+
             for (let node of nodes) {
               if (name === 'default') {
                 context.report(node, 'Multiple default exports.')
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 5ca7f458c3..13899dbd72 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -118,7 +118,7 @@ context('Typescript', function () {
     parsers.push(require.resolve('@typescript-eslint/parser'))
   }
 
-  if (semver.satisfies(eslintPkg.version, '<6.0.0')) {
+  if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
     parsers.push(require.resolve('typescript-eslint-parser'))
   }
 
@@ -147,6 +147,14 @@ context('Typescript', function () {
           `,
         }, parserConfig)),
 
+        test(Object.assign({
+          code: `
+            export function fff(a: string);
+            export function fff(a: number);
+            export function fff(a: string|number) {};
+          `,
+        }, parserConfig)),
+
         // namespace
         test(Object.assign({
           code: `

From 1caa402f47b4080051a8d761b9daf2f1a290e9bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Fermann?= <rene.fermann@gmx.de>
Date: Tue, 2 Jul 2019 11:43:43 +0200
Subject: [PATCH 008/767] [Fix] `no-unused-modules`: Exclude package
 "main"/"bin"/"browser" entry points

Fixes #1327.
---
 docs/rules/no-unused-modules.md               |  3 +-
 package.json                                  |  1 +
 src/rules/no-unused-modules.js                | 74 +++++++++++++++++--
 tests/files/no-unused-modules/bin.js          |  1 +
 .../no-unused-modules/binObject/index.js      |  1 +
 .../no-unused-modules/binObject/package.json  |  6 ++
 tests/files/no-unused-modules/browser.js      |  1 +
 .../no-unused-modules/browserObject/index.js  |  1 +
 .../browserObject/package.json                |  5 ++
 tests/files/no-unused-modules/main/index.js   |  1 +
 tests/files/no-unused-modules/package.json    |  5 ++
 .../no-unused-modules/privatePkg/index.js     |  1 +
 .../no-unused-modules/privatePkg/package.json |  4 +
 tests/src/rules/no-unused-modules.js          | 30 +++++++-
 14 files changed, 125 insertions(+), 9 deletions(-)
 create mode 100644 tests/files/no-unused-modules/bin.js
 create mode 100644 tests/files/no-unused-modules/binObject/index.js
 create mode 100644 tests/files/no-unused-modules/binObject/package.json
 create mode 100644 tests/files/no-unused-modules/browser.js
 create mode 100644 tests/files/no-unused-modules/browserObject/index.js
 create mode 100644 tests/files/no-unused-modules/browserObject/package.json
 create mode 100644 tests/files/no-unused-modules/main/index.js
 create mode 100644 tests/files/no-unused-modules/package.json
 create mode 100644 tests/files/no-unused-modules/privatePkg/index.js
 create mode 100644 tests/files/no-unused-modules/privatePkg/package.json

diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index 32db6465fc..4302bc8458 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -105,7 +105,8 @@ export function doAnything() {
 export default 5 // will not be reported
 ```
 
-
+#### Important Note
+Exports from files listed as a main file (`main`, `browser`, or `bin` fields in `package.json`) will be ignored by default. This only applies if the `package.json` is not set to `private: true`
 
 ## When not to use
 
diff --git a/package.json b/package.json
index f7989b2d7a..488a441a1b 100644
--- a/package.json
+++ b/package.json
@@ -88,6 +88,7 @@
     "eslint-module-utils": "^2.4.0",
     "has": "^1.0.3",
     "minimatch": "^3.0.4",
+    "object.values": "^1.1.0",
     "read-pkg-up": "^2.0.0",
     "resolve": "^1.11.0"
   },
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 16130d47d5..47cd11c0df 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -7,6 +7,10 @@
 import Exports from '../ExportMap'
 import resolve from 'eslint-module-utils/resolve'
 import docsUrl from '../docsUrl'
+import { dirname, join } from 'path'
+import readPkgUp from 'read-pkg-up'
+import values from 'object.values'
+import includes from 'array-includes'
 
 // eslint/lib/util/glob-util has been moved to eslint/lib/util/glob-utils with version 5.3
 // and has been moved to eslint/lib/cli-engine/file-enumerator in version 6
@@ -80,7 +84,7 @@ const prepareImportsAndExports = (srcFiles, context) => {
     if (currentExports) {
       const { dependencies, reexports, imports: localImportList, namespace  } = currentExports
 
-      // dependencies === export * from 
+      // dependencies === export * from
       const currentExportAll = new Set()
       dependencies.forEach(value => {
         currentExportAll.add(value().path)
@@ -146,7 +150,7 @@ const prepareImportsAndExports = (srcFiles, context) => {
 }
 
 /**
- * traverse through all imports and add the respective path to the whereUsed-list 
+ * traverse through all imports and add the respective path to the whereUsed-list
  * of the corresponding export
  */
 const determineUsage = () => {
@@ -201,6 +205,58 @@ const newNamespaceImportExists = specifiers =>
 const newDefaultImportExists = specifiers =>
   specifiers.some(({ type }) => type === IMPORT_DEFAULT_SPECIFIER)
 
+const fileIsInPkg = file => {
+  const { path, pkg } = readPkgUp.sync({cwd: file, normalize: false})
+  const basePath = dirname(path)
+
+  const checkPkgFieldString = pkgField => {
+    if (join(basePath, pkgField) === file) {
+        return true
+      }
+  }
+
+  const checkPkgFieldObject = pkgField => {
+      const pkgFieldFiles = values(pkgField).map(value => join(basePath, value))
+      if (includes(pkgFieldFiles, file)) {
+        return true
+      }
+  }
+
+  const checkPkgField = pkgField => {
+    if (typeof pkgField === 'string') {
+      return checkPkgFieldString(pkgField)
+    }
+
+    if (typeof pkgField === 'object') {
+      return checkPkgFieldObject(pkgField)
+    }
+  }
+
+  if (pkg.private === true) {
+    return false
+  }
+
+  if (pkg.bin) {
+    if (checkPkgField(pkg.bin)) {
+      return true
+    }
+  }
+
+  if (pkg.browser) {
+    if (checkPkgField(pkg.browser)) {
+      return true
+    }
+  }
+
+  if (pkg.main) {
+    if (checkPkgFieldString(pkg.main)) {
+      return true
+    }
+  }
+
+  return false
+}
+
 module.exports = {
   meta: {
     docs: { url: docsUrl('no-unused-modules') },
@@ -315,6 +371,10 @@ module.exports = {
         return
       }
 
+      if (fileIsInPkg(file)) {
+        return
+      }
+
       // refresh list of source files
       const srcFiles = resolveFiles(getSrc(src), ignoreExports)
 
@@ -325,7 +385,7 @@ module.exports = {
 
       exports = exportList.get(file)
 
-      // special case: export * from 
+      // special case: export * from
       const exportAll = exports.get(EXPORT_ALL_DECLARATION)
       if (typeof exportAll !== 'undefined' && exportedValue !== IMPORT_DEFAULT_SPECIFIER) {
         if (exportAll.whereUsed.size > 0) {
@@ -362,7 +422,7 @@ module.exports = {
 
     /**
      * only useful for tools like vscode-eslint
-     * 
+     *
      * update lists of existing exports during runtime
      */
     const updateExportUsage = node => {
@@ -384,7 +444,7 @@ module.exports = {
       node.body.forEach(({ type, declaration, specifiers }) => {
         if (type === EXPORT_DEFAULT_DECLARATION) {
           newExportIdentifiers.add(IMPORT_DEFAULT_SPECIFIER)
-        } 
+        }
         if (type === EXPORT_NAMED_DECLARATION) {
           if (specifiers.length > 0) {
             specifiers.forEach(specifier => {
@@ -399,7 +459,7 @@ module.exports = {
               declaration.type === CLASS_DECLARATION
             ) {
               newExportIdentifiers.add(declaration.id.name)
-            }   
+            }
             if (declaration.type === VARIABLE_DECLARATION) {
               declaration.declarations.forEach(({ id }) => {
                 newExportIdentifiers.add(id.name)
@@ -438,7 +498,7 @@ module.exports = {
 
     /**
      * only useful for tools like vscode-eslint
-     * 
+     *
      * update lists of existing imports during runtime
      */
     const updateImportUsage = node => {
diff --git a/tests/files/no-unused-modules/bin.js b/tests/files/no-unused-modules/bin.js
new file mode 100644
index 0000000000..c755d14027
--- /dev/null
+++ b/tests/files/no-unused-modules/bin.js
@@ -0,0 +1 @@
+export const bin = 'bin'
diff --git a/tests/files/no-unused-modules/binObject/index.js b/tests/files/no-unused-modules/binObject/index.js
new file mode 100644
index 0000000000..53cc33821f
--- /dev/null
+++ b/tests/files/no-unused-modules/binObject/index.js
@@ -0,0 +1 @@
+export const binObject = 'binObject'
diff --git a/tests/files/no-unused-modules/binObject/package.json b/tests/files/no-unused-modules/binObject/package.json
new file mode 100644
index 0000000000..fa9c85326d
--- /dev/null
+++ b/tests/files/no-unused-modules/binObject/package.json
@@ -0,0 +1,6 @@
+{
+  "bin": {
+    "binObject": "./index.js"
+  },
+  "private": false
+}
diff --git a/tests/files/no-unused-modules/browser.js b/tests/files/no-unused-modules/browser.js
new file mode 100644
index 0000000000..daad8d2942
--- /dev/null
+++ b/tests/files/no-unused-modules/browser.js
@@ -0,0 +1 @@
+export const browser = 'browser'
diff --git a/tests/files/no-unused-modules/browserObject/index.js b/tests/files/no-unused-modules/browserObject/index.js
new file mode 100644
index 0000000000..92d09f8f11
--- /dev/null
+++ b/tests/files/no-unused-modules/browserObject/index.js
@@ -0,0 +1 @@
+export const browserObject = 'browserObject'
diff --git a/tests/files/no-unused-modules/browserObject/package.json b/tests/files/no-unused-modules/browserObject/package.json
new file mode 100644
index 0000000000..28272c6fef
--- /dev/null
+++ b/tests/files/no-unused-modules/browserObject/package.json
@@ -0,0 +1,5 @@
+{
+  "browser": {
+    "browserObject": "./index.js"
+  }
+}
diff --git a/tests/files/no-unused-modules/main/index.js b/tests/files/no-unused-modules/main/index.js
new file mode 100644
index 0000000000..9eb0aade18
--- /dev/null
+++ b/tests/files/no-unused-modules/main/index.js
@@ -0,0 +1 @@
+export const main = 'main'
diff --git a/tests/files/no-unused-modules/package.json b/tests/files/no-unused-modules/package.json
new file mode 100644
index 0000000000..5aae42b811
--- /dev/null
+++ b/tests/files/no-unused-modules/package.json
@@ -0,0 +1,5 @@
+{
+  "bin": "./bin.js",
+  "browser": "./browser.js",
+  "main": "./main/index.js"
+}
diff --git a/tests/files/no-unused-modules/privatePkg/index.js b/tests/files/no-unused-modules/privatePkg/index.js
new file mode 100644
index 0000000000..c936cd4930
--- /dev/null
+++ b/tests/files/no-unused-modules/privatePkg/index.js
@@ -0,0 +1 @@
+export const privatePkg = 'privatePkg'
diff --git a/tests/files/no-unused-modules/privatePkg/package.json b/tests/files/no-unused-modules/privatePkg/package.json
new file mode 100644
index 0000000000..618c66d18c
--- /dev/null
+++ b/tests/files/no-unused-modules/privatePkg/package.json
@@ -0,0 +1,4 @@
+{
+  "main": "./index.js",
+  "private": true
+}
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index cefa6ff214..8050b56935 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -610,4 +610,32 @@ ruleTester.run('no-unused-modules', rule, {
             filename: testFilePath('../jsx/named.jsx')}),
   ],
   invalid: [],
-})
\ No newline at end of file
+})
+
+describe('do not report unused export for files mentioned in package.json', () => {
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({ options: unusedExportsOptions,
+             code: 'export const bin = "bin"',
+             filename: testFilePath('./no-unused-modules/bin.js')}),
+      test({ options: unusedExportsOptions,
+             code: 'export const binObject = "binObject"',
+             filename: testFilePath('./no-unused-modules/binObject/index.js')}),
+      test({ options: unusedExportsOptions,
+             code: 'export const browser = "browser"',
+             filename: testFilePath('./no-unused-modules/browser.js')}),
+      test({ options: unusedExportsOptions,
+             code: 'export const browserObject = "browserObject"',
+             filename: testFilePath('./no-unused-modules/browserObject/index.js')}),
+      test({ options: unusedExportsOptions,
+             code: 'export const main = "main"',
+             filename: testFilePath('./no-unused-modules/main/index.js')}),
+    ],
+    invalid: [
+      test({ options: unusedExportsOptions,
+             code: 'export const privatePkg = "privatePkg"',
+             filename: testFilePath('./no-unused-modules/privatePkg/index.js'),
+             errors: [error(`exported declaration 'privatePkg' not used within other modules`)]}),
+    ],
+  })
+})

From f4e3f1b3db2aa33cf3211ff64e46d696a324485a Mon Sep 17 00:00:00 2001
From: Sharmila <sharmila.jesupaul@airbnb.com>
Date: Wed, 17 Jul 2019 10:47:23 -0700
Subject: [PATCH 009/767] prefer-default-export: don't warn on TypeAlias &
 TSTypeAliasDeclaration

Fixes #1332.
---
 src/rules/prefer-default-export.js       |  9 +++-
 tests/src/rules/prefer-default-export.js | 67 +++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 0e31346f3b..01b8d8be02 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -47,9 +47,16 @@ module.exports = {
         // if there are specifiers, node.declaration should be null
         if (!node.declaration) return
 
-        // don't count flow types exports
+        // don't warn on single type aliases or declarations
         if (node.exportKind === 'type') return
 
+        if (
+          node.declaration.type === 'TSTypeAliasDeclaration' ||
+          node.declaration.type === 'TypeAlias'
+        ) {
+          return
+        }
+
         if (node.declaration.declarations) {
           node.declaration.declarations.forEach(function(declaration) {
             captureDeclaration(declaration.id)
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 1d670a02fe..55e739d98d 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -1,6 +1,8 @@
 import { test } from '../utils'
 
 import { RuleTester } from 'eslint'
+import eslintPkg from 'eslint/package.json'
+import semver from 'semver'
 
 const ruleTester = new RuleTester()
     , rule = require('rules/prefer-default-export')
@@ -83,7 +85,6 @@ ruleTester.run('prefer-default-export', rule, {
       code: 'export { a, b } from "foo.js"',
       parser: require.resolve('babel-eslint'),
     }),
-
     // ...SYNTAX_CASES,
   ],
   invalid: [
@@ -129,4 +130,66 @@ ruleTester.run('prefer-default-export', rule, {
       }],
     }),
   ],
-})
+});
+
+context('Typescript', function() {
+  // Typescript
+  const parsers = [require.resolve('babel-eslint')];
+
+  if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
+    parsers.push(require.resolve('typescript-eslint-parser'));
+  }
+
+  if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
+    parsers.push(require.resolve('@typescript-eslint/parser'));
+  }
+
+  parsers.forEach((parser) => {
+    const parserConfig = {
+      parser: parser,
+      settings: {
+        'import/parsers': { [parser]: ['.ts'] },
+        'import/resolver': { 'eslint-import-resolver-typescript': true },
+      },
+    };
+
+    ruleTester.run('prefer-default-export', rule, {
+      valid: [
+        // Exporting types
+        test(
+          {
+            code: `
+        export type foo = string;
+        export type bar = number;`,
+            parser,
+          },
+          parserConfig,
+        ),
+        test(
+          {
+            code: `
+        export type foo = string;
+        export type bar = number;`,
+            parser,
+          },
+          parserConfig,
+        ),
+        test(
+          {
+            code: 'export type foo = string',
+            parser,
+          },
+          parserConfig,
+        ),
+        test(
+          {
+            code: 'export type foo = string',
+            parser,
+          },
+          parserConfig,
+        ),
+      ],
+      invalid: [],
+    });
+  });
+});

From 3b21de6b36d4725d87d0a2b2b459d9541daefedf Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 18 Jul 2019 19:03:41 -0700
Subject: [PATCH 010/767] [Tests] extract common "get parser" logic into test
 helpers

---
 tests/src/rules/export.js                | 17 ++---------------
 tests/src/rules/named.js                 | 17 ++---------------
 tests/src/rules/no-deprecated.js         | 19 ++-----------------
 tests/src/rules/order.js                 | 23 +++--------------------
 tests/src/rules/prefer-default-export.js | 17 ++---------------
 tests/src/utils.js                       | 16 ++++++++++++++++
 6 files changed, 27 insertions(+), 82 deletions(-)

diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 13899dbd72..a858250e2b 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -1,8 +1,6 @@
-import { test, SYNTAX_CASES } from '../utils'
+import { test, SYNTAX_CASES, getTSParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
 
 var ruleTester = new RuleTester()
   , rule = require('rules/export')
@@ -111,18 +109,7 @@ ruleTester.run('export', rule, {
 
 
 context('Typescript', function () {
-  // Typescript
-  const parsers = []
-
-  if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-    parsers.push(require.resolve('@typescript-eslint/parser'))
-  }
-
-  if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
-    parsers.push(require.resolve('typescript-eslint-parser'))
-  }
-
-  parsers.forEach((parser) => {
+  getTSParsers().forEach((parser) => {
     const parserConfig = {
       parser: parser,
       settings: {
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 90e9c8b9b5..ec8a1dbecd 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -1,7 +1,5 @@
-import { test, SYNTAX_CASES } from '../utils'
+import { test, SYNTAX_CASES, getTSParsers } from '../utils'
 import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve'
 
@@ -285,18 +283,7 @@ ruleTester.run('named (export *)', rule, {
 
 
 context('Typescript', function () {
-  // Typescript
-  const parsers = []
-
-  if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-    parsers.push(require.resolve('@typescript-eslint/parser'))
-  }
-
-  if (semver.satisfies(eslintPkg.version, '<6.0.0')) {
-    parsers.push(require.resolve('typescript-eslint-parser'))
-  }
-
-  parsers.forEach((parser) => {
+  getTSParsers().forEach((parser) => {
     ['typescript', 'typescript-declare', 'typescript-export-assign'].forEach((source) => {
       ruleTester.run(`named`, rule, {
         valid: [
diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index eb08d412e6..28b8734f7e 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -1,9 +1,6 @@
-import { test, SYNTAX_CASES } from '../utils'
+import { test, SYNTAX_CASES, getTSParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
-
 
 const ruleTester = new RuleTester()
     , rule = require('rules/no-deprecated')
@@ -202,19 +199,7 @@ ruleTester.run('no-deprecated: hoisting', rule, {
 })
 
 describe('Typescript', function () {
-  // Typescript
-  const parsers = []
-
-  if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-    parsers.push(require.resolve('@typescript-eslint/parser'))
-  }
-
-  // typescript-eslint-parser doesn't support this rule on ESLint <4 for some reason
-  if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
-    parsers.push(require.resolve('typescript-eslint-parser'))
-  }
-
-  parsers.forEach((parser) => {
+  getTSParsers().forEach((parser) => {
     const parserConfig = {
       parser: parser,
       settings: {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 04236420c1..426c40a104 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,4 +1,4 @@
-import { test, testVersion } from '../utils'
+import { test, testVersion, getTSParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
 
@@ -1372,8 +1372,7 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     })),
-    // fix incorrect order with typescript-eslint-parser
-    testVersion('<6.0.0', () => ({
+    ...getTSParsers().map(parser => ({
       code: `
         var async = require('async');
         var fs = require('fs');
@@ -1382,23 +1381,7 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
         var async = require('async');
       `,
-      parser: require.resolve('typescript-eslint-parser'),
-      errors: [{
-        ruleId: 'order',
-        message: '`fs` import should occur before import of `async`',
-      }],
-    })),
-    // fix incorrect order with @typescript-eslint/parser
-    testVersion('>5.0.0', () => ({
-      code: `
-        var async = require('async');
-        var fs = require('fs');
-      `,
-      output: `
-        var fs = require('fs');
-        var async = require('async');
-      `,
-      parser: require.resolve('@typescript-eslint/parser'),
+      parser,
       errors: [{
         ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 55e739d98d..5f96454633 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -1,8 +1,6 @@
-import { test } from '../utils'
+import { test, getNonDefaultParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
 
 const ruleTester = new RuleTester()
     , rule = require('rules/prefer-default-export')
@@ -133,18 +131,7 @@ ruleTester.run('prefer-default-export', rule, {
 });
 
 context('Typescript', function() {
-  // Typescript
-  const parsers = [require.resolve('babel-eslint')];
-
-  if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
-    parsers.push(require.resolve('typescript-eslint-parser'));
-  }
-
-  if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-    parsers.push(require.resolve('@typescript-eslint/parser'));
-  }
-
-  parsers.forEach((parser) => {
+  getNonDefaultParsers().forEach((parser) => {
     const parserConfig = {
       parser: parser,
       settings: {
diff --git a/tests/src/utils.js b/tests/src/utils.js
index 9d71ad84ac..9e0c4a1e05 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -9,6 +9,22 @@ export function testFilePath(relativePath) {
   return path.join(process.cwd(), './tests/files', relativePath)
 }
 
+export function getTSParsers() {
+  const parsers = [];
+  if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
+    parsers.push(require.resolve('typescript-eslint-parser'));
+  }
+
+  if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
+    parsers.push(require.resolve('@typescript-eslint/parser'));
+  }
+  return parsers;
+}
+
+export function getNonDefaultParsers() {
+  return getTSParsers().concat(require.resolve('babel-eslint'));
+}
+
 export const FILENAME = testFilePath('foo.js')
 
 export function testVersion(specifier, t) {

From 32704da853fb2833143fdbe616c6a52bc425568a Mon Sep 17 00:00:00 2001
From: Brad Zacher <brad.zacher@gmail.com>
Date: Mon, 8 Jul 2019 09:38:38 -0700
Subject: [PATCH 011/767] fix: Improve parse perf when using
 `@typescript-eslint/parser`

Fixes #1408
See the above issue for justification.
---
 utils/parse.js | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/utils/parse.js b/utils/parse.js
index 2946047ad5..99e5a9334e 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -31,7 +31,14 @@ exports.default = function parse(path, content, context) {
   // provide the `filePath` like eslint itself does, in `parserOptions`
   // https://github.com/eslint/eslint/blob/3ec436ee/lib/linter.js#L637
   parserOptions.filePath = path
-
+  
+  // @typescript-eslint/parser will parse the entire project with typechecking if you provide
+  // "project" or "projects" in parserOptions. Removing these options means the parser will
+  // only parse one file in isolate mode, which is much, much faster.
+  // https://github.com/benmosher/eslint-plugin-import/issues/1408#issuecomment-509298962
+  delete parserOptions.project;
+  delete parserOptions.projects;
+  
   // require the parser relative to the main module (i.e., ESLint)
   const parser = moduleRequire(parserPath)
 

From b51aa2f7214dd8409ec9664e5df45e54444e4dbf Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 18 Jul 2019 23:16:55 -0700
Subject: [PATCH 012/767] Bump to v2.18.1

---
 CHANGELOG.md | 18 +++++++++++++++++-
 package.json |  2 +-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a5c4623ee3..aebca00e47 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,16 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.18.1] - 2019-07-18
+
+### Fixed
+ - Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
+ - [`prefer-default-export`]: don't warn on TypeAlias & TSTypeAliasDeclaration ([#1377], thanks [@sharmilajesupaul])
+ - [`no-unused-modules`]: Exclude package "main"/"bin"/"browser" entry points ([#1404], thanks [@rfermann])
+ - [`export`]: false positive for typescript overloads ([#1412], thanks [@golopot])
+
+### Refactors
+ - [`no-extraneous-dependencies`], `importType`: remove lodash ([#1419], thanks [@ljharb])
 
 ## [2.18.0] - 2019-06-24
 
@@ -14,7 +24,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]: add fixer for destructuring commonjs import ([#1372], thanks [@golopot])
 - typescript config: add TS def extensions + defer to TS over JS ([#1366], thanks [@benmosher])
 
-### Fixes
+### Fixed
 - [`no-unused-modules`]: handle ClassDeclaration ([#1371], thanks [@golopot])
 
 ### Docs
@@ -586,8 +596,13 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1419]: https://github.com/benmosher/eslint-plugin-import/pull/1419
+[#1412]: https://github.com/benmosher/eslint-plugin-import/pull/1412
+[#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
+[#1404]: https://github.com/benmosher/eslint-plugin-import/pull/1404
 [#1393]: https://github.com/benmosher/eslint-plugin-import/pull/1393
 [#1389]: https://github.com/benmosher/eslint-plugin-import/pull/1389
+[#1377]: https://github.com/benmosher/eslint-plugin-import/pull/1377
 [#1375]: https://github.com/benmosher/eslint-plugin-import/pull/1375
 [#1372]: https://github.com/benmosher/eslint-plugin-import/pull/1372
 [#1371]: https://github.com/benmosher/eslint-plugin-import/pull/1371
@@ -950,3 +965,4 @@ for info on changes for earlier releases.
 [@benmosher]: https://github.com/benmosher
 [@fooloomanzoo]: https://github.com/fooloomanzoo
 [@sheepsteak]: https://github.com/sheepsteak
+[@sharmilajesupaul]: https://github.com/sharmilajesupaul
diff --git a/package.json b/package.json
index 488a441a1b..873a387a13 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.18.0",
+  "version": "2.18.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 582236be6fd8ff7d7734be50466737190d2190f9 Mon Sep 17 00:00:00 2001
From: Joe Lencioni <joe.lencioni@airbnb.com>
Date: Fri, 19 Jul 2019 10:55:27 -0700
Subject: [PATCH 013/767] [bugfix] Skip warning on type interfaces

Similar to https://github.com/benmosher/eslint-plugin-import/pull/1377,
we don't want this rule to apply to exported interfaces.
---
 src/rules/prefer-default-export.js       | 10 +++++++---
 tests/src/rules/prefer-default-export.js |  7 +++++++
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 01b8d8be02..59c26d11ee 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -47,12 +47,16 @@ module.exports = {
         // if there are specifiers, node.declaration should be null
         if (!node.declaration) return
 
-        // don't warn on single type aliases or declarations
+        // don't warn on single type aliases, declarations, or interfaces
         if (node.exportKind === 'type') return
 
+        const { type } = node.declaration
+
         if (
-          node.declaration.type === 'TSTypeAliasDeclaration' ||
-          node.declaration.type === 'TypeAlias'
+          type === 'TSTypeAliasDeclaration' ||
+          type === 'TypeAlias' ||
+          type === 'TSInterfaceDeclaration' ||
+          type === 'InterfaceDeclaration'
         ) {
           return
         }
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 5f96454633..ae630b4476 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -175,6 +175,13 @@ context('Typescript', function() {
           },
           parserConfig,
         ),
+        test (
+          {
+            code: 'export interface foo { bar: string; }',
+            parser,
+          },
+          parserConfig,
+        ),
       ],
       invalid: [],
     });

From 984fa3b270dc87f58c91f4839084eefdf3fc284e Mon Sep 17 00:00:00 2001
From: Joe Lencioni <joe.lencioni@airbnb.com>
Date: Mon, 8 Jul 2019 12:36:22 -0700
Subject: [PATCH 014/767] Remove duplicate no-duplicates changelog entry

---
 CHANGELOG.md | 1 -
 1 file changed, 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index aebca00e47..decf05dacb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -62,7 +62,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [2.17.0] - 2019-04-13
 
 ### Added
-- Autofixer for [`no-duplicates`] rule ([#1312], thanks [@lydell])
 - [`no-useless-path-segments`]: Add `noUselessIndex` option ([#1290], thanks [@timkraut])
 - [`no-duplicates`]: Add autofix ([#1312], thanks [@lydell])
 - Add [`no-unused-modules`] rule ([#1142], thanks [@rfermann])

From b3e531109503d33e59a8bd713babc65b64f73e01 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 19 Jul 2019 14:08:10 -0700
Subject: [PATCH 015/767] bump utils to v2.4.1

---
 utils/CHANGELOG.md | 10 ++++++++++
 utils/package.json |  2 +-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 1fcaa1bff8..d0b2128edc 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,12 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v2.4.1 - 2019-07-19
+
+### Fixed
+ - Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
+ - Improve support for Typescript declare structures ([#1356], thanks [@christophercurrie])
+
 ## v2.4.0 - 2019-04-13
 
 ### Added
@@ -46,6 +52,8 @@ Yanked due to critical issue with cache key resulting from #839.
 
 
 
+[#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
+[#1356]: https://github.com/benmosher/eslint-plugin-import/pull/1356
 [#1290]: https://github.com/benmosher/eslint-plugin-import/pull/1290
 [#1218]: https://github.com/benmosher/eslint-plugin-import/pull/1218
 [#1166]: https://github.com/benmosher/eslint-plugin-import/issues/1166
@@ -55,3 +63,5 @@ Yanked due to critical issue with cache key resulting from #839.
 [@hulkish]: https://github.com/hulkish
 [@timkraut]: https://github.com/timkraut
 [@vikr01]: https://github.com/vikr01
+[@bradzacher]: https://github.com/bradzacher
+[@christophercurrie]: https://github.com/christophercurrie
diff --git a/utils/package.json b/utils/package.json
index be0c761475..eaad9b2544 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.4.0",
+  "version": "2.4.1",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From 1a90a2083b3da9e384eea7ba2f1652619896083a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 19 Jul 2019 14:10:00 -0700
Subject: [PATCH 016/767] Bump to v2.18.2

---
 CHANGELOG.md | 7 ++++++-
 package.json | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index decf05dacb..b2f76b79f9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.18.2] - 2019-07-19
+ - Skip warning on type interfaces ([#1425], thanks [@lencioni])
+
 ## [2.18.1] - 2019-07-18
 
 ### Fixed
@@ -455,7 +458,7 @@ memoizing parser, and takes only 27s with naked `babel-eslint` (thus, reparsing
   something that looks like an `export` is detected in the module content.
 
 ## [1.2.0] - 2016-03-19
-Thanks @lencioni for identifying a huge amount of rework in resolve and kicking
+Thanks [@lencioni] for identifying a huge amount of rework in resolve and kicking
 off a bunch of memoization.
 
 I'm seeing 62% improvement over my normal test codebase when executing only
@@ -595,6 +598,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1425]: https://github.com/benmosher/eslint-plugin-import/pull/1425
 [#1419]: https://github.com/benmosher/eslint-plugin-import/pull/1419
 [#1412]: https://github.com/benmosher/eslint-plugin-import/pull/1412
 [#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
@@ -965,3 +969,4 @@ for info on changes for earlier releases.
 [@fooloomanzoo]: https://github.com/fooloomanzoo
 [@sheepsteak]: https://github.com/sheepsteak
 [@sharmilajesupaul]: https://github.com/sharmilajesupaul
+[@lencioni]: https://github.com/lencioni
diff --git a/package.json b/package.json
index 873a387a13..b63f3af49c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.18.1",
+  "version": "2.18.2",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From ac14e232a8addb920041d8efb00bdd3ccde3a395 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 20 Jul 2019 08:04:29 -0700
Subject: [PATCH 017/767] [changelog] fix release compare links

---
 CHANGELOG.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b2f76b79f9..0d75cca7f9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -811,7 +811,9 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.0...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.2...HEAD
+[2.18.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.1...v2.18.2
+[2.18.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.0...v2.18.1
 [2.18.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.17.3...v2.18.0
 [2.17.3]: https://github.com/benmosher/eslint-plugin-import/compare/v2.17.2...v2.17.3
 [2.17.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.17.1...v2.17.2

From 989f6cc39a315709a9c80b9f0c515f7bf8276f4d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 20 Jul 2019 10:29:43 -0700
Subject: [PATCH 018/767] [meta] create FUNDING.yml

---
 .github/FUNDING.yml | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 .github/FUNDING.yml

diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000000..8fd7679907
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: [ljharb]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: npm/eslint-plugin-import
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

From bcd06ba6532ed7b064d00283eb7634ea112a2299 Mon Sep 17 00:00:00 2001
From: Ben Mosher <me@benmosher.com>
Date: Sat, 3 Aug 2019 08:43:02 -0400
Subject: [PATCH 019/767] Create SECURITY.md

---
 SECURITY.md | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 SECURITY.md

diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000..b155f54d59
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,11 @@
+# Security Policy
+
+## Supported Versions
+
+Latest major/minor version is supported only for security updates.
+
+## Reporting a Vulnerability
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure.

From ebcf17c531acda7ac99e98fd9b5e1ad2aeca9aad Mon Sep 17 00:00:00 2001
From: Ben Mosher <me@benmosher.com>
Date: Sat, 3 Aug 2019 08:48:05 -0400
Subject: [PATCH 020/767] add Tidelift link to README.md

---
 README.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/README.md b/README.md
index ddc95d4f81..aaa3f4c201 100644
--- a/README.md
+++ b/README.md
@@ -112,6 +112,10 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 [`no-named-export`]: ./docs/rules/no-named-export.md
 [`dynamic-import-chunkname`]: ./docs/rules/dynamic-import-chunkname.md
 
+## Support
+
+[Get supported eslint-plugin-import with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-eslint-plugin-import?utm_source=npm-eslint-plugin-import&utm_medium=referral&utm_campaign=readme)
+
 ## Installation
 
 ```sh

From 35a12f98e6b17c859f7483e46d9cde936a32a0ae Mon Sep 17 00:00:00 2001
From: JounQin <admin@1stg.me>
Date: Sat, 3 Aug 2019 15:26:39 +0800
Subject: [PATCH 021/767] [New] support `parseForESLint` from custom parser

---
 CHANGELOG.md                   | 15 ++++++++++-----
 tests/src/core/eslintParser.js |  7 +++++++
 tests/src/core/parse.js        | 11 +++++++++++
 utils/parse.js                 | 18 ++++++++++++++++++
 4 files changed, 46 insertions(+), 5 deletions(-)
 create mode 100644 tests/src/core/eslintParser.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d75cca7f9..23424cad3b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,16 +5,19 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Added
+- support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
+
 ## [2.18.2] - 2019-07-19
- - Skip warning on type interfaces ([#1425], thanks [@lencioni])
+- Skip warning on type interfaces ([#1425], thanks [@lencioni])
 
 ## [2.18.1] - 2019-07-18
 
 ### Fixed
- - Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
- - [`prefer-default-export`]: don't warn on TypeAlias & TSTypeAliasDeclaration ([#1377], thanks [@sharmilajesupaul])
- - [`no-unused-modules`]: Exclude package "main"/"bin"/"browser" entry points ([#1404], thanks [@rfermann])
- - [`export`]: false positive for typescript overloads ([#1412], thanks [@golopot])
+- Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
+- [`prefer-default-export`]: don't warn on TypeAlias & TSTypeAliasDeclaration ([#1377], thanks [@sharmilajesupaul])
+- [`no-unused-modules`]: Exclude package "main"/"bin"/"browser" entry points ([#1404], thanks [@rfermann])
+- [`export`]: false positive for typescript overloads ([#1412], thanks [@golopot])
 
 ### Refactors
  - [`no-extraneous-dependencies`], `importType`: remove lodash ([#1419], thanks [@ljharb])
@@ -598,6 +601,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
 [#1425]: https://github.com/benmosher/eslint-plugin-import/pull/1425
 [#1419]: https://github.com/benmosher/eslint-plugin-import/pull/1419
 [#1412]: https://github.com/benmosher/eslint-plugin-import/pull/1412
@@ -972,3 +976,4 @@ for info on changes for earlier releases.
 [@sheepsteak]: https://github.com/sheepsteak
 [@sharmilajesupaul]: https://github.com/sharmilajesupaul
 [@lencioni]: https://github.com/lencioni
+[@JounQin]: https://github.com/JounQin
diff --git a/tests/src/core/eslintParser.js b/tests/src/core/eslintParser.js
new file mode 100644
index 0000000000..3870ccc6e4
--- /dev/null
+++ b/tests/src/core/eslintParser.js
@@ -0,0 +1,7 @@
+module.exports = {
+  parseForESLint: function() {
+    return {
+      ast: {},
+    }
+  },
+}
diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index 4d8b5ab58c..72d232730d 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -9,6 +9,8 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
   const path = getFilename('jsx.js')
   const parseStubParser = require('./parseStubParser')
   const parseStubParserPath = require.resolve('./parseStubParser')
+  const eslintParser = require('./eslintParser')
+  const eslintParserPath = require.resolve('./eslintParser')
   let content
 
   before((done) =>
@@ -43,6 +45,15 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
     expect(parseSpy.args[0][1], 'custom parser to get parserOptions.filePath equal to the full path of the source file').to.have.property('filePath', path)
   })
 
+  it('passes with custom `parseForESLint` parser', function () {
+    const parseForESLintSpy = sinon.spy(eslintParser, 'parseForESLint')
+    const parseSpy = sinon.spy()
+    eslintParser.parse = parseSpy
+    parse(path, content, { settings: {}, parserPath: eslintParserPath })
+    expect(parseForESLintSpy.callCount, 'custom `parseForESLint` parser to be called once').to.equal(1)
+    expect(parseSpy.callCount, '`parseForESLint` takes higher priority than `parse`').to.equal(0)
+  })
+
   it('throws on context == null', function () {
     expect(parse.bind(null, path, content, null)).to.throw(Error)
   })
diff --git a/utils/parse.js b/utils/parse.js
index 99e5a9334e..9551599043 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -42,6 +42,24 @@ exports.default = function parse(path, content, context) {
   // require the parser relative to the main module (i.e., ESLint)
   const parser = moduleRequire(parserPath)
 
+  if (typeof parser.parseForESLint === 'function') {
+    let ast
+    try {
+      ast = parser.parseForESLint(content, parserOptions).ast
+    } catch (e) {
+      //
+    }
+    if (!ast || typeof ast !== 'object') {
+      console.warn(
+        '`parseForESLint` from parser `' +
+          parserPath +
+          '` is invalid and will just be ignored'
+      )
+    } else {
+      return ast
+    }
+  }
+
   return parser.parse(content, parserOptions)
 }
 

From 92b753310fa0d6d4e9d1a7af1a4cf3c874afcf0a Mon Sep 17 00:00:00 2001
From: Patrick Curry <pwfcurry@users.noreply.github.com>
Date: Wed, 7 Aug 2019 15:05:54 +0100
Subject: [PATCH 022/767] `dynamic-import-chunkname`: Fixed invalid chunk name
 pattern in docs

---
 docs/rules/dynamic-import-chunkname.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/rules/dynamic-import-chunkname.md b/docs/rules/dynamic-import-chunkname.md
index b1757b4e52..4bcc5a98b1 100644
--- a/docs/rules/dynamic-import-chunkname.md
+++ b/docs/rules/dynamic-import-chunkname.md
@@ -11,7 +11,7 @@ You can also configure the regex format you'd like to accept for the webpackChun
 {
   "dynamic-import-chunkname": [2, {
     importFunctions: ["dynamicImport"],
-    webpackChunknameFormat: "[a-zA-Z0-57-9-/_]"
+    webpackChunknameFormat: "[a-zA-Z0-57-9-/_]+"
   }]
 }
 ```

From df91bad38f73be7dcb13c38efbe3ce79d0d67f04 Mon Sep 17 00:00:00 2001
From: Ben Mosher <me@benmosher.com>
Date: Fri, 16 Aug 2019 20:03:36 -0400
Subject: [PATCH 023/767] webpack resolver Tidelift link

---
 resolvers/webpack/README.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/resolvers/webpack/README.md b/resolvers/webpack/README.md
index a9869aec44..4fc3b0ffff 100644
--- a/resolvers/webpack/README.md
+++ b/resolvers/webpack/README.md
@@ -79,3 +79,7 @@ settings:
         NODE_ENV: 'local'
         production: true
 ```
+
+## Support
+
+[Get supported eslint-import-resolver-webpack with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-eslint-import-resolver-webpack?utm_source=npm-eslint-import-resolver-webpack&utm_medium=referral&utm_campaign=readme)

From cb70c7e154984606b75d02d26a4191be4d35161c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 18 Aug 2019 21:59:10 -0700
Subject: [PATCH 024/767] [Deps] update `eslint-module-utils`, `resolve`

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index b63f3af49c..96358427dd 100644
--- a/package.json
+++ b/package.json
@@ -85,12 +85,12 @@
     "debug": "^2.6.9",
     "doctrine": "1.5.0",
     "eslint-import-resolver-node": "^0.3.2",
-    "eslint-module-utils": "^2.4.0",
+    "eslint-module-utils": "^2.4.1",
     "has": "^1.0.3",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.0",
     "read-pkg-up": "^2.0.0",
-    "resolve": "^1.11.0"
+    "resolve": "^1.12.0"
   },
   "nyc": {
     "require": [

From f235aab54ce7a5145fd8dd15e158a4988c1881c9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 18 Aug 2019 22:01:45 -0700
Subject: [PATCH 025/767] [Dev Deps] update `babylon`, `coveralls`, `rimraf`,
 `semver`

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 96358427dd..ec4efc1ee1 100644
--- a/package.json
+++ b/package.json
@@ -55,9 +55,9 @@
     "babel-plugin-istanbul": "^4.1.6",
     "babel-preset-es2015-argon": "latest",
     "babel-register": "^6.26.0",
-    "babylon": "^6.15.0",
+    "babylon": "^6.18.0",
     "chai": "^4.2.0",
-    "coveralls": "^3.0.2",
+    "coveralls": "^3.0.6",
     "cross-env": "^4.0.0",
     "eslint": "2.x - 6.x",
     "eslint-import-resolver-node": "file:./resolvers/node",
@@ -70,8 +70,8 @@
     "mocha": "^3.5.3",
     "nyc": "^11.9.0",
     "redux": "^3.7.2",
-    "rimraf": "^2.6.3",
-    "semver": "^6.0.0",
+    "rimraf": "^2.7.1",
+    "semver": "^6.3.0",
     "sinon": "^2.4.1",
     "typescript": "~3.2.2",
     "typescript-eslint-parser": "^22.0.0"

From 7ffbf03fc832df41c4e90ffd27fee43de3685224 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Fermann?= <rene.fermann@gmx.de>
Date: Thu, 8 Aug 2019 15:49:39 +0200
Subject: [PATCH 026/767] [fix] `no-unused-modules`: prevent memory overflow

Fixes #1364.
---
 src/rules/no-unused-modules.js | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 47cd11c0df..9cd7814754 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -47,6 +47,7 @@ let preparationDone = false
 const importList = new Map()
 const exportList = new Map()
 const ignoredFiles = new Set()
+const filesOutsideSrc = new Set()
 
 const isNodeModule = path => {
   return /\/(node_modules)\//.test(path)
@@ -192,8 +193,9 @@ const getSrc = src => {
  * prepare the lists of existing imports and exports - should only be executed once at
  * the start of a new eslint run
  */
+let srcFiles
 const doPreparation = (src, ignoreExports, context) => {
-  const srcFiles = resolveFiles(getSrc(src), ignoreExports)
+  srcFiles = resolveFiles(getSrc(src), ignoreExports)
   prepareImportsAndExports(srcFiles, context)
   determineUsage()
   preparationDone = true
@@ -375,12 +377,17 @@ module.exports = {
         return
       }
 
-      // refresh list of source files
-      const srcFiles = resolveFiles(getSrc(src), ignoreExports)
+      if (filesOutsideSrc.has(file)) {
+        return
+      }
 
       // make sure file to be linted is included in source files
       if (!srcFiles.has(file)) {
-        return
+        srcFiles = resolveFiles(getSrc(src), ignoreExports)
+        if (!srcFiles.has(file)) {
+          filesOutsideSrc.add(file)
+          return
+        }
       }
 
       exports = exportList.get(file)

From 726dda5e8f4e2e293dcde3c6d5633b1d845cc085 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Thu, 5 Sep 2019 00:49:20 +0800
Subject: [PATCH 027/767] [fix] `default`: make error message less confusing

Fixes #751, fixes #786
---
 CHANGELOG.md               |  4 ++++
 src/rules/default.js       | 16 +++++++---------
 tests/src/rules/default.js | 14 +++++++-------
 3 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 23424cad3b..0f91730177 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Added
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
 
+### Fixed
+- `default`: make error message less confusing ([#1470], thanks [@golopot])
+
 ## [2.18.2] - 2019-07-19
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
 
@@ -601,6 +604,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
 [#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
 [#1425]: https://github.com/benmosher/eslint-plugin-import/pull/1425
 [#1419]: https://github.com/benmosher/eslint-plugin-import/pull/1419
diff --git a/src/rules/default.js b/src/rules/default.js
index 7e07800dae..a524dcdc72 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -13,14 +13,9 @@ module.exports = {
 
     function checkDefault(specifierType, node) {
 
-      // poor man's Array.find
-      let defaultSpecifier
-      node.specifiers.some((n) => {
-        if (n.type === specifierType) {
-          defaultSpecifier = n
-          return true
-        }
-      })
+      const defaultSpecifier = node.specifiers.find(
+        specifier => specifier.type === specifierType
+      )
 
       if (!defaultSpecifier) return
       var imports = Exports.get(node.source.value, context)
@@ -29,7 +24,10 @@ module.exports = {
       if (imports.errors.length) {
         imports.reportErrors(context, node)
       } else if (imports.get('default') === undefined) {
-        context.report(defaultSpecifier, 'No default export found in module.')
+        context.report({
+          node: defaultSpecifier,
+          message: `No default export found in imported module "${node.source.value}".`,
+        })
       }
     }
 
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index c02b364489..c21f1fd8c2 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -102,7 +102,7 @@ ruleTester.run('default', rule, {
 
     test({
       code: 'import baz from "./named-exports";',
-      errors: [{ message: 'No default export found in module.'
+      errors: [{ message: 'No default export found in imported module "./named-exports".'
                , type: 'ImportDefaultSpecifier'}]}),
 
     test({
@@ -114,29 +114,29 @@ ruleTester.run('default', rule, {
     test({
       code: 'export baz from "./named-exports"',
       parser: require.resolve('babel-eslint'),
-      errors: ['No default export found in module.'],
+      errors: ['No default export found in imported module "./named-exports".'],
     }),
     test({
       code: 'export baz, { bar } from "./named-exports"',
       parser: require.resolve('babel-eslint'),
-      errors: ['No default export found in module.'],
+      errors: ['No default export found in imported module "./named-exports".'],
     }),
     test({
       code: 'export baz, * as names from "./named-exports"',
       parser: require.resolve('babel-eslint'),
-      errors: ['No default export found in module.'],
+      errors: ['No default export found in imported module "./named-exports".'],
     }),
     // exports default from a module with no default
     test({
       code: 'import twofer from "./broken-trampoline"',
       parser: require.resolve('babel-eslint'),
-      errors: ['No default export found in module.'],
+      errors: ['No default export found in imported module "./broken-trampoline".'],
     }),
 
     // #328: * exports do not include default
     test({
       code: 'import barDefault from "./re-export"',
-      errors: [`No default export found in module.`],
+      errors: ['No default export found in imported module "./re-export".'],
     }),
   ],
 })
@@ -152,7 +152,7 @@ if (!CASE_SENSITIVE_FS) {
     invalid: [
       test({
         code: 'import bar from "./Named-Exports"',
-        errors: ['No default export found in module.'],
+        errors: ['No default export found in imported module "./Named-Exports".'],
       }),
     ],
   })

From 2e047e65882e265c821822e45b31b8bf3b7e50d3 Mon Sep 17 00:00:00 2001
From: Attila Bartha <attila.bartha@babylonhealth.com>
Date: Sat, 7 Sep 2019 18:03:48 +0100
Subject: [PATCH 028/767] [New] `group-exports`: make aggregate module exports
 valid

---
 CHANGELOG.md                     |  5 +++++
 docs/rules/group-exports.md      | 12 ++++++++++++
 package.json                     |  1 +
 src/rules/group-exports.js       | 21 ++++++++++++++++++++-
 tests/src/rules/group-exports.js | 14 ++++++++++++++
 5 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f91730177..822efcebb1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Added
+- [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
+
 ### Added
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
 
@@ -604,6 +607,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
 [#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
 [#1425]: https://github.com/benmosher/eslint-plugin-import/pull/1425
@@ -981,3 +985,4 @@ for info on changes for earlier releases.
 [@sharmilajesupaul]: https://github.com/sharmilajesupaul
 [@lencioni]: https://github.com/lencioni
 [@JounQin]: https://github.com/JounQin
+[@atikenny]: https://github.com/atikenny
diff --git a/docs/rules/group-exports.md b/docs/rules/group-exports.md
index b0d88f4a05..f61ff5306b 100644
--- a/docs/rules/group-exports.md
+++ b/docs/rules/group-exports.md
@@ -26,6 +26,12 @@ export {
 }
 ```
 
+```js
+// Aggregating exports -> ok
+export { default as module1 } from 'module-1'
+export { default as module2 } from 'module-2'
+```
+
 ```js
 // A single exports assignment -> ok
 module.exports = {
@@ -63,6 +69,12 @@ export const first = true
 export const second = true
 ```
 
+```js
+// Aggregating exports from the same module -> not ok!
+export { module1 } from 'module-1'
+export { module2 } from 'module-1'
+```
+
 ```js
 // Multiple exports assignments -> not ok!
 exports.first = true
diff --git a/package.json b/package.json
index ec4efc1ee1..f395ffc0e5 100644
--- a/package.json
+++ b/package.json
@@ -81,6 +81,7 @@
   },
   "dependencies": {
     "array-includes": "^3.0.3",
+    "array.prototype.flat": "^1.2.1",
     "contains-path": "^0.1.0",
     "debug": "^2.6.9",
     "doctrine": "1.5.0",
diff --git a/src/rules/group-exports.js b/src/rules/group-exports.js
index d650fff877..cd7fc992dd 100644
--- a/src/rules/group-exports.js
+++ b/src/rules/group-exports.js
@@ -1,4 +1,6 @@
 import docsUrl from '../docsUrl'
+import values from 'object.values'
+import flat from 'array.prototype.flat'
 
 const meta = {
   type: 'suggestion',
@@ -46,11 +48,18 @@ function create(context) {
   const nodes = {
     modules: new Set(),
     commonjs: new Set(),
+    sources: {},
   }
 
   return {
     ExportNamedDeclaration(node) {
-      nodes.modules.add(node)
+      if (!node.source) {
+        nodes.modules.add(node)
+      } else if (Array.isArray(nodes.sources[node.source.value])) {
+        nodes.sources[node.source.value].push(node)
+      } else {
+        nodes.sources[node.source.value] = [node]
+      }
     },
 
     AssignmentExpression(node) {
@@ -86,6 +95,16 @@ function create(context) {
         })
       }
 
+      // Report multiple `aggregated exports` from the same module (ES2015 modules)
+      flat(values(nodes.sources)
+        .filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1))
+        .forEach((node) => {
+          context.report({
+            node,
+            message: errors[node.type],
+          })
+        })
+
       // Report multiple `module.exports` assignments (CommonJS)
       if (nodes.commonjs.size > 1) {
         nodes.commonjs.forEach(node => {
diff --git a/tests/src/rules/group-exports.js b/tests/src/rules/group-exports.js
index 3b08997e33..9a0c2c1ba7 100644
--- a/tests/src/rules/group-exports.js
+++ b/tests/src/rules/group-exports.js
@@ -45,6 +45,10 @@ ruleTester.run('group-exports', rule, {
       // test
       export default {}
     ` }),
+    test({ code: `
+      export { default as module1 } from './module-1'
+      export { default as module2 } from './module-2'
+    ` }),
     test({ code: 'module.exports = {} '}),
     test({ code: `
       module.exports = { test: true,
@@ -111,6 +115,16 @@ ruleTester.run('group-exports', rule, {
         errors.named,
       ],
     }),
+    test({
+      code: `
+        export { method1 } from './module-1'
+        export { method2 } from './module-1'
+      `,
+      errors: [
+        errors.named,
+        errors.named,
+      ],
+    }),
     test({
       code: `
         module.exports = {}

From 5edc3e6d72c6d73fd4bc0add1c6a01dc35af6055 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Sun, 15 Sep 2019 03:31:25 +0800
Subject: [PATCH 029/767] [eslint] make CI lint everything

---
 .eslintignore                             |  10 +
 config/.eslintrc.yml                      |  15 ++
 memo-parser/.eslintrc.yml                 |  15 ++
 package.json                              |   2 +-
 resolvers/.eslintrc                       |   3 -
 resolvers/.eslintrc.yml                   |  17 ++
 src/{.eslintrc => .eslintrc.yml}          |   0
 tests/.eslintrc                           |   6 -
 tests/.eslintrc.yml                       |  21 ++
 tests/files/.eslintrc                     | 290 +++++++++++++++++++++-
 tests/files/internal-modules/package.json |   1 +
 utils/.eslintrc.yml                       |  15 ++
 12 files changed, 380 insertions(+), 15 deletions(-)
 create mode 100644 .eslintignore
 create mode 100644 config/.eslintrc.yml
 create mode 100644 memo-parser/.eslintrc.yml
 delete mode 100644 resolvers/.eslintrc
 create mode 100644 resolvers/.eslintrc.yml
 rename src/{.eslintrc => .eslintrc.yml} (100%)
 delete mode 100644 tests/.eslintrc
 create mode 100644 tests/.eslintrc.yml
 create mode 100644 utils/.eslintrc.yml

diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000000..93daf655e5
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,10 @@
+lib
+coverage
+.nyc_output
+node_modules
+tests/files/malformed.js
+tests/files/with-syntax-error
+resolvers/webpack/test/files
+# we want to ignore "tests/files" here, but unfortunately doing so would
+# interfere with unit test and fail it for some reason.
+# tests/files
diff --git a/config/.eslintrc.yml b/config/.eslintrc.yml
new file mode 100644
index 0000000000..de964251c1
--- /dev/null
+++ b/config/.eslintrc.yml
@@ -0,0 +1,15 @@
+---
+rules:
+  semi: [1, 'never']
+  comma-dangle: [1, 'always-multiline']
+  no-unused-vars: 1
+  no-console: 1
+  no-extra-semi: 1
+  no-useless-escape: 1
+  quotes:
+    - 1
+    - single
+    - allowTemplateLiterals: true
+      avoidEscape: true
+  import/default: 1
+  import/no-extraneous-dependencies: 1
diff --git a/memo-parser/.eslintrc.yml b/memo-parser/.eslintrc.yml
new file mode 100644
index 0000000000..de964251c1
--- /dev/null
+++ b/memo-parser/.eslintrc.yml
@@ -0,0 +1,15 @@
+---
+rules:
+  semi: [1, 'never']
+  comma-dangle: [1, 'always-multiline']
+  no-unused-vars: 1
+  no-console: 1
+  no-extra-semi: 1
+  no-useless-escape: 1
+  quotes:
+    - 1
+    - single
+    - allowTemplateLiterals: true
+      avoidEscape: true
+  import/default: 1
+  import/no-extraneous-dependencies: 1
diff --git a/package.json b/package.json
index f395ffc0e5..cb6a1dbdbe 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
     "prebuild": "rimraf lib",
     "watch": "npm run mocha -- --watch tests/src",
     "pretest": "linklocal",
-    "posttest": "eslint ./src",
+    "posttest": "eslint .",
     "mocha": "cross-env BABEL_ENV=test NODE_PATH=./src nyc -s mocha -R dot --recursive -t 5s",
     "test": "npm run mocha tests/src",
     "test-compiled": "npm run prepublish && NODE_PATH=./lib mocha --compilers js:babel-register --recursive tests/src",
diff --git a/resolvers/.eslintrc b/resolvers/.eslintrc
deleted file mode 100644
index 9db33eda46..0000000000
--- a/resolvers/.eslintrc
+++ /dev/null
@@ -1,3 +0,0 @@
----
-env:
-  es6: false
diff --git a/resolvers/.eslintrc.yml b/resolvers/.eslintrc.yml
new file mode 100644
index 0000000000..7286ee9e56
--- /dev/null
+++ b/resolvers/.eslintrc.yml
@@ -0,0 +1,17 @@
+---
+env:
+  es6: false
+rules:
+  semi: [1, 'never']
+  comma-dangle: [1, 'always-multiline']
+  no-unused-vars: 1
+  no-console: 1
+  no-extra-semi: 1
+  no-useless-escape: 1
+  quotes:
+    - 1
+    - single
+    - allowTemplateLiterals: true
+      avoidEscape: true
+  import/default: 1
+  import/no-extraneous-dependencies: 1
diff --git a/src/.eslintrc b/src/.eslintrc.yml
similarity index 100%
rename from src/.eslintrc
rename to src/.eslintrc.yml
diff --git a/tests/.eslintrc b/tests/.eslintrc
deleted file mode 100644
index 700a3d6883..0000000000
--- a/tests/.eslintrc
+++ /dev/null
@@ -1,6 +0,0 @@
----
-env:
-  mocha: true
-rules:
-  no-unused-expressions: 0
-  max-len: 0
diff --git a/tests/.eslintrc.yml b/tests/.eslintrc.yml
new file mode 100644
index 0000000000..5a6bc6813d
--- /dev/null
+++ b/tests/.eslintrc.yml
@@ -0,0 +1,21 @@
+---
+parserOptions:
+  ecmaVersion: 8
+env:
+  mocha: true
+rules:
+  no-unused-expressions: 0
+  max-len: 0
+  semi: [1, 'never']
+  comma-dangle: [1, 'always-multiline']
+  no-unused-vars: 1
+  no-console: 1
+  no-extra-semi: 1
+  no-useless-escape: 1
+  quotes:
+    - 1
+    - single
+    - allowTemplateLiterals: true
+      avoidEscape: true
+  import/default: 1
+  import/no-extraneous-dependencies: 1
diff --git a/tests/files/.eslintrc b/tests/files/.eslintrc
index 5970c5fa16..6d36c133b3 100644
--- a/tests/files/.eslintrc
+++ b/tests/files/.eslintrc
@@ -1,5 +1,285 @@
----
-parser: 'babel-eslint'
-parserOptions:
-  ecmaFeatures:
-    jsx: true
+{
+  "parser": "babel-eslint",
+  "parserOptions": {
+    "sourceType": "module",
+    "ecmaVersion": 8
+  },
+  "rules": {
+    "accessor-pairs": 0,
+    "array-bracket-newline": 0,
+    "array-bracket-spacing": 0,
+    "array-callback-return": 0,
+    "array-element-newline": 0,
+    "arrow-body-style": 0,
+    "arrow-parens": 0,
+    "arrow-spacing": 0,
+    "block-scoped-var": 0,
+    "block-spacing": 0,
+    "brace-style": 0,
+    "callback-return": 0,
+    "camelcase": 0,
+    "capitalized-comments": 0,
+    "class-methods-use-this": 0,
+    "comma-dangle": 0,
+    "comma-spacing": 0,
+    "comma-style": 0,
+    "complexity": 0,
+    "computed-property-spacing": 0,
+    "consistent-return": 0,
+    "consistent-this": 0,
+    "constructor-super": 0,
+    "curly": 0,
+    "default-case": 0,
+    "dot-location": 0,
+    "dot-notation": 0,
+    "eol-last": 0,
+    "eqeqeq": 0,
+    "for-direction": 0,
+    "func-call-spacing": 0,
+    "func-name-matching": 0,
+    "func-names": 0,
+    "func-style": 0,
+    "function-paren-newline": 0,
+    "generator-star-spacing": 0,
+    "getter-return": 0,
+    "global-require": 0,
+    "guard-for-in": 0,
+    "handle-callback-err": 0,
+    "id-blacklist": 0,
+    "id-length": 0,
+    "id-match": 0,
+    "implicit-arrow-linebreak": 0,
+    "indent": 0,
+    "indent-legacy": 0,
+    "init-declarations": 0,
+    "jsx-quotes": 0,
+    "key-spacing": 0,
+    "keyword-spacing": 0,
+    "line-comment-position": 0,
+    "linebreak-style": 0,
+    "lines-around-comment": 0,
+    "lines-around-directive": 0,
+    "lines-between-class-members": 0,
+    "max-classes-per-file": 0,
+    "max-depth": 0,
+    "max-len": 0,
+    "max-lines": 0,
+    "max-lines-per-function": 0,
+    "max-nested-callbacks": 0,
+    "max-params": 0,
+    "max-statements": 0,
+    "max-statements-per-line": 0,
+    "multiline-comment-style": 0,
+    "multiline-ternary": 0,
+    "new-cap": 0,
+    "new-parens": 0,
+    "newline-after-var": 0,
+    "newline-before-return": 0,
+    "newline-per-chained-call": 0,
+    "no-alert": 0,
+    "no-array-constructor": 0,
+    "no-async-promise-executor": 0,
+    "no-await-in-loop": 0,
+    "no-bitwise": 0,
+    "no-buffer-constructor": 0,
+    "no-caller": 0,
+    "no-case-declarations": 0,
+    "no-catch-shadow": 0,
+    "no-class-assign": 0,
+    "no-compare-neg-zero": 0,
+    "no-cond-assign": 0,
+    "no-confusing-arrow": 0,
+    "no-console": 0,
+    "no-const-assign": 0,
+    "no-constant-condition": 0,
+    "no-continue": 0,
+    "no-control-regex": 0,
+    "no-debugger": 0,
+    "no-delete-var": 0,
+    "no-div-regex": 0,
+    "no-dupe-args": 0,
+    "no-dupe-class-members": 0,
+    "no-dupe-keys": 0,
+    "no-duplicate-case": 0,
+    "no-duplicate-imports": 0,
+    "no-else-return": 0,
+    "no-empty": 0,
+    "no-empty-character-class": 0,
+    "no-empty-function": 0,
+    "no-empty-pattern": 0,
+    "no-eq-null": 0,
+    "no-eval": 0,
+    "no-ex-assign": 0,
+    "no-extend-native": 0,
+    "no-extra-bind": 0,
+    "no-extra-boolean-cast": 0,
+    "no-extra-label": 0,
+    "no-extra-parens": 0,
+    "no-extra-semi": 0,
+    "no-fallthrough": 0,
+    "no-floating-decimal": 0,
+    "no-func-assign": 0,
+    "no-global-assign": 0,
+    "no-implicit-coercion": 0,
+    "no-implicit-globals": 0,
+    "no-implied-eval": 0,
+    "no-inline-comments": 0,
+    "no-inner-declarations": 0,
+    "no-invalid-regexp": 0,
+    "no-invalid-this": 0,
+    "no-irregular-whitespace": 0,
+    "no-iterator": 0,
+    "no-label-var": 0,
+    "no-labels": 0,
+    "no-lone-blocks": 0,
+    "no-lonely-if": 0,
+    "no-loop-func": 0,
+    "no-magic-numbers": 0,
+    "no-misleading-character-class": 0,
+    "no-mixed-operators": 0,
+    "no-mixed-requires": 0,
+    "no-mixed-spaces-and-tabs": 0,
+    "no-multi-assign": 0,
+    "no-multi-spaces": 0,
+    "no-multi-str": 0,
+    "no-multiple-empty-lines": 0,
+    "no-native-reassign": 0,
+    "no-negated-condition": 0,
+    "no-negated-in-lhs": 0,
+    "no-nested-ternary": 0,
+    "no-new": 0,
+    "no-new-func": 0,
+    "no-new-object": 0,
+    "no-new-require": 0,
+    "no-new-symbol": 0,
+    "no-new-wrappers": 0,
+    "no-obj-calls": 0,
+    "no-octal": 0,
+    "no-octal-escape": 0,
+    "no-param-reassign": 0,
+    "no-path-concat": 0,
+    "no-plusplus": 0,
+    "no-process-env": 0,
+    "no-process-exit": 0,
+    "no-proto": 0,
+    "no-prototype-builtins": 0,
+    "no-redeclare": 0,
+    "no-regex-spaces": 0,
+    "no-restricted-globals": 0,
+    "no-restricted-imports": 0,
+    "no-restricted-modules": 0,
+    "no-restricted-properties": 0,
+    "no-restricted-syntax": 0,
+    "no-return-assign": 0,
+    "no-return-await": 0,
+    "no-script-url": 0,
+    "no-self-assign": 0,
+    "no-self-compare": 0,
+    "no-sequences": 0,
+    "no-shadow": 0,
+    "no-shadow-restricted-names": 0,
+    "no-spaced-func": 0,
+    "no-sparse-arrays": 0,
+    "no-sync": 0,
+    "no-tabs": 0,
+    "no-template-curly-in-string": 0,
+    "no-ternary": 0,
+    "no-this-before-super": 0,
+    "no-throw-literal": 0,
+    "no-trailing-spaces": 0,
+    "no-undef": 0,
+    "no-undef-init": 0,
+    "no-undefined": 0,
+    "no-underscore-dangle": 0,
+    "no-unexpected-multiline": 0,
+    "no-unmodified-loop-condition": 0,
+    "no-unneeded-ternary": 0,
+    "no-unreachable": 0,
+    "no-unsafe-finally": 0,
+    "no-unsafe-negation": 0,
+    "no-unused-expressions": 0,
+    "no-unused-labels": 0,
+    "no-unused-vars": 0,
+    "no-use-before-define": 0,
+    "no-useless-call": 0,
+    "no-useless-catch": 0,
+    "no-useless-computed-key": 0,
+    "no-useless-concat": 0,
+    "no-useless-constructor": 0,
+    "no-useless-escape": 0,
+    "no-useless-rename": 0,
+    "no-useless-return": 0,
+    "no-var": 0,
+    "no-void": 0,
+    "no-warning-comments": 0,
+    "no-whitespace-before-property": 0,
+    "no-with": 0,
+    "nonblock-statement-body-position": 0,
+    "object-curly-newline": 0,
+    "object-curly-spacing": 0,
+    "object-property-newline": 0,
+    "object-shorthand": 0,
+    "one-var": 0,
+    "one-var-declaration-per-line": 0,
+    "operator-assignment": 0,
+    "operator-linebreak": 0,
+    "padded-blocks": 0,
+    "padding-line-between-statements": 0,
+    "prefer-arrow-callback": 0,
+    "prefer-const": 0,
+    "prefer-destructuring": 0,
+    "prefer-named-capture-group": 0,
+    "prefer-numeric-literals": 0,
+    "prefer-object-spread": 0,
+    "prefer-promise-reject-errors": 0,
+    "prefer-reflect": 0,
+    "prefer-rest-params": 0,
+    "prefer-spread": 0,
+    "prefer-template": 0,
+    "quote-props": 0,
+    "quotes": 0,
+    "radix": 0,
+    "require-atomic-updates": 0,
+    "require-await": 0,
+    "require-jsdoc": 0,
+    "require-unicode-regexp": 0,
+    "require-yield": 0,
+    "rest-spread-spacing": 0,
+    "semi": 0,
+    "semi-spacing": 0,
+    "semi-style": 0,
+    "sort-imports": 0,
+    "sort-keys": 0,
+    "sort-vars": 0,
+    "space-before-blocks": 0,
+    "space-before-function-paren": 0,
+    "space-in-parens": 0,
+    "space-infix-ops": 0,
+    "space-unary-ops": 0,
+    "spaced-comment": 0,
+    "strict": 0,
+    "switch-colon-spacing": 0,
+    "symbol-description": 0,
+    "template-curly-spacing": 0,
+    "template-tag-spacing": 0,
+    "unicode-bom": 0,
+    "use-isnan": 0,
+    "valid-jsdoc": 0,
+    "valid-typeof": 0,
+    "vars-on-top": 0,
+    "wrap-iife": 0,
+    "wrap-regex": 0,
+    "yield-star-spacing": 0,
+    "yoda": 0,
+    "import/no-unresolved": 0,
+    "import/named": 0,
+    "import/namespace": 0,
+    "import/default": 0,
+    "import/export": 0,
+    "import/no-named-as-default": 0,
+    "import/no-named-as-default-member": 0,
+    "import/no-duplicates": 0,
+    "import/no-extraneous-dependencies": 0,
+    "import/unambiguous": 0
+  }
+}
diff --git a/tests/files/internal-modules/package.json b/tests/files/internal-modules/package.json
index e69de29bb2..0967ef424b 100644
--- a/tests/files/internal-modules/package.json
+++ b/tests/files/internal-modules/package.json
@@ -0,0 +1 @@
+{}
diff --git a/utils/.eslintrc.yml b/utils/.eslintrc.yml
new file mode 100644
index 0000000000..de964251c1
--- /dev/null
+++ b/utils/.eslintrc.yml
@@ -0,0 +1,15 @@
+---
+rules:
+  semi: [1, 'never']
+  comma-dangle: [1, 'always-multiline']
+  no-unused-vars: 1
+  no-console: 1
+  no-extra-semi: 1
+  no-useless-escape: 1
+  quotes:
+    - 1
+    - single
+    - allowTemplateLiterals: true
+      avoidEscape: true
+  import/default: 1
+  import/no-extraneous-dependencies: 1

From e5967f99fa112bc1c9917a5cf3906f602dfb202f Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Mon, 16 Sep 2019 15:32:50 +0800
Subject: [PATCH 030/767] [eslint] manually fix `no-unused-vars`

---
 config/.eslintrc.yml                 | 1 -
 memo-parser/.eslintrc.yml            | 1 -
 resolvers/.eslintrc.yml              | 1 -
 tests/.eslintrc.yml                  | 1 -
 tests/src/rules/no-unused-modules.js | 3 +--
 tests/src/rules/order.js             | 2 +-
 utils/.eslintrc.yml                  | 1 -
 7 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/config/.eslintrc.yml b/config/.eslintrc.yml
index de964251c1..249bf06472 100644
--- a/config/.eslintrc.yml
+++ b/config/.eslintrc.yml
@@ -2,7 +2,6 @@
 rules:
   semi: [1, 'never']
   comma-dangle: [1, 'always-multiline']
-  no-unused-vars: 1
   no-console: 1
   no-extra-semi: 1
   no-useless-escape: 1
diff --git a/memo-parser/.eslintrc.yml b/memo-parser/.eslintrc.yml
index de964251c1..249bf06472 100644
--- a/memo-parser/.eslintrc.yml
+++ b/memo-parser/.eslintrc.yml
@@ -2,7 +2,6 @@
 rules:
   semi: [1, 'never']
   comma-dangle: [1, 'always-multiline']
-  no-unused-vars: 1
   no-console: 1
   no-extra-semi: 1
   no-useless-escape: 1
diff --git a/resolvers/.eslintrc.yml b/resolvers/.eslintrc.yml
index 7286ee9e56..4a068818b8 100644
--- a/resolvers/.eslintrc.yml
+++ b/resolvers/.eslintrc.yml
@@ -4,7 +4,6 @@ env:
 rules:
   semi: [1, 'never']
   comma-dangle: [1, 'always-multiline']
-  no-unused-vars: 1
   no-console: 1
   no-extra-semi: 1
   no-useless-escape: 1
diff --git a/tests/.eslintrc.yml b/tests/.eslintrc.yml
index 5a6bc6813d..30891ab215 100644
--- a/tests/.eslintrc.yml
+++ b/tests/.eslintrc.yml
@@ -8,7 +8,6 @@ rules:
   max-len: 0
   semi: [1, 'never']
   comma-dangle: [1, 'always-multiline']
-  no-unused-vars: 1
   no-console: 1
   no-extra-semi: 1
   no-useless-escape: 1
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 8050b56935..792748cd86 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -1,7 +1,6 @@
 import { test, testFilePath } from '../utils'
 
 import { RuleTester } from 'eslint'
-import { expect } from 'chai'
 import fs from 'fs'
 
 const ruleTester = new RuleTester()
@@ -148,7 +147,7 @@ ruleTester.run('no-unused-modules', rule, {
   ],
 })
 
-// // test for export from 
+// // test for export from
 ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 426c40a104..5e10e1a252 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,4 +1,4 @@
-import { test, testVersion, getTSParsers } from '../utils'
+import { test, getTSParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
 
diff --git a/utils/.eslintrc.yml b/utils/.eslintrc.yml
index de964251c1..249bf06472 100644
--- a/utils/.eslintrc.yml
+++ b/utils/.eslintrc.yml
@@ -2,7 +2,6 @@
 rules:
   semi: [1, 'never']
   comma-dangle: [1, 'always-multiline']
-  no-unused-vars: 1
   no-console: 1
   no-extra-semi: 1
   no-useless-escape: 1

From c3cad519c448bf28dfb664b1c23b2629755289c6 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Mon, 16 Sep 2019 15:58:30 +0800
Subject: [PATCH 031/767] [eslint] increase severity of rules; `eslint --quiet
 --fix`

---
 .eslintrc.yml                                 |  1 +
 config/.eslintrc.yml                          | 14 --------
 config/errors.js                              |  4 +--
 config/recommended.js                         |  2 +-
 config/stage-0.js                             |  2 +-
 config/typescript.js                          | 12 +++----
 memo-parser/.eslintrc.yml                     | 11 ------
 memo-parser/index.js                          |  4 +--
 resolvers/.eslintrc.yml                       | 13 -------
 resolvers/webpack/.eslintrc.yml               |  4 +++
 resolvers/webpack/test/config.js              |  6 ++--
 .../webpack-resolver-plugin-test/index.js     | 34 +++++++++----------
 .../webpack/test/files/webpack.config.js      | 14 ++++----
 tests/.eslintrc.yml                           | 14 +-------
 tests/src/core/importType.js                  |  4 +--
 tests/src/core/resolve.js                     |  4 +--
 tests/src/rules/exports-last.js               |  4 +--
 tests/src/rules/first.js                      | 14 ++++----
 tests/src/rules/named.js                      |  2 +-
 tests/src/rules/no-deprecated.js              |  8 ++---
 tests/src/rules/no-restricted-paths.js        |  4 +--
 tests/src/rules/no-unassigned-import.js       |  2 +-
 tests/src/rules/no-unresolved.js              | 12 +++----
 tests/src/rules/order.js                      | 18 +++++-----
 tests/src/rules/prefer-default-export.js      | 10 +++---
 tests/src/utils.js                            | 10 +++---
 utils/.eslintrc.yml                           | 11 ------
 utils/ModuleCache.js                          |  2 +-
 utils/declaredScope.js                        |  2 +-
 utils/hash.js                                 |  6 ++--
 utils/module-require.js                       |  2 +-
 utils/parse.js                                |  6 ++--
 utils/resolve.js                              | 10 +++---
 33 files changed, 105 insertions(+), 161 deletions(-)
 delete mode 100644 config/.eslintrc.yml
 create mode 100644 resolvers/webpack/.eslintrc.yml

diff --git a/.eslintrc.yml b/.eslintrc.yml
index b54ed522fb..5ee1be595b 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -24,6 +24,7 @@ rules:
     - 2
     - single
     - allowTemplateLiterals: true
+      avoidEscape: true
 
   # dog fooding
   import/no-extraneous-dependencies: "error"
diff --git a/config/.eslintrc.yml b/config/.eslintrc.yml
deleted file mode 100644
index 249bf06472..0000000000
--- a/config/.eslintrc.yml
+++ /dev/null
@@ -1,14 +0,0 @@
----
-rules:
-  semi: [1, 'never']
-  comma-dangle: [1, 'always-multiline']
-  no-console: 1
-  no-extra-semi: 1
-  no-useless-escape: 1
-  quotes:
-    - 1
-    - single
-    - allowTemplateLiterals: true
-      avoidEscape: true
-  import/default: 1
-  import/no-extraneous-dependencies: 1
diff --git a/config/errors.js b/config/errors.js
index 8f865b90f7..d99a9dacf0 100644
--- a/config/errors.js
+++ b/config/errors.js
@@ -9,6 +9,6 @@ module.exports = {
          , 'import/named': 2
          , 'import/namespace': 2
          , 'import/default': 2
-         , 'import/export': 2
-         }
+         , 'import/export': 2,
+         },
 }
diff --git a/config/recommended.js b/config/recommended.js
index 70514eed3e..9970918933 100644
--- a/config/recommended.js
+++ b/config/recommended.js
@@ -16,7 +16,7 @@ module.exports = {
     // red flags (thus, warnings)
     'import/no-named-as-default': 'warn',
     'import/no-named-as-default-member': 'warn',
-    'import/no-duplicates': 'warn'
+    'import/no-duplicates': 'warn',
   },
 
   // need all these for parsing dependencies (even if _your_ code doesn't need
diff --git a/config/stage-0.js b/config/stage-0.js
index 1a77784861..25ad75feb1 100644
--- a/config/stage-0.js
+++ b/config/stage-0.js
@@ -8,5 +8,5 @@ module.exports = {
   plugins: ['import'],
   rules: {
     'import/no-deprecated': 1,
-  }
+  },
 }
diff --git a/config/typescript.js b/config/typescript.js
index a8efe8e9a7..fdd1d5910b 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -2,20 +2,20 @@
  * Adds `.jsx`, `.ts` and `.tsx` as an extension, and enables JSX/TSX parsing.
  */
 
-var allExtensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx'];
+var allExtensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx']
 
 module.exports = {
 
   settings: {
     'import/extensions': allExtensions,
     'import/parsers': {
-      '@typescript-eslint/parser': ['.ts', '.tsx', '.d.ts']
+      '@typescript-eslint/parser': ['.ts', '.tsx', '.d.ts'],
     },
     'import/resolver': {
       'node': {
-        'extensions': allExtensions
-      }
-    }
-  }
+        'extensions': allExtensions,
+      },
+    },
+  },
 
 }
diff --git a/memo-parser/.eslintrc.yml b/memo-parser/.eslintrc.yml
index 249bf06472..e7e6b3d341 100644
--- a/memo-parser/.eslintrc.yml
+++ b/memo-parser/.eslintrc.yml
@@ -1,14 +1,3 @@
 ---
 rules:
-  semi: [1, 'never']
-  comma-dangle: [1, 'always-multiline']
-  no-console: 1
-  no-extra-semi: 1
-  no-useless-escape: 1
-  quotes:
-    - 1
-    - single
-    - allowTemplateLiterals: true
-      avoidEscape: true
-  import/default: 1
   import/no-extraneous-dependencies: 1
diff --git a/memo-parser/index.js b/memo-parser/index.js
index 9fd74c33a9..b64f854219 100644
--- a/memo-parser/index.js
+++ b/memo-parser/index.js
@@ -1,4 +1,4 @@
-"use strict"
+'use strict'
 
 const crypto = require('crypto')
     , moduleRequire = require('eslint-module-utils/module-require').default
@@ -20,7 +20,7 @@ exports.parse = function parse(content, options) {
   options = Object.assign({}, options, parserOptions)
 
   if (!options.filePath) {
-    throw new Error("no file path provided!")
+    throw new Error('no file path provided!')
   }
 
   const keyHash = crypto.createHash('sha256')
diff --git a/resolvers/.eslintrc.yml b/resolvers/.eslintrc.yml
index 4a068818b8..9db33eda46 100644
--- a/resolvers/.eslintrc.yml
+++ b/resolvers/.eslintrc.yml
@@ -1,16 +1,3 @@
 ---
 env:
   es6: false
-rules:
-  semi: [1, 'never']
-  comma-dangle: [1, 'always-multiline']
-  no-console: 1
-  no-extra-semi: 1
-  no-useless-escape: 1
-  quotes:
-    - 1
-    - single
-    - allowTemplateLiterals: true
-      avoidEscape: true
-  import/default: 1
-  import/no-extraneous-dependencies: 1
diff --git a/resolvers/webpack/.eslintrc.yml b/resolvers/webpack/.eslintrc.yml
new file mode 100644
index 0000000000..febeb09cfa
--- /dev/null
+++ b/resolvers/webpack/.eslintrc.yml
@@ -0,0 +1,4 @@
+---
+rules:
+  import/no-extraneous-dependencies: 1
+  no-console: 1
diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index 07c6350c56..ff0c0bd669 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -119,8 +119,8 @@ describe("config", function () {
     var settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
       argv: {
-        mode: 'test'
-      }
+        mode: 'test',
+      },
     }
 
     expect(resolve('baz', file, settings)).to.have.property('path')
@@ -130,7 +130,7 @@ describe("config", function () {
   it('passes a default empty argv object to config when it is a function', function() {
     var settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
-      argv: undefined
+      argv: undefined,
     }
 
     expect(function () { resolve('baz', file, settings) }).to.not.throw(Error)
diff --git a/resolvers/webpack/test/files/node_modules/webpack-resolver-plugin-test/index.js b/resolvers/webpack/test/files/node_modules/webpack-resolver-plugin-test/index.js
index 2989f9bab3..f23d4af0c1 100644
--- a/resolvers/webpack/test/files/node_modules/webpack-resolver-plugin-test/index.js
+++ b/resolvers/webpack/test/files/node_modules/webpack-resolver-plugin-test/index.js
@@ -1,4 +1,4 @@
-var path = require('path');
+var path = require('path')
 
 /**
  * ResolverPlugin
@@ -9,15 +9,15 @@ var path = require('path');
  */
 
 function ResolverPlugin(plugins, types) {
-  if(!Array.isArray(plugins)) plugins = [plugins];
-  if(!types) types = ["normal"];
-  else if(!Array.isArray(types)) types = [types];
+  if(!Array.isArray(plugins)) plugins = [plugins]
+  if(!types) types = ["normal"]
+  else if(!Array.isArray(types)) types = [types]
 
-  this.plugins = plugins;
-  this.types = types;
+  this.plugins = plugins
+  this.types = types
 }
 
-module.exports.ResolverPlugin = ResolverPlugin;
+module.exports.ResolverPlugin = ResolverPlugin
 
 
 /**
@@ -29,29 +29,29 @@ module.exports.ResolverPlugin = ResolverPlugin;
  */
 
 function SimpleResolver(file, source) {
-  this.file = file;
-  this.source = source;
+  this.file = file
+  this.source = source
 }
 
 SimpleResolver.prototype.apply = function (resolver) {
 
-  var file = this.file;
-  var source = this.source;
+  var file = this.file
+  var source = this.source
 
   resolver.plugin('directory', function (request, done) {
 
-    var absolutePath = path.resolve(request.path, request.request);
+    var absolutePath = path.resolve(request.path, request.request)
 
     if (absolutePath === source) {
       resolver.doResolve('file', { request: file }, function (error, result) {
-        return done(undefined, result || undefined);
-      });
+        return done(undefined, result || undefined)
+      })
     }
 
-    return done();
+    return done()
 
-  });
+  })
 
 }
 
-module.exports.SimpleResolver = SimpleResolver;
+module.exports.SimpleResolver = SimpleResolver
diff --git a/resolvers/webpack/test/files/webpack.config.js b/resolvers/webpack/test/files/webpack.config.js
index 7c7c8b3c89..38a4c888bd 100644
--- a/resolvers/webpack/test/files/webpack.config.js
+++ b/resolvers/webpack/test/files/webpack.config.js
@@ -23,10 +23,10 @@ module.exports = {
     'bootstrap',
     function (context, request, callback) {
       if (request === 'underscore') {
-        return callback(null, 'underscore');
-      };
-      callback();
-    }
+        return callback(null, 'underscore')
+      }
+      callback()
+    },
   ],
 
   plugins: [
@@ -34,7 +34,7 @@ module.exports = {
       new pluginsTest.SimpleResolver(
         path.join(__dirname, 'some', 'bar', 'bar.js'),
         path.join(__dirname, 'some', 'bar')
-      )
-    ])
-  ]
+      ),
+    ]),
+  ],
 }
diff --git a/tests/.eslintrc.yml b/tests/.eslintrc.yml
index 30891ab215..92b917ed62 100644
--- a/tests/.eslintrc.yml
+++ b/tests/.eslintrc.yml
@@ -4,17 +4,5 @@ parserOptions:
 env:
   mocha: true
 rules:
-  no-unused-expressions: 0
   max-len: 0
-  semi: [1, 'never']
-  comma-dangle: [1, 'always-multiline']
-  no-console: 1
-  no-extra-semi: 1
-  no-useless-escape: 1
-  quotes:
-    - 1
-    - single
-    - allowTemplateLiterals: true
-      avoidEscape: true
-  import/default: 1
-  import/no-extraneous-dependencies: 1
+  import/default: 0
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index f60063991d..07466bfa92 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -43,12 +43,12 @@ describe('importType(name)', function () {
   })
 
   it("should return 'internal' for non-builtins resolved outside of node_modules", function () {
-    const pathContext = testContext({ "import/resolver": { node: { paths: [pathToTestFiles] } } })
+    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
     expect(importType('importType', pathContext)).to.equal('internal')
   })
 
   it.skip("should return 'internal' for scoped packages resolved outside of node_modules", function () {
-    const pathContext = testContext({ "import/resolver": { node: { paths: [pathToTestFiles] } } })
+    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
     expect(importType('@importType/index', pathContext)).to.equal('internal')
   })
     
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index b9a9063243..1664f8d90c 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -111,8 +111,8 @@ describe('resolve', function () {
   })
 
   it('reports loaded resolver with invalid interface', function () {
-    const resolverName = './foo-bar-resolver-invalid';
-    const testContext = utils.testContext({ 'import/resolver': resolverName });
+    const resolverName = './foo-bar-resolver-invalid'
+    const testContext = utils.testContext({ 'import/resolver': resolverName })
     const testContextReports = []
     testContext.report = function (reportInfo) {
       testContextReports.push(reportInfo)
diff --git a/tests/src/rules/exports-last.js b/tests/src/rules/exports-last.js
index 871c62e85c..770e123d31 100644
--- a/tests/src/rules/exports-last.js
+++ b/tests/src/rules/exports-last.js
@@ -8,8 +8,8 @@ const ruleTester = new RuleTester()
 const error = type => ({
   ruleId: 'exports-last',
   message: 'Export statements should appear at the end of the file',
-  type
-});
+  type,
+})
 
 ruleTester.run('exports-last', rule, {
   valid: [
diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index 6a0fcdd649..55367cf43c 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -22,7 +22,7 @@ ruleTester.run('first', rule, {
          , errors: 1
          , output: "import { x } from './foo';\
                   import { y } from './bar';\
-                  export { x };"
+                  export { x };",
          })
   , test({ code: "import { x } from './foo';\
                   export { x };\
@@ -32,11 +32,11 @@ ruleTester.run('first', rule, {
          , output: "import { x } from './foo';\
                   import { y } from './bar';\
                   import { z } from './baz';\
-                  export { x };"
+                  export { x };",
          })
   , test({ code: "import { x } from './foo'; import { y } from 'bar'"
          , options: ['absolute-first']
-         , errors: 1
+         , errors: 1,
          })
   , test({ code: "import { x } from 'foo';\
                   'use directive';\
@@ -44,7 +44,7 @@ ruleTester.run('first', rule, {
          , errors: 1
          , output: "import { x } from 'foo';\
                   import { y } from 'bar';\
-                  'use directive';"
+                  'use directive';",
          })
   , test({ code: "var a = 1;\
                   import { y } from './bar';\
@@ -56,12 +56,12 @@ ruleTester.run('first', rule, {
                   var a = 1;\
                   if (true) { x() };\
                   import { x } from './foo';\
-                  import { z } from './baz';"
+                  import { z } from './baz';",
   })
   , test({ code: "if (true) { console.log(1) }import a from 'b'"
          , errors: 1
-         , output: "import a from 'b'\nif (true) { console.log(1) }"
+         , output: "import a from 'b'\nif (true) { console.log(1) }",
   })
   ,
-  ]
+  ],
 })
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index ec8a1dbecd..9e15a34b0a 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -197,7 +197,7 @@ ruleTester.run('named', rule, {
     test({
       code: 'import { baz } from "./broken-trampoline"',
       parser: require.resolve('babel-eslint'),
-      errors: ["baz not found via broken-trampoline.js -> named-exports.js"],
+      errors: ['baz not found via broken-trampoline.js -> named-exports.js'],
     }),
 
     // parse errors
diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index 28b8734f7e..53f8779021 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -15,16 +15,16 @@ ruleTester.run('no-deprecated', rule, {
 
     test({
       code: "import { fn } from './deprecated'",
-      settings: { 'import/docstyle': ['tomdoc'] }
+      settings: { 'import/docstyle': ['tomdoc'] },
     }),
 
     test({
       code: "import { fine } from './tomdoc-deprecated'",
-      settings: { 'import/docstyle': ['tomdoc'] }
+      settings: { 'import/docstyle': ['tomdoc'] },
     }),
     test({
       code: "import { _undocumented } from './tomdoc-deprecated'",
-      settings: { 'import/docstyle': ['tomdoc'] }
+      settings: { 'import/docstyle': ['tomdoc'] },
     }),
 
     // naked namespace is fine
@@ -70,7 +70,7 @@ ruleTester.run('no-deprecated', rule, {
     test({
       code: "import { fn } from './tomdoc-deprecated'",
       settings: { 'import/docstyle': ['tomdoc'] },
-      errors: ["Deprecated: This function is terrible."],
+      errors: ['Deprecated: This function is terrible.'],
     }),
 
     test({
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index 13f8472cb1..ba7d650994 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -37,14 +37,14 @@ ruleTester.run('no-restricted-paths', rule, {
       filename: testFilePath('./restricted-paths/client/a.js'),
         options: [ {
           zones: [ { target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/server' } ],
-        } ], }),
+        } ] }),
 
     // no config
     test({ code: 'require("../server/b.js")' }),
     test({ code: 'import b from "../server/b.js"' }),
 
     // builtin (ignore)
-    test({ code: 'require("os")' })
+    test({ code: 'require("os")' }),
   ],
 
   invalid: [
diff --git a/tests/src/rules/no-unassigned-import.js b/tests/src/rules/no-unassigned-import.js
index 92b2769998..97be736134 100644
--- a/tests/src/rules/no-unassigned-import.js
+++ b/tests/src/rules/no-unassigned-import.js
@@ -8,7 +8,7 @@ const ruleTester = new RuleTester()
 
 const error = {
   ruleId: 'no-unassigned-import',
-  message: 'Imported module should be assigned'
+  message: 'Imported module should be assigned',
 }
 
 ruleTester.run('no-unassigned-import', rule, {
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 124ac84830..0c3a9008cb 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -302,34 +302,34 @@ ruleTester.run('no-unresolved ignore list', rule, {
   valid: [
     test({
       code: 'import "./malformed.js"',
-      options: [{ ignore: ['\.png$', '\.gif$']}],
+      options: [{ ignore: ['.png$', '.gif$']}],
     }),
     test({
       code: 'import "./test.giffy"',
-      options: [{ ignore: ['\.png$', '\.gif$']}],
+      options: [{ ignore: ['.png$', '.gif$']}],
     }),
 
     test({
       code: 'import "./test.gif"',
-      options: [{ ignore: ['\.png$', '\.gif$']}],
+      options: [{ ignore: ['.png$', '.gif$']}],
     }),
 
     test({
       code: 'import "./test.png"',
-      options: [{ ignore: ['\.png$', '\.gif$']}],
+      options: [{ ignore: ['.png$', '.gif$']}],
     }),
   ],
 
   invalid:[
     test({
       code: 'import "./test.gif"',
-      options: [{ ignore: ['\.png$']}],
+      options: [{ ignore: ['.png$']}],
       errors: [ "Unable to resolve path to module './test.gif'." ],
     }),
 
     test({
       code: 'import "./test.png"',
-      options: [{ ignore: ['\.gif$']}],
+      options: [{ ignore: ['.gif$']}],
       errors: [ "Unable to resolve path to module './test.png'." ],
     }),
   ],
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 5e10e1a252..5eb5eedb85 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -319,7 +319,7 @@ ruleTester.run('order', rule, {
         } from 'bar';
         import external from 'external'
       `,
-      options: [{ 'newlines-between': 'always' }]
+      options: [{ 'newlines-between': 'always' }],
     }),
     // Option newlines-between: 'always' with multiline imports #2
     test({
@@ -330,7 +330,7 @@ ruleTester.run('order', rule, {
 
         import external from 'external'
       `,
-      options: [{ 'newlines-between': 'always' }]
+      options: [{ 'newlines-between': 'always' }],
     }),
     // Option newlines-between: 'always' with multiline imports #3
     test({
@@ -341,7 +341,7 @@ ruleTester.run('order', rule, {
         import bar
           from './sibling';
       `,
-      options: [{ 'newlines-between': 'always' }]
+      options: [{ 'newlines-between': 'always' }],
     }),
     // Option newlines-between: 'always' with not assigned import #1
     test({
@@ -353,7 +353,7 @@ ruleTester.run('order', rule, {
 
         import _ from 'lodash';
       `,
-      options: [{ 'newlines-between': 'always' }]
+      options: [{ 'newlines-between': 'always' }],
     }),
     // Option newlines-between: 'never' with not assigned import #2
     test({
@@ -363,7 +363,7 @@ ruleTester.run('order', rule, {
         import 'something-else';
         import _ from 'lodash';
       `,
-      options: [{ 'newlines-between': 'never' }]
+      options: [{ 'newlines-between': 'never' }],
     }),
     // Option newlines-between: 'always' with not assigned require #1
     test({
@@ -375,7 +375,7 @@ ruleTester.run('order', rule, {
 
         var _ = require('lodash');
       `,
-      options: [{ 'newlines-between': 'always' }]
+      options: [{ 'newlines-between': 'always' }],
     }),
     // Option newlines-between: 'never' with not assigned require #2
     test({
@@ -385,7 +385,7 @@ ruleTester.run('order', rule, {
         require('something-else');
         var _ = require('lodash');
       `,
-      options: [{ 'newlines-between': 'never' }]
+      options: [{ 'newlines-between': 'never' }],
     }),
     // Option newlines-between: 'never' should ignore nested require statement's #1
     test({
@@ -402,7 +402,7 @@ ruleTester.run('order', rule, {
           }
         }
       `,
-      options: [{ 'newlines-between': 'never' }]
+      options: [{ 'newlines-between': 'never' }],
     }),
     // Option newlines-between: 'always' should ignore nested require statement's #2
     test({
@@ -418,7 +418,7 @@ ruleTester.run('order', rule, {
           }
         }
       `,
-      options: [{ 'newlines-between': 'always' }]
+      options: [{ 'newlines-between': 'always' }],
     }),
     // Option: newlines-between: 'always-and-inside-groups'
     test({
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index ae630b4476..adca4b6021 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -128,7 +128,7 @@ ruleTester.run('prefer-default-export', rule, {
       }],
     }),
   ],
-});
+})
 
 context('Typescript', function() {
   getNonDefaultParsers().forEach((parser) => {
@@ -138,7 +138,7 @@ context('Typescript', function() {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
-    };
+    }
 
     ruleTester.run('prefer-default-export', rule, {
       valid: [
@@ -184,6 +184,6 @@ context('Typescript', function() {
         ),
       ],
       invalid: [],
-    });
-  });
-});
+    })
+  })
+})
diff --git a/tests/src/utils.js b/tests/src/utils.js
index 9e0c4a1e05..4bc8f0119a 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -10,19 +10,19 @@ export function testFilePath(relativePath) {
 }
 
 export function getTSParsers() {
-  const parsers = [];
+  const parsers = []
   if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
-    parsers.push(require.resolve('typescript-eslint-parser'));
+    parsers.push(require.resolve('typescript-eslint-parser'))
   }
 
   if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-    parsers.push(require.resolve('@typescript-eslint/parser'));
+    parsers.push(require.resolve('@typescript-eslint/parser'))
   }
-  return parsers;
+  return parsers
 }
 
 export function getNonDefaultParsers() {
-  return getTSParsers().concat(require.resolve('babel-eslint'));
+  return getTSParsers().concat(require.resolve('babel-eslint'))
 }
 
 export const FILENAME = testFilePath('foo.js')
diff --git a/utils/.eslintrc.yml b/utils/.eslintrc.yml
index 249bf06472..d30c264659 100644
--- a/utils/.eslintrc.yml
+++ b/utils/.eslintrc.yml
@@ -1,14 +1,3 @@
 ---
 rules:
-  semi: [1, 'never']
-  comma-dangle: [1, 'always-multiline']
   no-console: 1
-  no-extra-semi: 1
-  no-useless-escape: 1
-  quotes:
-    - 1
-    - single
-    - allowTemplateLiterals: true
-      avoidEscape: true
-  import/default: 1
-  import/no-extraneous-dependencies: 1
diff --git a/utils/ModuleCache.js b/utils/ModuleCache.js
index eba86d2585..ab0266fe58 100644
--- a/utils/ModuleCache.js
+++ b/utils/ModuleCache.js
@@ -1,4 +1,4 @@
-"use strict"
+'use strict'
 exports.__esModule = true
 
 const log = require('debug')('eslint-module-utils:ModuleCache')
diff --git a/utils/declaredScope.js b/utils/declaredScope.js
index 2ef3d19a97..904279ad79 100644
--- a/utils/declaredScope.js
+++ b/utils/declaredScope.js
@@ -1,4 +1,4 @@
-"use strict"
+'use strict'
 exports.__esModule = true
 
 exports.default = function declaredScope(context, name) {
diff --git a/utils/hash.js b/utils/hash.js
index 0b946a5106..d69dd4df5f 100644
--- a/utils/hash.js
+++ b/utils/hash.js
@@ -2,7 +2,7 @@
  * utilities for hashing config objects.
  * basically iteratively updates hash with a JSON-like format
  */
-"use strict"
+'use strict'
 exports.__esModule = true
 
 const createHash = require('crypto').createHash
@@ -42,12 +42,12 @@ exports.hashArray = hashArray
 function hashObject(object, hash) {
   if (!hash) hash = createHash('sha256')
 
-  hash.update("{")
+  hash.update('{')
   Object.keys(object).sort().forEach(key => {
     hash.update(stringify(key))
     hash.update(':')
     hashify(object[key], hash)
-    hash.update(",")
+    hash.update(',')
   })
   hash.update('}')
 
diff --git a/utils/module-require.js b/utils/module-require.js
index 9b387ad1a6..689450658c 100644
--- a/utils/module-require.js
+++ b/utils/module-require.js
@@ -1,4 +1,4 @@
-"use strict"
+'use strict'
 exports.__esModule = true
 
 const Module = require('module')
diff --git a/utils/parse.js b/utils/parse.js
index 9551599043..fa2ff14259 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -1,4 +1,4 @@
-"use strict"
+'use strict'
 exports.__esModule = true
 
 const moduleRequire = require('./module-require').default
@@ -36,8 +36,8 @@ exports.default = function parse(path, content, context) {
   // "project" or "projects" in parserOptions. Removing these options means the parser will
   // only parse one file in isolate mode, which is much, much faster.
   // https://github.com/benmosher/eslint-plugin-import/issues/1408#issuecomment-509298962
-  delete parserOptions.project;
-  delete parserOptions.projects;
+  delete parserOptions.project
+  delete parserOptions.projects
   
   // require the parser relative to the main module (i.e., ESLint)
   const parser = moduleRequire(parserPath)
diff --git a/utils/resolve.js b/utils/resolve.js
index 87a1eaea81..fdd6f1ee54 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -1,4 +1,4 @@
-"use strict"
+'use strict'
 exports.__esModule = true
 
 const pkgDir = require('pkg-dir')
@@ -15,17 +15,17 @@ exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS
 const fileExistsCache = new ModuleCache()
 
 function tryRequire(target) {
-  let resolved;
+  let resolved
   try {
     // Check if the target exists
-    resolved = require.resolve(target);
+    resolved = require.resolve(target)
   } catch(e) {
     // If the target does not exist then just return undefined
-    return undefined;
+    return undefined
   }
 
   // If the target exists then return the loaded module
-  return require(resolved);
+  return require(resolved)
 }
 
 // http://stackoverflow.com/a/27382838

From 5e143b23f3b89096e1b6a268af723f60c1ecb22f Mon Sep 17 00:00:00 2001
From: Simon Emanuel Schmid <simon@schmid.io>
Date: Sun, 4 Aug 2019 13:40:03 +0200
Subject: [PATCH 032/767] [new] `no-extraneous-dependencies`: Implement support
 for bundledDependencies

 - See https://npm.github.io/using-pkgs-docs/package-json/types/bundleddependencies.html
 - Fixes #1436.
---
 CHANGELOG.md                                  |  3 ++
 docs/rules/no-extraneous-dependencies.md      | 14 +++++++--
 src/rules/no-extraneous-dependencies.js       | 15 +++++++++-
 .../node_modules/@generated/bar/index.js      |  0
 .../node_modules/@generated/foo/index.js      |  0
 .../as-array-bundle-deps/package.json         |  4 +++
 .../node_modules/@generated/bar/index.js      |  0
 .../node_modules/@generated/foo/index.js      |  0
 .../as-object/package.json                    |  4 +++
 .../node_modules/@generated/bar/index.js      |  0
 .../node_modules/@generated/foo/index.js      |  0
 .../race-condition/package.json               |  5 ++++
 .../node_modules/@generated/bar/index.js      |  0
 .../node_modules/@generated/foo/index.js      |  0
 tests/files/package.json                      |  3 +-
 tests/src/rules/no-extraneous-dependencies.js | 30 +++++++++++++++++++
 16 files changed, 74 insertions(+), 4 deletions(-)
 create mode 100644 tests/files/bundled-dependencies/as-array-bundle-deps/node_modules/@generated/bar/index.js
 create mode 100644 tests/files/bundled-dependencies/as-array-bundle-deps/node_modules/@generated/foo/index.js
 create mode 100644 tests/files/bundled-dependencies/as-array-bundle-deps/package.json
 create mode 100644 tests/files/bundled-dependencies/as-object/node_modules/@generated/bar/index.js
 create mode 100644 tests/files/bundled-dependencies/as-object/node_modules/@generated/foo/index.js
 create mode 100644 tests/files/bundled-dependencies/as-object/package.json
 create mode 100644 tests/files/bundled-dependencies/race-condition/node_modules/@generated/bar/index.js
 create mode 100644 tests/files/bundled-dependencies/race-condition/node_modules/@generated/foo/index.js
 create mode 100644 tests/files/bundled-dependencies/race-condition/package.json
 create mode 100644 tests/files/node_modules/@generated/bar/index.js
 create mode 100644 tests/files/node_modules/@generated/foo/index.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 822efcebb1..8ca2345676 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Added
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
+- [`no-extraneous-dependencies`]: Implement support for [bundledDependencies](https://npm.github.io/using-pkgs-docs/package-json/types/bundleddependencies.html) ([#1436], thanks [@schmidsi]))
 
 ### Fixed
 - `default`: make error message less confusing ([#1470], thanks [@golopot])
@@ -609,6 +610,7 @@ for info on changes for earlier releases.
 
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
+[#1436]: https://github.com/benmosher/eslint-plugin-import/pull/1436
 [#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
 [#1425]: https://github.com/benmosher/eslint-plugin-import/pull/1425
 [#1419]: https://github.com/benmosher/eslint-plugin-import/pull/1419
@@ -986,3 +988,4 @@ for info on changes for earlier releases.
 [@lencioni]: https://github.com/lencioni
 [@JounQin]: https://github.com/JounQin
 [@atikenny]: https://github.com/atikenny
+[@schmidsi]: https://github.com/schmidsi
diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index 2b66aa25c0..295590ccd0 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -1,6 +1,6 @@
 # import/no-extraneous-dependencies: Forbid the use of extraneous packages
 
-Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies` or `peerDependencies`.
+Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`, or `bundledDependencies`.
 The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behaviour can be changed with the rule option `packageDir`.
 
 Modules have to be installed for this rule to work.
@@ -15,6 +15,8 @@ This rule supports the following options:
 
 `peerDependencies`: If set to `false`, then the rule will show an error when `peerDependencies` are imported. Defaults to `false`.
 
+`bundledDependencies`: If set to `false`, then the rule will show an error when `bundledDependencies` are imported. Defaults to `true`.
+
 You can set the options like this:
 
 ```js
@@ -70,7 +72,10 @@ Given the following `package.json`:
   },
   "peerDependencies": {
     "react": ">=15.0.0 <16.0.0"
-  }
+  },
+  "bundledDependencies": [
+    "@generated/foo",
+  ]
 }
 ```
 
@@ -90,6 +95,10 @@ var test = require('ava');
 /* eslint import/no-extraneous-dependencies: ["error", {"optionalDependencies": false}] */
 import isArray from 'lodash.isarray';
 var isArray = require('lodash.isarray');
+
+/* eslint import/no-extraneous-dependencies: ["error", {"bundledDependencies": false}] */
+import foo from '"@generated/foo"';
+var foo = require('"@generated/foo"');
 ```
 
 
@@ -103,6 +112,7 @@ var foo = require('./foo');
 import test from 'ava';
 import find from 'lodash.find';
 import isArray from 'lodash.isarray';
+import foo from '"@generated/foo"';
 
 /* eslint import/no-extraneous-dependencies: ["error", {"peerDependencies": true}] */
 import react from 'react';
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 647481a374..1351029cc8 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -11,12 +11,19 @@ function hasKeys(obj = {}) {
   return Object.keys(obj).length > 0
 }
 
+function arrayOrKeys(arrayOrObject) {
+  return Array.isArray(arrayOrObject) ? arrayOrObject : Object.keys(arrayOrObject)
+}
+
 function extractDepFields(pkg) {
   return {
     dependencies: pkg.dependencies || {},
     devDependencies: pkg.devDependencies || {},
     optionalDependencies: pkg.optionalDependencies || {},
     peerDependencies: pkg.peerDependencies || {},
+    // BundledDeps should be in the form of an array, but object notation is also supported by
+    // `npm`, so we convert it to an array if it is an object
+    bundledDependencies: arrayOrKeys(pkg.bundleDependencies || pkg.bundledDependencies || [])
   }
 }
 
@@ -28,6 +35,7 @@ function getDependencies(context, packageDir) {
       devDependencies: {},
       optionalDependencies: {},
       peerDependencies: {},
+      bundledDependencies: [],
     }
 
     if (packageDir && packageDir.length > 0) {
@@ -63,6 +71,7 @@ function getDependencies(context, packageDir) {
       packageContent.devDependencies,
       packageContent.optionalDependencies,
       packageContent.peerDependencies,
+      packageContent.bundledDependencies,
     ].some(hasKeys)) {
       return null
     }
@@ -121,11 +130,13 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
   const isInDevDeps = deps.devDependencies[packageName] !== undefined
   const isInOptDeps = deps.optionalDependencies[packageName] !== undefined
   const isInPeerDeps = deps.peerDependencies[packageName] !== undefined
+  const isInBundledDeps = deps.bundledDependencies.indexOf(packageName) !== -1
 
   if (isInDeps ||
     (depsOptions.allowDevDeps && isInDevDeps) ||
     (depsOptions.allowPeerDeps && isInPeerDeps) ||
-    (depsOptions.allowOptDeps && isInOptDeps)
+    (depsOptions.allowOptDeps && isInOptDeps) ||
+    (depsOptions.allowBundledDeps && isInBundledDeps)
   ) {
     return
   }
@@ -169,6 +180,7 @@ module.exports = {
           'devDependencies': { 'type': ['boolean', 'array'] },
           'optionalDependencies': { 'type': ['boolean', 'array'] },
           'peerDependencies': { 'type': ['boolean', 'array'] },
+          'bundledDependencies': { 'type': ['boolean', 'array'] },
           'packageDir': { 'type': ['string', 'array'] },
         },
         'additionalProperties': false,
@@ -185,6 +197,7 @@ module.exports = {
       allowDevDeps: testConfig(options.devDependencies, filename) !== false,
       allowOptDeps: testConfig(options.optionalDependencies, filename) !== false,
       allowPeerDeps: testConfig(options.peerDependencies, filename) !== false,
+      allowBundledDeps: testConfig(options.bundledDependencies, filename) !== false,
     }
 
     // todo: use module visitor from module-utils core
diff --git a/tests/files/bundled-dependencies/as-array-bundle-deps/node_modules/@generated/bar/index.js b/tests/files/bundled-dependencies/as-array-bundle-deps/node_modules/@generated/bar/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/bundled-dependencies/as-array-bundle-deps/node_modules/@generated/foo/index.js b/tests/files/bundled-dependencies/as-array-bundle-deps/node_modules/@generated/foo/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/bundled-dependencies/as-array-bundle-deps/package.json b/tests/files/bundled-dependencies/as-array-bundle-deps/package.json
new file mode 100644
index 0000000000..ef9c675edb
--- /dev/null
+++ b/tests/files/bundled-dependencies/as-array-bundle-deps/package.json
@@ -0,0 +1,4 @@
+{
+  "dummy": true,
+  "bundleDependencies": ["@generated/foo"]
+}
diff --git a/tests/files/bundled-dependencies/as-object/node_modules/@generated/bar/index.js b/tests/files/bundled-dependencies/as-object/node_modules/@generated/bar/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/bundled-dependencies/as-object/node_modules/@generated/foo/index.js b/tests/files/bundled-dependencies/as-object/node_modules/@generated/foo/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/bundled-dependencies/as-object/package.json b/tests/files/bundled-dependencies/as-object/package.json
new file mode 100644
index 0000000000..1a5baff5a9
--- /dev/null
+++ b/tests/files/bundled-dependencies/as-object/package.json
@@ -0,0 +1,4 @@
+{
+  "dummy": true,
+  "bundledDependencies": {"@generated/foo": "latest"}
+}
diff --git a/tests/files/bundled-dependencies/race-condition/node_modules/@generated/bar/index.js b/tests/files/bundled-dependencies/race-condition/node_modules/@generated/bar/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/bundled-dependencies/race-condition/node_modules/@generated/foo/index.js b/tests/files/bundled-dependencies/race-condition/node_modules/@generated/foo/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/bundled-dependencies/race-condition/package.json b/tests/files/bundled-dependencies/race-condition/package.json
new file mode 100644
index 0000000000..827ecc583e
--- /dev/null
+++ b/tests/files/bundled-dependencies/race-condition/package.json
@@ -0,0 +1,5 @@
+{
+  "dummy": true,
+  "bundledDependencies": {"@generated/bar": "latest"},
+  "bundleDependencies": ["@generated/foo"]
+}
diff --git a/tests/files/node_modules/@generated/bar/index.js b/tests/files/node_modules/@generated/bar/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/node_modules/@generated/foo/index.js b/tests/files/node_modules/@generated/foo/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/package.json b/tests/files/package.json
index 0a60f28d36..0ca8e77737 100644
--- a/tests/files/package.json
+++ b/tests/files/package.json
@@ -15,5 +15,6 @@
   },
   "optionalDependencies": {
     "lodash.isarray": "^4.0.0"
-  }
+  },
+  "bundledDependencies": ["@generated/foo"]
 }
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index b9d24580ec..b50f9923b5 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -18,6 +18,9 @@ const packageDirWithFlowTyped = path.join(__dirname, '../../files/with-flow-type
 const packageDirMonoRepoRoot = path.join(__dirname, '../../files/monorepo')
 const packageDirMonoRepoWithNested = path.join(__dirname, '../../files/monorepo/packages/nested-package')
 const packageDirWithEmpty = path.join(__dirname, '../../files/empty')
+const packageDirBundleDeps = path.join(__dirname, '../../files/bundled-dependencies/as-array-bundle-deps')
+const packageDirBundledDepsAsObject = path.join(__dirname, '../../files/bundled-dependencies/as-object')
+const packageDirBundledDepsRaceCondition = path.join(__dirname, '../../files/bundled-dependencies/race-condition')
 
 ruleTester.run('no-extraneous-dependencies', rule, {
   valid: [
@@ -106,6 +109,19 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import rightpad from "right-pad";',
       options: [{packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested]}],
     }),
+    test({ code: 'import foo from "@generated/foo"'}),
+    test({
+      code: 'import foo from "@generated/foo"',
+      options: [{packageDir: packageDirBundleDeps}],
+    }),
+    test({
+      code: 'import foo from "@generated/foo"',
+      options: [{packageDir: packageDirBundledDepsAsObject}],
+    }),
+    test({
+      code: 'import foo from "@generated/foo"',
+      options: [{packageDir: packageDirBundledDepsRaceCondition}],
+    }),
   ],
   invalid: [
     test({
@@ -289,5 +305,19 @@ ruleTester.run('no-extraneous-dependencies', rule, {
         message: "'react' should be listed in the project's dependencies. Run 'npm i -S react' to add it",
       }],
     }),
+    test({
+      code: 'import bar from "@generated/bar"',
+      errors: ["'@generated/bar' should be listed in the project's dependencies. Run 'npm i -S @generated/bar' to add it"],
+    }),
+    test({
+      code: 'import foo from "@generated/foo"',
+      options: [{bundledDependencies: false}],
+      errors: ["'@generated/foo' should be listed in the project's dependencies. Run 'npm i -S @generated/foo' to add it"],
+    }),
+    test({
+      code: 'import bar from "@generated/bar"',
+      options: [{packageDir: packageDirBundledDepsRaceCondition}],
+      errors: ["'@generated/bar' should be listed in the project's dependencies. Run 'npm i -S @generated/bar' to add it"],
+    }),
   ],
 })

From 370480171e99241980f7251a19049c1973fcaad9 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Sat, 24 Aug 2019 23:24:23 +0800
Subject: [PATCH 033/767] [fix] `prefer-default-export`: fix cases when
 exporting array destructuring

Fixes #706
---
 src/rules/prefer-default-export.js       |  5 ++++-
 tests/src/rules/prefer-default-export.js | 12 ++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 59c26d11ee..f0af00d02b 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -23,7 +23,10 @@ module.exports = {
           .forEach(function(property) {
             captureDeclaration(property.value)
           })
-      } else {
+      } else if (identifierOrPattern.type === 'ArrayPattern') {
+        identifierOrPattern.elements
+          .forEach(captureDeclaration)
+      } else  {
       // assume it's a single standard identifier
         specifierExportCount++
       }
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index adca4b6021..d0b46530ab 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -43,6 +43,10 @@ ruleTester.run('prefer-default-export', rule, {
       code: `
         export const { foo: { bar, baz } } = item;`,
       }),
+    test({
+      code: `
+        export const [a, b] = item;`,
+      }),
     test({
       code: `
         let item;
@@ -127,6 +131,14 @@ ruleTester.run('prefer-default-export', rule, {
         message: 'Prefer default export.',
       }],
     }),
+    test({
+      code: `
+        export const [a] = ["foo"]`,
+      errors: [{
+        ruleId: 'ExportNamedDeclaration',
+        message: 'Prefer default export.',
+      }],
+    }),
   ],
 })
 

From d030d8e33a8ade202f4a25b4d19dd603b3dce88e Mon Sep 17 00:00:00 2001
From: Trevor Burnham <tburnham@hubspot.com>
Date: Sat, 29 Jun 2019 18:06:13 -0400
Subject: [PATCH 034/767] [New] `no-namespace`: Make rule fixable

 - Add guards to avoid crashing older versions of ESLint
 - Note that no-namespace's --fix requires ESLint 5+
 - Prevent no-namespace --fix tests from running under ESLint < 5
---
 CHANGELOG.md                    |   3 +
 README.md                       |   2 +-
 docs/rules/no-namespace.md      |  10 ++-
 src/rules/no-namespace.js       | 132 +++++++++++++++++++++++++++++++-
 tests/src/rules/no-namespace.js | 101 ++++++++++++++++++++----
 5 files changed, 228 insertions(+), 20 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ca2345676..6e1fcd225b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Added
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
+- [`no-namespace`]: Make rule fixable ([#1401], thanks [@TrevorBurnham])
 
 ### Added
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
@@ -617,6 +618,7 @@ for info on changes for earlier releases.
 [#1412]: https://github.com/benmosher/eslint-plugin-import/pull/1412
 [#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
 [#1404]: https://github.com/benmosher/eslint-plugin-import/pull/1404
+[#1401]: https://github.com/benmosher/eslint-plugin-import/pull/1401
 [#1393]: https://github.com/benmosher/eslint-plugin-import/pull/1393
 [#1389]: https://github.com/benmosher/eslint-plugin-import/pull/1389
 [#1377]: https://github.com/benmosher/eslint-plugin-import/pull/1377
@@ -989,3 +991,4 @@ for info on changes for earlier releases.
 [@JounQin]: https://github.com/JounQin
 [@atikenny]: https://github.com/atikenny
 [@schmidsi]: https://github.com/schmidsi
+[@TrevorBurnham]: https://github.com/TrevorBurnham
diff --git a/README.md b/README.md
index aaa3f4c201..856baa9090 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 * Ensure all imports appear before other statements ([`first`])
 * Ensure all exports appear after other statements ([`exports-last`])
 * Report repeated import of the same module in multiple places ([`no-duplicates`])
-* Report namespace imports ([`no-namespace`])
+* Forbid namespace (a.k.a. "wildcard" `*`) imports ([`no-namespace`])
 * Ensure consistent use of file extension within the import path ([`extensions`])
 * Enforce a convention in module import order ([`order`])
 * Enforce a newline after import statements ([`newline-after-import`])
diff --git a/docs/rules/no-namespace.md b/docs/rules/no-namespace.md
index b308d66210..e0b0f0b967 100644
--- a/docs/rules/no-namespace.md
+++ b/docs/rules/no-namespace.md
@@ -1,6 +1,9 @@
 # import/no-namespace
 
-Reports if namespace import is used.
+Enforce a convention of not using namespace (a.k.a. "wildcard" `*`) imports.
+
++(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule, provided that the namespace object is only used for direct member access, e.g. `namespace.a`.
+The `--fix` functionality for this rule requires ESLint 5 or newer.
 
 ## Rule Details
 
@@ -12,10 +15,13 @@ import { a, b }  from './bar'
 import defaultExport, { a, b }  from './foobar'
 ```
 
-...whereas here imports will be reported:
+Invalid:
 
 ```js
 import * as foo from 'foo';
+```
+
+```js
 import defaultExport, * as foo from 'foo';
 ```
 
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index 3dbedca500..a3a6913646 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -16,13 +16,143 @@ module.exports = {
     docs: {
       url: docsUrl('no-namespace'),
     },
+    fixable: 'code',
   },
 
   create: function (context) {
     return {
       'ImportNamespaceSpecifier': function (node) {
-        context.report(node, `Unexpected namespace import.`)
+        const scopeVariables = context.getScope().variables
+        const namespaceVariable = scopeVariables.find((variable) =>
+          variable.defs[0].node === node
+        )
+        const namespaceReferences = namespaceVariable.references
+        const namespaceIdentifiers = namespaceReferences.map(reference => reference.identifier)
+        const canFix = namespaceIdentifiers.length > 0 && !usesNamespaceAsObject(namespaceIdentifiers)
+
+        context.report({
+          node,
+          message: `Unexpected namespace import.`,
+          fix: canFix && (fixer => {
+            const scopeManager = context.getSourceCode().scopeManager
+            const fixes = []
+
+            // Pass 1: Collect variable names that are already in scope for each reference we want
+            // to transform, so that we can be sure that we choose non-conflicting import names
+            const importNameConflicts = {}
+            namespaceIdentifiers.forEach((identifier) => {
+              const parent = identifier.parent
+              if (parent && parent.type === 'MemberExpression') {
+                const importName = getMemberPropertyName(parent)
+                const localConflicts = getVariableNamesInScope(scopeManager, parent)
+                if (!importNameConflicts[importName]) {
+                  importNameConflicts[importName] = localConflicts
+                } else {
+                  localConflicts.forEach((c) => importNameConflicts[importName].add(c))
+                }
+              }
+            })
+
+            // Choose new names for each import
+            const importNames = Object.keys(importNameConflicts)
+            const importLocalNames = generateLocalNames(
+              importNames,
+              importNameConflicts,
+              namespaceVariable.name
+            )
+
+            // Replace the ImportNamespaceSpecifier with a list of ImportSpecifiers
+            const namedImportSpecifiers = importNames.map((importName) =>
+              importName === importLocalNames[importName]
+                ? importName
+                : `${importName} as ${importLocalNames[importName]}`
+            )
+            fixes.push(fixer.replaceText(node, `{ ${namedImportSpecifiers.join(', ')} }`))
+
+            // Pass 2: Replace references to the namespace with references to the named imports
+            namespaceIdentifiers.forEach((identifier) => {
+              const parent = identifier.parent
+              if (parent && parent.type === 'MemberExpression') {
+                const importName = getMemberPropertyName(parent)
+                fixes.push(fixer.replaceText(parent, importLocalNames[importName]))
+              }
+            })
+
+            return fixes
+          }),
+        })
       },
     }
   },
 }
+
+/**
+ * @param {Identifier[]} namespaceIdentifiers
+ * @returns {boolean} `true` if the namespace variable is more than just a glorified constant
+ */
+function usesNamespaceAsObject(namespaceIdentifiers) {
+  return !namespaceIdentifiers.every((identifier) => {
+    const parent = identifier.parent
+
+    // `namespace.x` or `namespace['x']`
+    return (
+      parent && parent.type === 'MemberExpression' &&
+      (parent.property.type === 'Identifier' || parent.property.type === 'Literal')
+    )
+  })
+}
+
+/**
+ * @param {MemberExpression} memberExpression
+ * @returns {string} the name of the member in the object expression, e.g. the `x` in `namespace.x`
+ */
+function getMemberPropertyName(memberExpression) {
+  return memberExpression.property.type === 'Identifier'
+    ? memberExpression.property.name
+    : memberExpression.property.value
+}
+
+/**
+ * @param {ScopeManager} scopeManager
+ * @param {ASTNode} node
+ * @return {Set<string>}
+ */
+function getVariableNamesInScope(scopeManager, node) {
+  let currentNode = node
+  let scope = scopeManager.acquire(currentNode)
+  while (scope == null) {
+    currentNode = currentNode.parent
+    scope = scopeManager.acquire(currentNode, true)
+  }
+  return new Set([
+    ...scope.variables.map(variable => variable.name),
+    ...scope.upper.variables.map(variable => variable.name),
+  ])
+}
+
+/**
+ *
+ * @param {*} names
+ * @param {*} nameConflicts
+ * @param {*} namespaceName
+ */
+function generateLocalNames(names, nameConflicts, namespaceName) {
+  const localNames = {}
+  names.forEach((name) => {
+    let localName
+    if (!nameConflicts[name].has(name)) {
+      localName = name
+    } else if (!nameConflicts[name].has(`${namespaceName}_${name}`)) {
+      localName = `${namespaceName}_${name}`
+    } else {
+      for (let i = 1; i < Infinity; i++) {
+        if (!nameConflicts[name].has(`${namespaceName}_${name}_${i}`)) {
+          localName = `${namespaceName}_${name}_${i}`
+          break
+        }
+      }
+    }
+    localNames[name] = localName
+  })
+  return localNames
+}
diff --git a/tests/src/rules/no-namespace.js b/tests/src/rules/no-namespace.js
index d9ef3423c2..a7cb4dd21f 100644
--- a/tests/src/rules/no-namespace.js
+++ b/tests/src/rules/no-namespace.js
@@ -1,44 +1,113 @@
 import { RuleTester } from 'eslint'
+import eslintPkg from 'eslint/package.json'
+import semver from 'semver'
+import { test } from '../utils'
 
 const ERROR_MESSAGE = 'Unexpected namespace import.'
 
 const ruleTester = new RuleTester()
 
+// --fix functionality requires ESLint 5+
+const FIX_TESTS = semver.satisfies(eslintPkg.version, '>5.0.0') ? [
+  test({
+    code: `
+      import * as foo from './foo';
+      florp(foo.bar);
+      florp(foo['baz']);
+    `.trim(),
+    output: `
+      import { bar, baz } from './foo';
+      florp(bar);
+      florp(baz);
+    `.trim(),
+    errors: [ {
+      line: 1,
+      column: 8,
+      message: ERROR_MESSAGE,
+    }],
+  }),
+  test({
+    code: `
+      import * as foo from './foo';
+      const bar = 'name conflict';
+      const baz = 'name conflict';
+      const foo_baz = 'name conflict';
+      florp(foo.bar);
+      florp(foo['baz']);
+    `.trim(),
+    output: `
+      import { bar as foo_bar, baz as foo_baz_1 } from './foo';
+      const bar = 'name conflict';
+      const baz = 'name conflict';
+      const foo_baz = 'name conflict';
+      florp(foo_bar);
+      florp(foo_baz_1);
+    `.trim(),
+    errors: [ {
+      line: 1,
+      column: 8,
+      message: ERROR_MESSAGE,
+    }],
+  }),
+  test({
+    code: `
+      import * as foo from './foo';
+      function func(arg) {
+        florp(foo.func);
+        florp(foo['arg']);
+      }
+    `.trim(),
+    output: `
+      import { func as foo_func, arg as foo_arg } from './foo';
+      function func(arg) {
+        florp(foo_func);
+        florp(foo_arg);
+      }
+    `.trim(),
+    errors: [ {
+      line: 1,
+      column: 8,
+      message: ERROR_MESSAGE,
+    }],
+  }),
+] : []
+
 ruleTester.run('no-namespace', require('rules/no-namespace'), {
   valid: [
-    { code: "import { a, b } from 'foo';", parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
-    { code: "import { a, b } from './foo';", parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
-    { code: "import bar from 'bar';", parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
-    { code: "import bar from './bar';", parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
+    { code: 'import { a, b } from \'foo\';', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
+    { code: 'import { a, b } from \'./foo\';', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
+    { code: 'import bar from \'bar\';', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
+    { code: 'import bar from \'./bar\';', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
   ],
 
   invalid: [
-    {
-      code: "import * as foo from 'foo';",
+    test({
+      code: 'import * as foo from \'foo\';',
+      output: 'import * as foo from \'foo\';',
       errors: [ {
         line: 1,
         column: 8,
         message: ERROR_MESSAGE,
       } ],
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
-    {
-      code: "import defaultExport, * as foo from 'foo';",
+    }),
+    test({
+      code: 'import defaultExport, * as foo from \'foo\';',
+      output: 'import defaultExport, * as foo from \'foo\';',
       errors: [ {
         line: 1,
         column: 23,
         message: ERROR_MESSAGE,
       } ],
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
-    {
-      code: "import * as foo from './foo';",
+    }),
+    test({
+      code: 'import * as foo from \'./foo\';',
+      output: 'import * as foo from \'./foo\';',
       errors: [ {
         line: 1,
         column: 8,
         message: ERROR_MESSAGE,
       } ],
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
+    }),
+    ...FIX_TESTS,
   ],
 })

From c14c9bd665525865f023b7214bbaf3d0124563dd Mon Sep 17 00:00:00 2001
From: Ben Munro <benmunro@amazon.com>
Date: Mon, 7 Oct 2019 18:03:41 +0200
Subject: [PATCH 035/767] [Fix] `named`/`ExportMap`: Fix ExportMap for a merged
 typescript namespace

A typescript namespace may be declared multiple times, it is then merged
together and considered to be a single declaration from consuming code.
In the case where a merged namespace is assigned as the export from a
module then the declarations from all the instances of the namespace in
the AST need to be considered as exported.
---
 CHANGELOG.md                                  |  3 ++
 src/ExportMap.js                              | 44 ++++++++++---------
 .../typescript-export-assign-merged.d.ts      | 41 +++++++++++++++++
 tests/src/rules/named.js                      |  2 +-
 4 files changed, 68 insertions(+), 22 deletions(-)
 create mode 100644 tests/files/typescript-export-assign-merged.d.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e1fcd225b..7a9c6519fc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - `default`: make error message less confusing ([#1470], thanks [@golopot])
+- Support export of a merged typescript namespace declaration ([#1495], thanks [@benmunro])
 
 ## [2.18.2] - 2019-07-19
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
@@ -609,6 +610,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
 [#1436]: https://github.com/benmosher/eslint-plugin-import/pull/1436
@@ -992,3 +994,4 @@ for info on changes for earlier releases.
 [@atikenny]: https://github.com/atikenny
 [@schmidsi]: https://github.com/schmidsi
 [@TrevorBurnham]: https://github.com/TrevorBurnham
+[@benmunro]: https://github.com/benmunro
diff --git a/src/ExportMap.js b/src/ExportMap.js
index ebeb4fad7f..c9544c9c87 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -514,30 +514,32 @@ ExportMap.parse = function (path, content, context) {
 
     // This doesn't declare anything, but changes what's being exported.
     if (n.type === 'TSExportAssignment') {
-      const moduleDecl = ast.body.find((bodyNode) =>
+      const moduleDecls = ast.body.filter((bodyNode) =>
         bodyNode.type === 'TSModuleDeclaration' && bodyNode.id.name === n.expression.name
       )
-      if (moduleDecl && moduleDecl.body && moduleDecl.body.body) {
-        moduleDecl.body.body.forEach((moduleBlockNode) => {
-          // Export-assignment exports all members in the namespace, explicitly exported or not.
-          const exportedDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
-            moduleBlockNode.declaration :
-            moduleBlockNode
-
-          if (exportedDecl.type === 'VariableDeclaration') {
-            exportedDecl.declarations.forEach((decl) =>
-              recursivePatternCapture(decl.id,(id) => m.namespace.set(
-                id.name,
-                captureDoc(source, docStyleParsers, decl, exportedDecl, moduleBlockNode))
+      moduleDecls.forEach((moduleDecl) => {
+        if (moduleDecl && moduleDecl.body && moduleDecl.body.body) {
+          moduleDecl.body.body.forEach((moduleBlockNode) => {
+            // Export-assignment exports all members in the namespace, explicitly exported or not.
+            const exportedDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
+              moduleBlockNode.declaration :
+              moduleBlockNode
+
+            if (exportedDecl.type === 'VariableDeclaration') {
+              exportedDecl.declarations.forEach((decl) =>
+                recursivePatternCapture(decl.id,(id) => m.namespace.set(
+                  id.name,
+                  captureDoc(source, docStyleParsers, decl, exportedDecl, moduleBlockNode))
+                )
               )
-            )
-          } else {
-            m.namespace.set(
-              exportedDecl.id.name,
-              captureDoc(source, docStyleParsers, moduleBlockNode))
-          }
-        })
-      }
+            } else {
+              m.namespace.set(
+                exportedDecl.id.name,
+                captureDoc(source, docStyleParsers, moduleBlockNode))
+            }
+          })
+        }
+      })
     }
   })
 
diff --git a/tests/files/typescript-export-assign-merged.d.ts b/tests/files/typescript-export-assign-merged.d.ts
new file mode 100644
index 0000000000..377a10d20c
--- /dev/null
+++ b/tests/files/typescript-export-assign-merged.d.ts
@@ -0,0 +1,41 @@
+export = AssignedNamespace;
+
+declare namespace AssignedNamespace {
+  type MyType = string
+  enum MyEnum {
+    Foo,
+    Bar,
+    Baz
+  }
+}
+
+declare namespace AssignedNamespace {
+  interface Foo {
+    native: string | number
+    typedef: MyType
+    enum: MyEnum
+  }
+
+  abstract class Bar {
+    abstract foo(): Foo
+
+    method();
+  }
+
+  export function getFoo() : MyType;
+
+  export module MyModule {
+    export function ModuleFunction();
+  }
+
+  export namespace MyNamespace {
+    export function NamespaceFunction();
+
+    export module NSModule {
+      export function NSModuleFunction();
+    }
+  }
+
+  // Export-assignment exports all members in the namespace, explicitly exported or not.
+  // interface NotExported {}
+}
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 9e15a34b0a..90e07ba39b 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -284,7 +284,7 @@ ruleTester.run('named (export *)', rule, {
 
 context('Typescript', function () {
   getTSParsers().forEach((parser) => {
-    ['typescript', 'typescript-declare', 'typescript-export-assign'].forEach((source) => {
+    ['typescript', 'typescript-declare', 'typescript-export-assign', 'typescript-export-assign-merged'].forEach((source) => {
       ruleTester.run(`named`, rule, {
         valid: [
           test({

From e62011f2facc2a50206f32abb496fb7a0f774ba4 Mon Sep 17 00:00:00 2001
From: Eugene Tihonov <tihonov.ea@gmail.com>
Date: Thu, 3 Jan 2019 13:47:44 +0500
Subject: [PATCH 036/767] [Fix] `import/order`: fix autofix to not move imports
 across fn calls

Fixes #1252.

 - Reordering import statement to line below ignores uncrossable statements
 - Add more tests for ordering around function call
---
 CHANGELOG.md             |   5 +-
 src/rules/order.js       |   6 +-
 tests/src/rules/order.js | 157 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 164 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7a9c6519fc..b0f80bb8af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,14 +8,13 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Added
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
 - [`no-namespace`]: Make rule fixable ([#1401], thanks [@TrevorBurnham])
-
-### Added
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
 - [`no-extraneous-dependencies`]: Implement support for [bundledDependencies](https://npm.github.io/using-pkgs-docs/package-json/types/bundleddependencies.html) ([#1436], thanks [@schmidsi]))
 
 ### Fixed
 - `default`: make error message less confusing ([#1470], thanks [@golopot])
 - Support export of a merged typescript namespace declaration ([#1495], thanks [@benmunro])
+- [`import/order`]: fix autofix to not move imports across fn calls ([#1253], thanks [@tihonove])
 
 ## [2.18.2] - 2019-07-19
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
@@ -651,6 +650,7 @@ for info on changes for earlier releases.
 [#1290]: https://github.com/benmosher/eslint-plugin-import/pull/1290
 [#1277]: https://github.com/benmosher/eslint-plugin-import/pull/1277
 [#1257]: https://github.com/benmosher/eslint-plugin-import/pull/1257
+[#1253]: https://github.com/benmosher/eslint-plugin-import/pull/1253
 [#1235]: https://github.com/benmosher/eslint-plugin-import/pull/1235
 [#1234]: https://github.com/benmosher/eslint-plugin-import/pull/1234
 [#1232]: https://github.com/benmosher/eslint-plugin-import/pull/1232
@@ -995,3 +995,4 @@ for info on changes for earlier releases.
 [@schmidsi]: https://github.com/schmidsi
 [@TrevorBurnham]: https://github.com/TrevorBurnham
 [@benmunro]: https://github.com/benmunro
+[@tihonove]: https://github.com/tihonove
diff --git a/src/rules/order.js b/src/rules/order.js
index 3d3e1b96b7..cd3db89453 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -162,8 +162,10 @@ function canCrossNodeWhileReorder(node) {
 
 function canReorderItems(firstNode, secondNode) {
   const parent = firstNode.parent
-  const firstIndex = parent.body.indexOf(firstNode)
-  const secondIndex = parent.body.indexOf(secondNode)
+  const [firstIndex, secondIndex] = [
+    parent.body.indexOf(firstNode),
+    parent.body.indexOf(secondNode),
+  ].sort()
   const nodesBetween = parent.body.slice(firstIndex, secondIndex + 1)
   for (var nodeBetween of nodesBetween) {
     if (!canCrossNodeWhileReorder(nodeBetween)) {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 5eb5eedb85..7c441dd373 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1265,7 +1265,137 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    // reorder fix cannot cross function call on moving below #1
+    test({
+      code: `
+        const local = require('./local');
+
+        fn_call();
+
+        const global1 = require('global1');
+        const global2 = require('global2');
+
+        fn_call();
+      `,
+      output: `
+        const local = require('./local');
+
+        fn_call();
+
+        const global1 = require('global1');
+        const global2 = require('global2');
+
+        fn_call();
+      `,
+      errors: [{
+        ruleId: 'order',
+        message: '`./local` import should occur after import of `global2`',
+      }],
+    }),
+    // reorder fix cannot cross function call on moving below #2
+    test({
+      code: `
+        const local = require('./local');
+        fn_call();
+        const global1 = require('global1');
+        const global2 = require('global2');
+
+        fn_call();
+      `,
+      output: `
+        const local = require('./local');
+        fn_call();
+        const global1 = require('global1');
+        const global2 = require('global2');
+
+        fn_call();
+      `,
+      errors: [{
+        ruleId: 'order',
+        message: '`./local` import should occur after import of `global2`',
+      }],
+    }),
+    // reorder fix cannot cross function call on moving below #3
+    test({
+      code: `
+        const local1 = require('./local1');
+        const local2 = require('./local2');
+        const local3 = require('./local3');
+        const local4 = require('./local4');
+        fn_call();
+        const global1 = require('global1');
+        const global2 = require('global2');
+        const global3 = require('global3');
+        const global4 = require('global4');
+        const global5 = require('global5');
+        fn_call();
+      `,
+      output: `
+        const local1 = require('./local1');
+        const local2 = require('./local2');
+        const local3 = require('./local3');
+        const local4 = require('./local4');
+        fn_call();
+        const global1 = require('global1');
+        const global2 = require('global2');
+        const global3 = require('global3');
+        const global4 = require('global4');
+        const global5 = require('global5');
+        fn_call();
+      `,
+      errors: [
+        '`./local1` import should occur after import of `global5`',
+        '`./local2` import should occur after import of `global5`',
+        '`./local3` import should occur after import of `global5`',
+        '`./local4` import should occur after import of `global5`',
+      ],
+    }),
+    // reorder fix cannot cross function call on moving below
+    test(withoutAutofixOutput({
+      code: `
+        const local = require('./local');
+        const global1 = require('global1');
+        const global2 = require('global2');
+        fn_call();
+        const global3 = require('global3');
+
+        fn_call();
+      `,
+      errors: [{
+        ruleId: 'order',
+        message: '`./local` import should occur after import of `global3`',
+      }],
+    })),
+    // reorder fix cannot cross function call on moving below
+    // fix imports that not crosses function call only
+    test({
+      code: `
+        const local1 = require('./local1');
+        const global1 = require('global1');
+        const global2 = require('global2');
+        fn_call();
+        const local2 = require('./local2');
+        const global3 = require('global3');
+        const global4 = require('global4');
+
+        fn_call();
+      `,
+      output: `
+        const local1 = require('./local1');
+        const global1 = require('global1');
+        const global2 = require('global2');
+        fn_call();
+        const global3 = require('global3');
+        const global4 = require('global4');
+        const local2 = require('./local2');
 
+        fn_call();
+      `,
+      errors: [
+        '`./local1` import should occur after import of `global4`',
+        '`./local2` import should occur after import of `global4`',
+      ],
+    }),
     // reorder fix cannot cross non import or require
     test(withoutAutofixOutput({
       code: `
@@ -1278,6 +1408,33 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     })),
+    // reorder fix cannot cross function call on moving below (from #1252)
+    test({
+      code: `
+        const env = require('./config');
+
+        Object.keys(env);
+
+        const http = require('http');
+        const express = require('express');
+
+        http.createServer(express());
+      `,
+      output: `
+        const env = require('./config');
+
+        Object.keys(env);
+
+        const http = require('http');
+        const express = require('express');
+
+        http.createServer(express());
+      `,
+      errors: [{
+        ruleId: 'order',
+        message: '`./config` import should occur after import of `express`',
+      }],
+    }),
     // reorder cannot cross non plain requires
     test(withoutAutofixOutput({
       code: `

From b280acdce76cb209564451805687eb244ef9799d Mon Sep 17 00:00:00 2001
From: Jakob Krigovsky <jakob@krigovsky.com>
Date: Thu, 10 Oct 2019 10:14:11 +0200
Subject: [PATCH 037/767] =?UTF-8?q?Fix=20spelling=20of=20=E2=80=9CTypeScri?=
 =?UTF-8?q?pt=E2=80=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .travis.yml                              |  2 +-
 CHANGELOG.md                             | 16 ++++++++--------
 README.md                                |  2 +-
 src/rules/export.js                      |  4 ++--
 tests/dep-time-travel.sh                 |  4 ++--
 tests/src/rules/export.js                |  2 +-
 tests/src/rules/named.js                 |  2 +-
 tests/src/rules/no-deprecated.js         |  2 +-
 tests/src/rules/prefer-default-export.js |  2 +-
 utils/CHANGELOG.md                       |  2 +-
 10 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 606c355367..03c405436d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -65,7 +65,7 @@ matrix:
 
   fast_finish: true
   allow_failures:
-  # issues with typescript deps in this version intersection
+  # issues with TypeScript deps in this version intersection
   - node_js: '4'
     env: ESLINT_VERSION=4
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b0f80bb8af..1f6591aa52 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,7 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - `default`: make error message less confusing ([#1470], thanks [@golopot])
-- Support export of a merged typescript namespace declaration ([#1495], thanks [@benmunro])
+- Support export of a merged TypeScript namespace declaration ([#1495], thanks [@benmunro])
 - [`import/order`]: fix autofix to not move imports across fn calls ([#1253], thanks [@tihonove])
 
 ## [2.18.2] - 2019-07-19
@@ -25,7 +25,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
 - [`prefer-default-export`]: don't warn on TypeAlias & TSTypeAliasDeclaration ([#1377], thanks [@sharmilajesupaul])
 - [`no-unused-modules`]: Exclude package "main"/"bin"/"browser" entry points ([#1404], thanks [@rfermann])
-- [`export`]: false positive for typescript overloads ([#1412], thanks [@golopot])
+- [`export`]: false positive for TypeScript overloads ([#1412], thanks [@golopot])
 
 ### Refactors
  - [`no-extraneous-dependencies`], `importType`: remove lodash ([#1419], thanks [@ljharb])
@@ -36,7 +36,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - Support eslint v6 ([#1393], thanks [@sheepsteak])
 - [`order`]: Adds support for correctly sorting unknown types into a single group ([#1375], thanks [@swernerx])
 - [`order`]: add fixer for destructuring commonjs import ([#1372], thanks [@golopot])
-- typescript config: add TS def extensions + defer to TS over JS ([#1366], thanks [@benmosher])
+- TypeScript config: add TS def extensions + defer to TS over JS ([#1366], thanks [@benmosher])
 
 ### Fixed
 - [`no-unused-modules`]: handle ClassDeclaration ([#1371], thanks [@golopot])
@@ -54,7 +54,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: make appveyor tests passing ([#1333], thanks [@rfermann])
 - [`named`]: ignore Flow `typeof` imports and `type` exports ([#1345], thanks [@loganfsmyth])
 - [refactor] fix eslint 6 compat by fixing imports (thank [@ljharb])
-- Improve support for Typescript declare structures ([#1356], thanks [@christophercurrie])
+- Improve support for TypeScript declare structures ([#1356], thanks [@christophercurrie])
 
 ### Docs
 - add missing `no-unused-modules` in README ([#1358], thanks [@golopot])
@@ -79,7 +79,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-useless-path-segments`]: Add `noUselessIndex` option ([#1290], thanks [@timkraut])
 - [`no-duplicates`]: Add autofix ([#1312], thanks [@lydell])
 - Add [`no-unused-modules`] rule ([#1142], thanks [@rfermann])
-- support export type named exports from typescript ([#1304], thanks [@bradennapier] and [@schmod])
+- support export type named exports from TypeScript ([#1304], thanks [@bradennapier] and [@schmod])
 
 ### Fixed
 - [`order`]: Fix interpreting some external modules being interpreted as internal modules ([#793], [#794] thanks [@ephys])
@@ -88,11 +88,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`namespace`]: add check for null ExportMap ([#1235], [#1144], thanks [@ljqx])
 - [ExportMap] fix condition for checking if block comment ([#1234], [#1233], thanks [@ljqx])
 - Fix overwriting of dynamic import() CallExpression ([`no-cycle`], [`no-relative-parent-import`], [`no-unresolved`], [`no-useless-path-segments`]) ([#1218], [#1166], [#1035], thanks [@vikr01])
-- [`export`]: false positives for typescript type + value export ([#1319], thanks [@bradzacher])
-- [`export`]: Support typescript namespaces ([#1320], [#1300], thanks [@bradzacher])
+- [`export`]: false positives for TypeScript type + value export ([#1319], thanks [@bradzacher])
+- [`export`]: Support TypeScript namespaces ([#1320], [#1300], thanks [@bradzacher])
 
 ### Docs
-- Update readme for Typescript ([#1256], [#1277], thanks [@kirill-konshin])
+- Update readme for TypeScript ([#1256], [#1277], thanks [@kirill-konshin])
 - make rule names consistent ([#1112], thanks [@feychenie])
 
 ### Tests
diff --git a/README.md b/README.md
index 856baa9090..76d50f44cf 100644
--- a/README.md
+++ b/README.md
@@ -152,7 +152,7 @@ rules:
   # etc...
 ```
 
-# Typescript
+# TypeScript
 
 You may use the following shortcut or assemble your own config using the granular settings described below.
 
diff --git a/src/rules/export.js b/src/rules/export.js
index a9fba849e0..9402bc9d87 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -3,7 +3,7 @@ import docsUrl from '../docsUrl'
 import includes from 'array-includes'
 
 /*
-Notes on Typescript namespaces aka TSModuleDeclaration:
+Notes on TypeScript namespaces aka TSModuleDeclaration:
 
 There are two forms:
 - active namespaces: namespace Foo {} / module Foo {}
@@ -86,7 +86,7 @@ module.exports = {
         if (node.declaration == null) return
 
         const parent = getParent(node)
-        // support for old typescript versions
+        // support for old TypeScript versions
         const isTypeVariableDecl = node.declaration.kind === 'type'
 
         if (node.declaration.id != null) {
diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index 996ed0b1cf..078d9059b8 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -4,13 +4,13 @@
 
 npm install --no-save eslint@$ESLINT_VERSION --ignore-scripts || true
 
-# completely remove the new typescript parser for ESLint < v5
+# completely remove the new TypeScript parser for ESLint < v5
 if [[ "$ESLINT_VERSION" -lt "5" ]]; then
   echo "Removing @typescript-eslint/parser..."
   npm uninstall --no-save @typescript-eslint/parser
 fi
 
-# use these alternate typescript dependencies for ESLint < v4
+# use these alternate TypeScript dependencies for ESLint < v4
 if [[ "$ESLINT_VERSION" -lt "4" ]]; then
   echo "Downgrading babel-eslint..."
   npm i --no-save babel-eslint@8.0.3
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index a858250e2b..c7f303c4dd 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -108,7 +108,7 @@ ruleTester.run('export', rule, {
 })
 
 
-context('Typescript', function () {
+context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
       parser: parser,
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 90e07ba39b..8318066496 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -282,7 +282,7 @@ ruleTester.run('named (export *)', rule, {
 })
 
 
-context('Typescript', function () {
+context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     ['typescript', 'typescript-declare', 'typescript-export-assign', 'typescript-export-assign-merged'].forEach((source) => {
       ruleTester.run(`named`, rule, {
diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index 53f8779021..36a137f7ad 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -198,7 +198,7 @@ ruleTester.run('no-deprecated: hoisting', rule, {
   ],
 })
 
-describe('Typescript', function () {
+describe('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
       parser: parser,
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index d0b46530ab..452192737f 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -142,7 +142,7 @@ ruleTester.run('prefer-default-export', rule, {
   ],
 })
 
-context('Typescript', function() {
+context('TypeScript', function() {
   getNonDefaultParsers().forEach((parser) => {
     const parserConfig = {
       parser: parser,
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index d0b2128edc..34bae11215 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -9,7 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
  - Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
- - Improve support for Typescript declare structures ([#1356], thanks [@christophercurrie])
+ - Improve support for TypeScript declare structures ([#1356], thanks [@christophercurrie])
 
 ## v2.4.0 - 2019-04-13
 

From 112a0bf442e52b25cd7029a9905df2508e191ac1 Mon Sep 17 00:00:00 2001
From: Jakob Krigovsky <jakob@krigovsky.com>
Date: Fri, 11 Oct 2019 13:53:42 +0200
Subject: [PATCH 038/767] Fix typos

---
 tests/src/rules/order.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 7c441dd373..ff71bbed25 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -164,7 +164,7 @@ ruleTester.run('order', rule, {
         var index = require('./');
       `,
     }),
-    // Addijg unknown import types (e.g. using an resolver alias via babel) to the groups.
+    // Adding unknown import types (e.g. using a resolver alias via babel) to the groups.
     test({
       code: `
         import fs from 'fs';
@@ -175,7 +175,7 @@ ruleTester.run('order', rule, {
         groups: ['builtin', 'external', 'unknown', 'parent', 'sibling', 'index'],
       }],
     }),
-    // Using unknown import types (e.g. using an resolver alias via babel) with
+    // Using unknown import types (e.g. using a resolver alias via babel) with
     // an alternative custom group list.
     test({
       code: `
@@ -187,7 +187,7 @@ ruleTester.run('order', rule, {
         groups: [ 'unknown', 'builtin', 'external', 'parent', 'sibling', 'index' ],
       }],
     }),
-    // Using unknown import types (e.g. using an resolver alias via babel)
+    // Using unknown import types (e.g. using a resolver alias via babel)
     // Option: newlines-between: 'always'
     test({
       code: `

From 15ba863914fc041dcdc399df1a79784b0ba8354f Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Fri, 18 Oct 2019 18:03:49 +0800
Subject: [PATCH 039/767] [Fix] false positive for prefer-default-export with
 type export

---
 src/rules/prefer-default-export.js       | 8 ++++----
 tests/src/rules/prefer-default-export.js | 9 ++++++++-
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index f0af00d02b..17a07688c3 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -14,6 +14,7 @@ module.exports = {
     let specifierExportCount = 0
     let hasDefaultExport = false
     let hasStarExport = false
+    let hasTypeExport = false
     let namedExportNode = null
 
     function captureDeclaration(identifierOrPattern) {
@@ -50,9 +51,6 @@ module.exports = {
         // if there are specifiers, node.declaration should be null
         if (!node.declaration) return
 
-        // don't warn on single type aliases, declarations, or interfaces
-        if (node.exportKind === 'type') return
-
         const { type } = node.declaration
 
         if (
@@ -61,6 +59,8 @@ module.exports = {
           type === 'TSInterfaceDeclaration' ||
           type === 'InterfaceDeclaration'
         ) {
+          specifierExportCount++
+          hasTypeExport = true
           return
         }
 
@@ -86,7 +86,7 @@ module.exports = {
       },
 
       'Program:exit': function() {
-        if (specifierExportCount === 1 && !hasDefaultExport && !hasStarExport) {
+        if (specifierExportCount === 1 && !hasDefaultExport && !hasStarExport && !hasTypeExport) {
           context.report(namedExportNode, 'Prefer default export.')
         }
       },
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 452192737f..19aef41e0b 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -3,7 +3,7 @@ import { test, getNonDefaultParsers } from '../utils'
 import { RuleTester } from 'eslint'
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/prefer-default-export')
+    , rule = require('../../../src/rules/prefer-default-export')
 
 ruleTester.run('prefer-default-export', rule, {
   valid: [
@@ -194,6 +194,13 @@ context('TypeScript', function() {
           },
           parserConfig,
         ),
+        test (
+          {
+            code: 'export interface foo { bar: string; }; export function goo() {}',
+            parser,
+          },
+          parserConfig,
+        ),
       ],
       invalid: [],
     })

From a0614a7871682b33915a83e2885b5c8fc85eb1a1 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 4 Dec 2019 23:12:09 -0800
Subject: [PATCH 040/767] [meta] add missing changelog entry from #1506

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f6591aa52..ff5aeb3e05 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - `default`: make error message less confusing ([#1470], thanks [@golopot])
 - Support export of a merged TypeScript namespace declaration ([#1495], thanks [@benmunro])
 - [`import/order`]: fix autofix to not move imports across fn calls ([#1253], thanks [@tihonove])
+- [`prefer-default-export`]: fix false positive with type export ([#1506], thanks [@golopot])
 
 ## [2.18.2] - 2019-07-19
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
@@ -609,6 +610,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1506]: https://github.com/benmosher/eslint-plugin-import/pull/1506
 [#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470

From 1b96580940dd21c6e05c343496412e0e6df192c2 Mon Sep 17 00:00:00 2001
From: Brendan Abbott <brendan.abbott@shopify.com>
Date: Mon, 28 Oct 2019 12:47:46 +1000
Subject: [PATCH 041/767] [meta] Fix eslint comma-dangle violations

---
 src/rules/no-extraneous-dependencies.js |  2 +-
 tests/src/core/getExports.js            |  2 +-
 tests/src/core/resolve.js               | 32 ++++++++++++-------------
 tests/src/rules/no-duplicates.js        |  2 +-
 tests/src/rules/no-unresolved.js        |  2 +-
 5 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 1351029cc8..003e7a044f 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -23,7 +23,7 @@ function extractDepFields(pkg) {
     peerDependencies: pkg.peerDependencies || {},
     // BundledDeps should be in the form of an array, but object notation is also supported by
     // `npm`, so we convert it to an array if it is an object
-    bundledDependencies: arrayOrKeys(pkg.bundleDependencies || pkg.bundledDependencies || [])
+    bundledDependencies: arrayOrKeys(pkg.bundleDependencies || pkg.bundledDependencies || []),
   }
 }
 
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 44edcf6292..d61544e7a9 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -85,7 +85,7 @@ describe('ExportMap', function () {
     var imports = ExportMap.parse(
       path,
       contents,
-      { parserPath: 'babel-eslint', settings: {} }
+      { parserPath: 'babel-eslint', settings: {} },
     )
 
     expect(imports, 'imports').to.exist
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index 1664f8d90c..5d5bd3a206 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -16,15 +16,15 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' })
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
                       )).to.equal(utils.testFilePath('./bar.jsx'))
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
                     )).to.equal(undefined)
 
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } }),
                     )).to.equal(undefined)
   })
 
@@ -32,15 +32,15 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' })
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
                       )).to.equal(utils.testFilePath('./bar.jsx'))
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
                     )).to.equal(undefined)
 
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } }),
                     )).to.equal(undefined)
   })
 
@@ -52,12 +52,12 @@ describe('resolve', function () {
     }
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
                       )).to.equal(utils.testFilePath('./bar.jsx'))
 
     testContextReports.length = 0
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
                     )).to.equal(undefined)
     expect(testContextReports[0]).to.be.an('object')
     expect(testContextReports[0].message).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception')
@@ -65,7 +65,7 @@ describe('resolve', function () {
 
     testContextReports.length = 0
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } }),
                     )).to.equal(undefined)
     expect(testContextReports.length).to.equal(0)
   })
@@ -74,7 +74,7 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] })
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
                       )).to.equal(utils.testFilePath('./bar.jsx'))
   })
 
@@ -82,7 +82,7 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } })
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
                       )).to.equal(utils.testFilePath('./bar.jsx'))
   })
 
@@ -90,7 +90,7 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] })
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
                       )).to.equal(utils.testFilePath('./bar.jsx'))
   })
 
@@ -103,7 +103,7 @@ describe('resolve', function () {
 
     testContextReports.length = 0
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
                     )).to.equal(undefined)
     expect(testContextReports[0]).to.be.an('object')
     expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config')
@@ -119,7 +119,7 @@ describe('resolve', function () {
     }
     testContextReports.length = 0
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
                     )).to.equal(undefined)
     expect(testContextReports[0]).to.be.an('object')
     expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`)
@@ -130,7 +130,7 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }})
 
     expect(resolve( './jsx/MyCoolComponent'
-                      , testContext
+                      , testContext,
                       )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx'))
   })
 
@@ -142,7 +142,7 @@ describe('resolve', function () {
     }
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
                     )).to.equal(undefined)
     expect(testContextReports[0]).to.be.an('object')
     expect(testContextReports[0].message).to.equal('Resolve error: TEST ERROR')
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 29b080466f..a93fdfa925 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -45,7 +45,7 @@ ruleTester.run('no-duplicates', rule, {
       output: "import { x , y } from './bar'; ",
       settings: { 'import/resolve': {
         paths: [path.join( process.cwd()
-                         , 'tests', 'files'
+                         , 'tests', 'files',
                          )] }},
       errors: 2, // path ends up hardcoded
      }),
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 0c3a9008cb..cae6e8468b 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -15,7 +15,7 @@ function runResolverTests(resolver) {
   function rest(specs) {
     specs.settings = Object.assign({},
       specs.settings,
-      { 'import/resolver': resolver }
+      { 'import/resolver': resolver },
     )
 
     return test(specs)

From fb8ae719e0a8e28ef0776545ae02350a0e5e17f5 Mon Sep 17 00:00:00 2001
From: Brendan Abbott <brendan.abbott@shopify.com>
Date: Mon, 28 Oct 2019 12:05:44 +1000
Subject: [PATCH 042/767] When populating ExportMap, only load file if it's not
 ignored

---
 CHANGELOG.md     |  3 +++
 src/ExportMap.js | 13 ++++++++++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff5aeb3e05..0c893274e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - `default`: make error message less confusing ([#1470], thanks [@golopot])
+- Improve performance of `ExportMap.for` by only loading paths when necessary. ([#1519], thanks [@brendo])
 - Support export of a merged TypeScript namespace declaration ([#1495], thanks [@benmunro])
 - [`import/order`]: fix autofix to not move imports across fn calls ([#1253], thanks [@tihonove])
 - [`prefer-default-export`]: fix false positive with type export ([#1506], thanks [@golopot])
@@ -610,6 +611,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
 [#1506]: https://github.com/benmosher/eslint-plugin-import/pull/1506
 [#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
@@ -998,3 +1000,4 @@ for info on changes for earlier releases.
 [@TrevorBurnham]: https://github.com/TrevorBurnham
 [@benmunro]: https://github.com/benmunro
 [@tihonove]: https://github.com/tihonove
+[@brendo]: https://github.com/brendo
diff --git a/src/ExportMap.js b/src/ExportMap.js
index c9544c9c87..8009f8b831 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -310,11 +310,18 @@ ExportMap.for = function (context) {
     return null
   }
 
+  // check for and cache ignore
+  if (isIgnored(path, context)) {
+    log('ignored path due to ignore settings:', path)
+    exportCache.set(cacheKey, null)
+    return null
+  }
+
   const content = fs.readFileSync(path, { encoding: 'utf8' })
 
-  // check for and cache ignore
-  if (isIgnored(path, context) || !unambiguous.test(content)) {
-    log('ignored path due to unambiguous regex or ignore settings:', path)
+  // check for and cache unambigious modules
+  if (!unambiguous.test(content)) {
+    log('ignored path due to unambiguous regex:', path)
     exportCache.set(cacheKey, null)
     return null
   }

From 568ca430e3114c582e0ae49509ce294347f6e722 Mon Sep 17 00:00:00 2001
From: Kagami Sascha Rosylight <saschanaz@outlook.com>
Date: Mon, 28 Oct 2019 16:57:56 +0900
Subject: [PATCH 043/767] [Fix] `extensions`: Fix `ignorePackages` to produce
 errors

---
 CHANGELOG.md                  |  5 ++++-
 src/rules/extensions.js       |  5 +++++
 tests/src/rules/extensions.js | 24 +++++++++++++++++++++++-
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0c893274e0..33f9267854 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,11 +12,12 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-extraneous-dependencies`]: Implement support for [bundledDependencies](https://npm.github.io/using-pkgs-docs/package-json/types/bundleddependencies.html) ([#1436], thanks [@schmidsi]))
 
 ### Fixed
-- `default`: make error message less confusing ([#1470], thanks [@golopot])
+- [`default`]: make error message less confusing ([#1470], thanks [@golopot])
 - Improve performance of `ExportMap.for` by only loading paths when necessary. ([#1519], thanks [@brendo])
 - Support export of a merged TypeScript namespace declaration ([#1495], thanks [@benmunro])
 - [`import/order`]: fix autofix to not move imports across fn calls ([#1253], thanks [@tihonove])
 - [`prefer-default-export`]: fix false positive with type export ([#1506], thanks [@golopot])
+- [`extensions`]: Fix `ignorePackages` to produce errors ([#1521], thanks [@saschanaz])
 
 ## [2.18.2] - 2019-07-19
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
@@ -611,6 +612,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
 [#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
 [#1506]: https://github.com/benmosher/eslint-plugin-import/pull/1506
 [#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
@@ -1001,3 +1003,4 @@ for info on changes for earlier releases.
 [@benmunro]: https://github.com/benmunro
 [@tihonove]: https://github.com/tihonove
 [@brendo]: https://github.com/brendo
+[@saschanaz]: https://github.com/saschanaz
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index b72c91bad0..0fe605adcb 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -50,6 +50,11 @@ function buildProperties(context) {
       }
     })
 
+    if (result.defaultConfig === 'ignorePackages') {
+      result.defaultConfig = 'always'
+      result.ignorePackages = true
+    }
+
     return result
 }
 
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index d7b97bea0b..a1629335c6 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -63,7 +63,7 @@ ruleTester.run('extensions', rule, {
       code: `
         import foo from './foo.js'
         import bar from './bar.json'
-        import Component from './Component'
+        import Component from './Component.jsx'
         import express from 'express'
       `,
       options: [ 'ignorePackages' ],
@@ -309,6 +309,28 @@ ruleTester.run('extensions', rule, {
       ],
     }),
 
+    test({
+      code: `
+        import foo from './foo.js'
+        import bar from './bar.json'
+        import Component from './Component'
+        import baz from 'foo/baz'
+        import express from 'express'
+      `,
+      options: [ 'ignorePackages' ],
+      errors: [
+        {
+          message: 'Missing file extension for "./Component"',
+          line: 4,
+          column: 31,
+        }, {
+          message: 'Missing file extension for "foo/baz"',
+          line: 5,
+          column: 25,
+        },
+      ],
+    }),
+
     test({
       code: `
         import foo from './foo.js'

From 2cdfc19d44cbe4a7faa22dc00a91291340bacca5 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Fri, 18 Oct 2019 18:25:16 +0800
Subject: [PATCH 044/767] [Docs] `no-useless-path-segments`: add docs for
 option `commonjs`

---
 CHANGELOG.md                           | 4 ++++
 docs/rules/no-useless-path-segments.md | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33f9267854..81ca852140 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`prefer-default-export`]: fix false positive with type export ([#1506], thanks [@golopot])
 - [`extensions`]: Fix `ignorePackages` to produce errors ([#1521], thanks [@saschanaz])
 
+### Docs
+- [`no-useless-path-segments`]: add docs for option `commonjs` ([#1507], thanks [@golopot])
+
 ## [2.18.2] - 2019-07-19
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
 
@@ -614,6 +617,7 @@ for info on changes for earlier releases.
 
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
 [#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
+[#1507]: https://github.com/benmosher/eslint-plugin-import/pull/1507
 [#1506]: https://github.com/benmosher/eslint-plugin-import/pull/1506
 [#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
diff --git a/docs/rules/no-useless-path-segments.md b/docs/rules/no-useless-path-segments.md
index 6a02eab9fa..19b7725855 100644
--- a/docs/rules/no-useless-path-segments.md
+++ b/docs/rules/no-useless-path-segments.md
@@ -73,3 +73,7 @@ import "./pages/index.js"; // should be "./pages" (auto-fixable)
 ```
 
 Note: `noUselessIndex` only avoids ambiguous imports for `.js` files if you haven't specified other resolved file extensions. See [Settings: import/extensions](https://github.com/benmosher/eslint-plugin-import#importextensions) for details.
+
+### commonjs
+
+When set to `true`, this rule checks CommonJS imports. Default to `false`.

From c37e42f3cb9c7dc7739e052aa32b570059469362 Mon Sep 17 00:00:00 2001
From: Liqueur Librazy <im@librazy.org>
Date: Sun, 29 Sep 2019 15:36:07 +0800
Subject: [PATCH 045/767] [new] `core`: add internal-regex setting for marking
 packages as internal

---
 CHANGELOG.md                 |  3 +++
 README.md                    | 14 ++++++++++++++
 docs/rules/order.md          |  4 ++++
 src/core/importType.js       |  3 ++-
 tests/src/core/importType.js | 12 +++++++++++-
 5 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81ca852140..d075a16e3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Added
+- [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
+
 ### Added
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
 - [`no-namespace`]: Make rule fixable ([#1401], thanks [@TrevorBurnham])
diff --git a/README.md b/README.md
index 76d50f44cf..814d5fc28d 100644
--- a/README.md
+++ b/README.md
@@ -402,6 +402,20 @@ settings:
 [`eslint_d`]: https://www.npmjs.com/package/eslint_d
 [`eslint-loader`]: https://www.npmjs.com/package/eslint-loader
 
+#### `import/internal-regex`
+
+A regex for packages should be treated as internal. Useful when you are utilizing a monorepo setup or developing a set of packages that depend on each other.
+
+By default, any package referenced from [`import/external-module-folders`](#importexternal-module-folders) will be considered as "external", including packages in a monorepo like yarn workspace or lerna emvironentment. If you want to mark these packages as "internal" this will be useful.
+
+For example, if you pacakges in a monorepo are all in `@scope`, you can configure `import/internal-regex` like this
+
+```yaml
+# .eslintrc.yml
+settings:
+  import/internal-regex: ^@scope/
+```
+
 
 ## SublimeLinter-eslint
 
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 88ddca46fb..d716430481 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -168,4 +168,8 @@ import sibling from './foo';
 
 - [`import/external-module-folders`] setting
 
+- [`import/internal-regex`] setting
+
 [`import/external-module-folders`]: ../../README.md#importexternal-module-folders
+
+[`import/internal-regex`]: ../../README.md#importinternal-regex
diff --git a/src/core/importType.js b/src/core/importType.js
index b948ea2bb9..a3480ae12a 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -54,8 +54,9 @@ export function isScopedMain(name) {
 }
 
 function isInternalModule(name, settings, path) {
+  const internalScope = (settings && settings['import/internal-regex'])
   const matchesScopedOrExternalRegExp = scopedRegExp.test(name) || externalModuleRegExp.test(name)
-  return (matchesScopedOrExternalRegExp && !isExternalPath(path, name, settings))
+  return (matchesScopedOrExternalRegExp && (internalScope && new RegExp(internalScope).test(name) || !isExternalPath(path, name, settings)))
 }
 
 function isRelativeToParent(name) {
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 07466bfa92..c85124a1f4 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -51,7 +51,7 @@ describe('importType(name)', function () {
     const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
     expect(importType('@importType/index', pathContext)).to.equal('internal')
   })
-    
+
   it("should return 'internal' for internal modules that are referenced by aliases", function () {
     const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
     expect(importType('@my-alias/fn', pathContext)).to.equal('internal')
@@ -130,6 +130,16 @@ describe('importType(name)', function () {
     expect(importType('resolve', foldersContext)).to.equal('internal')
   })
 
+  it("should return 'internal' for module from 'node_modules' if its name matched 'internal-regex'", function() {
+    const foldersContext = testContext({ 'import/internal-regex': '^@org' })
+    expect(importType('@org/foobar', foldersContext)).to.equal('internal')
+  })
+
+  it("should return 'external' for module from 'node_modules' if its name did not match 'internal-regex'", function() {
+    const foldersContext = testContext({ 'import/internal-regex': '^@bar' })
+    expect(importType('@org/foobar', foldersContext)).to.equal('external')
+  })
+
   it("should return 'external' for module from 'node_modules' if 'node_modules' contained in 'external-module-folders'", function() {
     const foldersContext = testContext({ 'import/external-module-folders': ['node_modules'] })
     expect(importType('resolve', foldersContext)).to.equal('external')

From 14c71a3fde4611226320c6fc1eb6ebbb6115f61d Mon Sep 17 00:00:00 2001
From: Brett Zamir <brettz9@yahoo.com>
Date: Tue, 3 Dec 2019 12:29:23 +0800
Subject: [PATCH 046/767] [Refactor] `no-unused-modules`/`es-modules-utils`:
 Avoid superfluous calls and code

---
 CHANGELOG.md                   | 7 +++++--
 src/rules/no-unused-modules.js | 2 +-
 src/rules/order.js             | 2 +-
 utils/CHANGELOG.md             | 5 +++++
 utils/resolve.js               | 2 +-
 5 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d075a16e3c..6639a77c13 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,8 +7,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Added
 - [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
-
-### Added
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
 - [`no-namespace`]: Make rule fixable ([#1401], thanks [@TrevorBurnham])
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
@@ -25,6 +23,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Docs
 - [`no-useless-path-segments`]: add docs for option `commonjs` ([#1507], thanks [@golopot])
 
+### Changed
+- [`no-unused-modules`]/`eslint-module-utils`: Avoid superfluous calls and code ([#1551], thanks [@brettz9])
+
 ## [2.18.2] - 2019-07-19
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
 
@@ -618,6 +619,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
 [#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
 [#1507]: https://github.com/benmosher/eslint-plugin-import/pull/1507
@@ -1011,3 +1013,4 @@ for info on changes for earlier releases.
 [@tihonove]: https://github.com/tihonove
 [@brendo]: https://github.com/brendo
 [@saschanaz]: https://github.com/saschanaz
+[@brettz9]: https://github.com/brettz9
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 9cd7814754..860a73d625 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -355,7 +355,7 @@ module.exports = {
 
       exportCount.delete(EXPORT_ALL_DECLARATION)
       exportCount.delete(IMPORT_NAMESPACE_SPECIFIER)
-      if (missingExports && exportCount.size < 1) {
+      if (exportCount.size < 1) {
         // node.body[0] === 'undefined' only happens, if everything is commented out in the file
         // being linted
         context.report(node.body[0] ? node.body[0] : node, 'No exports found')
diff --git a/src/rules/order.js b/src/rules/order.js
index cd3db89453..920345ff2c 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -340,7 +340,7 @@ function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
         context.report({
           node: previousImport.node,
           message: 'There should be at least one empty line between import groups',
-          fix: fixNewLineAfterImport(context, previousImport, currentImport),
+          fix: fixNewLineAfterImport(context, previousImport),
         })
       } else if (currentImport.rank === previousImport.rank
         && emptyLinesBetween > 0
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 34bae11215..c42cbced40 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Changed
+ - Avoid superfluous calls and code ([#1551], thanks [@brettz9])
+
 ## v2.4.1 - 2019-07-19
 
 ### Fixed
@@ -52,6 +55,7 @@ Yanked due to critical issue with cache key resulting from #839.
 
 
 
+[#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
 [#1356]: https://github.com/benmosher/eslint-plugin-import/pull/1356
 [#1290]: https://github.com/benmosher/eslint-plugin-import/pull/1290
@@ -65,3 +69,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@vikr01]: https://github.com/vikr01
 [@bradzacher]: https://github.com/bradzacher
 [@christophercurrie]: https://github.com/christophercurrie
+[@brettz9]: https://github.com/brettz9
diff --git a/utils/resolve.js b/utils/resolve.js
index fdd6f1ee54..92c8f35002 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -64,7 +64,7 @@ function relative(modulePath, sourceFile, settings) {
 function fullResolve(modulePath, sourceFile, settings) {
   // check if this is a bonus core module
   const coreSet = new Set(settings['import/core-modules'])
-  if (coreSet != null && coreSet.has(modulePath)) return { found: true, path: null }
+  if (coreSet.has(modulePath)) return { found: true, path: null }
 
   const sourceDir = path.dirname(sourceFile)
       , cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath

From 05085bbdafa624d8cf6a765b9e078c41c931679b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Fermann?= <rene.fermann@gmx.de>
Date: Sun, 17 Nov 2019 10:47:01 +0100
Subject: [PATCH 047/767] [flow] `no-unused-modules`: add flow type support

---
 CHANGELOG.md                            |  2 ++
 src/rules/no-unused-modules.js          |  7 ++++--
 tests/files/no-unused-modules/flow-0.js |  1 +
 tests/files/no-unused-modules/flow-1.js |  2 ++
 tests/files/no-unused-modules/flow-2.js |  2 ++
 tests/src/rules/no-unused-modules.js    | 32 +++++++++++++++++++++++++
 6 files changed, 44 insertions(+), 2 deletions(-)
 create mode 100644 tests/files/no-unused-modules/flow-0.js
 create mode 100644 tests/files/no-unused-modules/flow-1.js
 create mode 100644 tests/files/no-unused-modules/flow-2.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6639a77c13..fc51048f3a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-namespace`]: Make rule fixable ([#1401], thanks [@TrevorBurnham])
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
 - [`no-extraneous-dependencies`]: Implement support for [bundledDependencies](https://npm.github.io/using-pkgs-docs/package-json/types/bundleddependencies.html) ([#1436], thanks [@schmidsi]))
+- [`no-unused-modules`]: add flow type support ([#1542], thanks [@rfermann])
 
 ### Fixed
 - [`default`]: make error message less confusing ([#1470], thanks [@golopot])
@@ -620,6 +621,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
+[#1542]: https://github.com/benmosher/eslint-plugin-import/pull/1542
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
 [#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
 [#1507]: https://github.com/benmosher/eslint-plugin-import/pull/1507
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 860a73d625..ccb16fd95a 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -42,6 +42,7 @@ const VARIABLE_DECLARATION = 'VariableDeclaration'
 const FUNCTION_DECLARATION = 'FunctionDeclaration'
 const CLASS_DECLARATION = 'ClassDeclaration'
 const DEFAULT = 'default'
+const TYPE_ALIAS = 'TypeAlias'
 
 let preparationDone = false
 const importList = new Map()
@@ -463,7 +464,8 @@ module.exports = {
           if (declaration) {
             if (
               declaration.type === FUNCTION_DECLARATION ||
-              declaration.type === CLASS_DECLARATION
+              declaration.type === CLASS_DECLARATION ||
+              declaration.type === TYPE_ALIAS
             ) {
               newExportIdentifiers.add(declaration.id.name)
             }
@@ -788,7 +790,8 @@ module.exports = {
         if (node.declaration) {
           if (
             node.declaration.type === FUNCTION_DECLARATION ||
-            node.declaration.type === CLASS_DECLARATION
+            node.declaration.type === CLASS_DECLARATION ||
+            node.declaration.type === TYPE_ALIAS
           ) {
             checkUsage(node, node.declaration.id.name)
           }
diff --git a/tests/files/no-unused-modules/flow-0.js b/tests/files/no-unused-modules/flow-0.js
new file mode 100644
index 0000000000..46bda68794
--- /dev/null
+++ b/tests/files/no-unused-modules/flow-0.js
@@ -0,0 +1 @@
+import { type FooType } from './flow-2';
diff --git a/tests/files/no-unused-modules/flow-1.js b/tests/files/no-unused-modules/flow-1.js
new file mode 100644
index 0000000000..bb7266d3ce
--- /dev/null
+++ b/tests/files/no-unused-modules/flow-1.js
@@ -0,0 +1,2 @@
+// @flow strict
+export type Bar = number;
diff --git a/tests/files/no-unused-modules/flow-2.js b/tests/files/no-unused-modules/flow-2.js
new file mode 100644
index 0000000000..0cbb836a6d
--- /dev/null
+++ b/tests/files/no-unused-modules/flow-2.js
@@ -0,0 +1,2 @@
+// @flow strict
+export type FooType = string;
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 792748cd86..fed0f39bb5 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -638,3 +638,35 @@ describe('do not report unused export for files mentioned in package.json', () =
     ],
   })
 })
+
+describe('correctly report flow types', () => {
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsOptions,
+        code: 'import { type FooType } from "./flow-2";',
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/flow-0.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: `// @flow strict
+               export type FooType = string;`,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/flow-2.js'),
+      }),
+    ],
+    invalid: [
+      test({
+        options: unusedExportsOptions,
+        code: `// @flow strict
+               export type Bar = string;`,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/flow-1.js'),
+        errors: [
+          error(`exported declaration 'Bar' not used within other modules`),
+        ],
+      }),
+    ],
+  })
+})

From 0cd5e438728a44b15899e0029865dfa6752170be Mon Sep 17 00:00:00 2001
From: Yoann Prot <yoann.prot@gmail.com>
Date: Tue, 8 Oct 2019 13:26:28 +0200
Subject: [PATCH 048/767] [Fix] `no-unused-modules`: fix crash due to `export
 *`

---
 CHANGELOG.md                             |  3 +++
 src/rules/no-unused-modules.js           |  9 +++++++--
 tests/files/no-unused-modules/cjs.js     |  7 +++++++
 tests/files/no-unused-modules/filte-r.js |  1 +
 tests/src/rules/no-unused-modules.js     | 16 ++++++++++++++++
 5 files changed, 34 insertions(+), 2 deletions(-)
 create mode 100644 tests/files/no-unused-modules/cjs.js
 create mode 100644 tests/files/no-unused-modules/filte-r.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc51048f3a..dbbc991db8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`import/order`]: fix autofix to not move imports across fn calls ([#1253], thanks [@tihonove])
 - [`prefer-default-export`]: fix false positive with type export ([#1506], thanks [@golopot])
 - [`extensions`]: Fix `ignorePackages` to produce errors ([#1521], thanks [@saschanaz])
+- [`no-unused-modules`]: fix crash due to `export *` ([#1496], thanks [@Taranys])
 
 ### Docs
 - [`no-useless-path-segments`]: add docs for option `commonjs` ([#1507], thanks [@golopot])
@@ -626,6 +627,7 @@ for info on changes for earlier releases.
 [#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
 [#1507]: https://github.com/benmosher/eslint-plugin-import/pull/1507
 [#1506]: https://github.com/benmosher/eslint-plugin-import/pull/1506
+[#1496]: https://github.com/benmosher/eslint-plugin-import/pull/1496
 [#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
@@ -1016,3 +1018,4 @@ for info on changes for earlier releases.
 [@brendo]: https://github.com/brendo
 [@saschanaz]: https://github.com/saschanaz
 [@brettz9]: https://github.com/brettz9
+[@Taranys]: https://github.com/Taranys
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index ccb16fd95a..9bbafe99db 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -88,8 +88,13 @@ const prepareImportsAndExports = (srcFiles, context) => {
 
       // dependencies === export * from
       const currentExportAll = new Set()
-      dependencies.forEach(value => {
-        currentExportAll.add(value().path)
+      dependencies.forEach(getDependency => {
+        const dependency = getDependency()
+        if (dependency === null) {
+          return
+        }
+
+        currentExportAll.add(dependency.path)
       })
       exportAll.set(file, currentExportAll)
 
diff --git a/tests/files/no-unused-modules/cjs.js b/tests/files/no-unused-modules/cjs.js
new file mode 100644
index 0000000000..d5d7fbb98d
--- /dev/null
+++ b/tests/files/no-unused-modules/cjs.js
@@ -0,0 +1,7 @@
+// Simple import extracted from 'redux-starter-kit' compiled file
+
+function isPlain(val) {
+  return true;
+}
+
+exports.isPlain = isPlain;
diff --git a/tests/files/no-unused-modules/filte-r.js b/tests/files/no-unused-modules/filte-r.js
new file mode 100644
index 0000000000..c5b0dbbfeb
--- /dev/null
+++ b/tests/files/no-unused-modules/filte-r.js
@@ -0,0 +1 @@
+export * from './cjs'
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index fed0f39bb5..5afae4dfac 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -453,6 +453,11 @@ describe('test behaviour for new file', () => {
       test({ options: unusedExportsOptions,
              code: `export * from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
              filename: testFilePath('./no-unused-modules/file-0.js')}),
+      // Test export * from 'external-compiled-library'
+      test({ options: unusedExportsOptions,
+        code: `export * from 'external-compiled-library'`,
+        filename: testFilePath('./no-unused-modules/file-r.js'),
+      }),
     ],
     invalid: [
       test({ options: unusedExportsOptions,
@@ -670,3 +675,14 @@ describe('correctly report flow types', () => {
     ],
   })
 })
+
+describe('Avoid errors if re-export all from umd compiled library', () => {
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({ options: unusedExportsOptions,
+        code: `export * from '${testFilePath('./no-unused-modules/bin.js')}'`,
+        filename: testFilePath('./no-unused-modules/main/index.js')}),
+    ],
+    invalid: [],
+  })
+})

From 21bf8c665f15647f8fa9651b61a5332b8c26cd83 Mon Sep 17 00:00:00 2001
From: Maxim Malov <maxmalov@users.noreply.github.com>
Date: Sat, 5 Oct 2019 14:08:07 +0600
Subject: [PATCH 049/767] [Fix] `no-cycle`: should not warn for Flow imports

---
 CHANGELOG.md                               |  3 +++
 src/ExportMap.js                           | 12 ++++++++++--
 tests/files/cycles/flow-types-depth-one.js |  6 ++++++
 tests/files/cycles/flow-types-depth-two.js |  1 +
 tests/files/cycles/flow-types.js           |  6 ++++++
 tests/src/rules/no-cycle.js                |  9 +++++++++
 6 files changed, 35 insertions(+), 2 deletions(-)
 create mode 100644 tests/files/cycles/flow-types-depth-one.js
 create mode 100644 tests/files/cycles/flow-types-depth-two.js
 create mode 100644 tests/files/cycles/flow-types.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dbbc991db8..e6995d1737 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`prefer-default-export`]: fix false positive with type export ([#1506], thanks [@golopot])
 - [`extensions`]: Fix `ignorePackages` to produce errors ([#1521], thanks [@saschanaz])
 - [`no-unused-modules`]: fix crash due to `export *` ([#1496], thanks [@Taranys])
+- [`no-cycle`]: should not warn for Flow imports ([#1494], thanks [@maxmalov])
 
 ### Docs
 - [`no-useless-path-segments`]: add docs for option `commonjs` ([#1507], thanks [@golopot])
@@ -629,6 +630,7 @@ for info on changes for earlier releases.
 [#1506]: https://github.com/benmosher/eslint-plugin-import/pull/1506
 [#1496]: https://github.com/benmosher/eslint-plugin-import/pull/1496
 [#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
+[#1494]: https://github.com/benmosher/eslint-plugin-import/pull/1494
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
 [#1436]: https://github.com/benmosher/eslint-plugin-import/pull/1436
@@ -1019,3 +1021,4 @@ for info on changes for earlier releases.
 [@saschanaz]: https://github.com/saschanaz
 [@brettz9]: https://github.com/brettz9
 [@Taranys]: https://github.com/Taranys
+[@maxmalov]: https://github.com/maxmalov
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 8009f8b831..ba455e3685 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -404,19 +404,27 @@ ExportMap.parse = function (path, content, context) {
 
   function captureDependency(declaration) {
     if (declaration.source == null) return null
+    if (declaration.importKind === 'type') return null // skip Flow type imports
     const importedSpecifiers = new Set()
     const supportedTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier'])
+    let hasImportedType = false
     if (declaration.specifiers) {
       declaration.specifiers.forEach(specifier => {
-        if (supportedTypes.has(specifier.type)) {
+        const isType = specifier.importKind === 'type'
+        hasImportedType = hasImportedType || isType
+
+        if (supportedTypes.has(specifier.type) && !isType) {
           importedSpecifiers.add(specifier.type)
         }
-        if (specifier.type === 'ImportSpecifier') {
+        if (specifier.type === 'ImportSpecifier' && !isType) {
           importedSpecifiers.add(specifier.imported.name)
         }
       })
     }
 
+    // only Flow types were imported
+    if (hasImportedType && importedSpecifiers.size === 0) return null
+
     const p = remotePath(declaration.source.value)
     if (p == null) return null
     const existing = m.imports.get(p)
diff --git a/tests/files/cycles/flow-types-depth-one.js b/tests/files/cycles/flow-types-depth-one.js
new file mode 100644
index 0000000000..f8a7a4b47c
--- /dev/null
+++ b/tests/files/cycles/flow-types-depth-one.js
@@ -0,0 +1,6 @@
+// @flow
+
+import type { FooType } from './flow-types-depth-two';
+import { type BarType, bar } from './flow-types-depth-two';
+
+export { bar }
diff --git a/tests/files/cycles/flow-types-depth-two.js b/tests/files/cycles/flow-types-depth-two.js
new file mode 100644
index 0000000000..9058840ac6
--- /dev/null
+++ b/tests/files/cycles/flow-types-depth-two.js
@@ -0,0 +1 @@
+import { foo } from './depth-one'
diff --git a/tests/files/cycles/flow-types.js b/tests/files/cycles/flow-types.js
new file mode 100644
index 0000000000..fbfb69f309
--- /dev/null
+++ b/tests/files/cycles/flow-types.js
@@ -0,0 +1,6 @@
+// @flow
+
+import type { FooType } from './flow-types-depth-two';
+import { type BarType } from './flow-types-depth-two';
+
+export const bar = 1;
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 18fe88af18..df1e6d1433 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -53,6 +53,10 @@ ruleTester.run('no-cycle', rule, {
       code: 'import type { FooType, BarType } from "./depth-one"',
       parser: require.resolve('babel-eslint'),
     }),
+    test({
+      code: 'import { bar } from "./flow-types"',
+      parser: require.resolve('babel-eslint'),
+    }),
   ],
   invalid: [
     test({
@@ -120,6 +124,11 @@ ruleTester.run('no-cycle', rule, {
       errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
       parser: require.resolve('babel-eslint'),
     }),
+    test({
+      code: 'import { bar } from "./flow-types-depth-one"',
+      parser: require.resolve('babel-eslint'),
+      errors: [error(`Dependency cycle via ./flow-types-depth-two:4=>./depth-one:1`)],
+    }),
   ],
 })
 // })

From 99b3fbf8f25686aa86ba80661e5ba94d85e8f3d3 Mon Sep 17 00:00:00 2001
From: Marcus Armstrong <marmstrong@tripadvisor.com>
Date: Mon, 2 Dec 2019 17:41:14 -0500
Subject: [PATCH 050/767] [Fix] `no-extraneous-dependencies`: Add support for
 `export from`

Fixes #1049.
---
 CHANGELOG.md                                  |  3 +++
 src/rules/no-extraneous-dependencies.js       |  6 ++++++
 tests/src/rules/no-extraneous-dependencies.js | 16 ++++++++++++++++
 3 files changed, 25 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6995d1737..ba7f308459 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+- [`no-extraneous-dependencies`]: Check `export from` ([#1049], thanks [@marcusdarmstrong])
 
 ### Added
 - [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
@@ -691,6 +692,7 @@ for info on changes for earlier releases.
 [#1093]: https://github.com/benmosher/eslint-plugin-import/pull/1093
 [#1085]: https://github.com/benmosher/eslint-plugin-import/pull/1085
 [#1068]: https://github.com/benmosher/eslint-plugin-import/pull/1068
+[#1049]: https://github.com/benmosher/eslint-plugin-import/pull/1049
 [#1046]: https://github.com/benmosher/eslint-plugin-import/pull/1046
 [#944]: https://github.com/benmosher/eslint-plugin-import/pull/944
 [#912]: https://github.com/benmosher/eslint-plugin-import/pull/912
@@ -1022,3 +1024,4 @@ for info on changes for earlier releases.
 [@brettz9]: https://github.com/brettz9
 [@Taranys]: https://github.com/Taranys
 [@maxmalov]: https://github.com/maxmalov
+[@marcusdarmstrong]: https://github.com/marcusdarmstrong
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 003e7a044f..ced0f44b60 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -205,6 +205,12 @@ module.exports = {
       ImportDeclaration: function (node) {
         reportIfMissing(context, deps, depsOptions, node, node.source.value)
       },
+      ExportNamedDeclaration: function (node) {
+        reportIfMissing(context, deps, depsOptions, node, node.source.value)
+      },
+      ExportAllDeclaration: function (node) {
+        reportIfMissing(context, deps, depsOptions, node, node.source.value)
+      },
       CallExpression: function handleRequires(node) {
         if (isStaticRequire(node)) {
           reportIfMissing(context, deps, depsOptions, node, node.arguments[0].value)
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index b50f9923b5..d29f23857f 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -122,6 +122,8 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import foo from "@generated/foo"',
       options: [{packageDir: packageDirBundledDepsRaceCondition}],
     }),
+    test({ code: 'export { foo } from "lodash.cond"' }),
+    test({ code: 'export * from "lodash.cond"' }),
   ],
   invalid: [
     test({
@@ -319,5 +321,19 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       options: [{packageDir: packageDirBundledDepsRaceCondition}],
       errors: ["'@generated/bar' should be listed in the project's dependencies. Run 'npm i -S @generated/bar' to add it"],
     }),
+    test({
+      code: 'export { foo } from "not-a-dependency";',
+      errors: [{
+        ruleId: 'no-extraneous-dependencies',
+        message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
+      }],
+    }),
+    test({
+      code: 'export * from "not-a-dependency";',
+      errors: [{
+        ruleId: 'no-extraneous-dependencies',
+        message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
+      }],
+    }),
   ],
 })

From 0426f164304d0acb2c0e241409025e63aa877e9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= <mairu@gmx.net>
Date: Thu, 20 Jun 2019 08:11:42 +0200
Subject: [PATCH 051/767] [New] `order`: add pathGroups option to add support
 to order by paths

Co-Authored-By: Matt Seccafien <matt@studiocartogram.com>
---
 CHANGELOG.md             |   4 +
 docs/rules/order.md      |  26 +++++
 src/rules/order.js       |  98 ++++++++++++++++-
 tests/src/rules/order.js | 228 ++++++++++++++++++++++++++++++++++++++-
 4 files changed, 349 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba7f308459..a6143e9159 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
 - [`no-extraneous-dependencies`]: Implement support for [bundledDependencies](https://npm.github.io/using-pkgs-docs/package-json/types/bundleddependencies.html) ([#1436], thanks [@schmidsi]))
 - [`no-unused-modules`]: add flow type support ([#1542], thanks [@rfermann])
+- [`order`]: Adds support for pathGroups to allow ordering by defined patterns ([#795], [#1386], thanks [@Mairu])
 
 ### Fixed
 - [`default`]: make error message less confusing ([#1470], thanks [@golopot])
@@ -644,6 +645,7 @@ for info on changes for earlier releases.
 [#1401]: https://github.com/benmosher/eslint-plugin-import/pull/1401
 [#1393]: https://github.com/benmosher/eslint-plugin-import/pull/1393
 [#1389]: https://github.com/benmosher/eslint-plugin-import/pull/1389
+[#1386]: https://github.com/benmosher/eslint-plugin-import/pull/1386
 [#1377]: https://github.com/benmosher/eslint-plugin-import/pull/1377
 [#1375]: https://github.com/benmosher/eslint-plugin-import/pull/1375
 [#1372]: https://github.com/benmosher/eslint-plugin-import/pull/1372
@@ -788,6 +790,7 @@ for info on changes for earlier releases.
 [#863]: https://github.com/benmosher/eslint-plugin-import/issues/863
 [#842]: https://github.com/benmosher/eslint-plugin-import/issues/842
 [#839]: https://github.com/benmosher/eslint-plugin-import/issues/839
+[#795]: https://github.com/benmosher/eslint-plugin-import/issues/795
 [#793]: https://github.com/benmosher/eslint-plugin-import/issues/793
 [#720]: https://github.com/benmosher/eslint-plugin-import/issues/720
 [#717]: https://github.com/benmosher/eslint-plugin-import/issues/717
@@ -1025,3 +1028,4 @@ for info on changes for earlier releases.
 [@Taranys]: https://github.com/Taranys
 [@maxmalov]: https://github.com/maxmalov
 [@marcusdarmstrong]: https://github.com/marcusdarmstrong
+[@Mairu]: https://github.com/Mairu
diff --git a/docs/rules/order.md b/docs/rules/order.md
index d716430481..94c0115e15 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -94,6 +94,32 @@ You can set the options like this:
 "import/order": ["error", {"groups": ["index", "sibling", "parent", "internal", "external", "builtin"]}]
 ```
 
+### `pathGroups: [array of objects]`:
+
+To be able so group by paths mostly needed with aliases pathGroups can be defined.
+
+Properties of the objects
+
+| property       | required | type   | description   |
+|----------------|:--------:|--------|---------------|
+| pattern        |     x    | string | minimatch pattern for the paths to be in this group (will not be used for builtins or externals) |
+| patternOptions |          | object | options for minimatch, default: { nocomment: true } |
+| group          |     x    | string | one of the allowed groups, the pathGroup will be positioned relative to this group |
+| position       |          | string | defines where around the group the pathGroup will be positioned, can be 'after' or 'before', if not provided pathGroup will be positioned like the group |
+
+```json
+{
+  "import/order": ["error", {
+    "pathGroups": [
+      {
+        "pattern": "~/**",
+        "group": "external"
+      }
+    ]
+  }]
+}
+```
+
 ### `newlines-between: [ignore|always|always-and-inside-groups|never]`:
 
 
diff --git a/src/rules/order.js b/src/rules/order.js
index 920345ff2c..9daeb5e8a2 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -1,5 +1,6 @@
 'use strict'
 
+import minimatch from 'minimatch'
 import importType from '../core/importType'
 import isStaticRequire from '../core/staticRequire'
 import docsUrl from '../docsUrl'
@@ -244,9 +245,29 @@ function makeOutOfOrderReport(context, imported) {
 
 // DETECTING
 
+function computePathRank(ranks, pathGroups, path, maxPosition) {
+  for (let i = 0, l = pathGroups.length; i < l; i++) {
+    const { pattern, patternOptions, group, position = 1 } = pathGroups[i]
+    if (minimatch(path, pattern, patternOptions || { nocomment: true })) {
+      return ranks[group] + (position / maxPosition)
+    }
+  }
+}
+
 function computeRank(context, ranks, name, type) {
-  return ranks[importType(name, context)] +
-    (type === 'import' ? 0 : 100)
+  const impType = importType(name, context)
+  let rank
+  if (impType !== 'builtin' && impType !== 'external') {
+    rank = computePathRank(ranks.groups, ranks.pathGroups, name, ranks.maxPosition)
+  }
+  if (!rank) {
+    rank = ranks.groups[impType]
+  }
+  if (type !== 'import') {
+    rank += 100
+  }
+
+  return rank
 }
 
 function registerNode(context, node, name, type, ranks, imported) {
@@ -294,6 +315,49 @@ function convertGroupsToRanks(groups) {
   }, rankObject)
 }
 
+function convertPathGroupsForRanks(pathGroups) {
+  const after = {}
+  const before = {}
+
+  const transformed = pathGroups.map((pathGroup, index) => {
+    const { group, position: positionString } = pathGroup
+    let position = 0
+    if (positionString === 'after') {
+      if (!after[group]) {
+        after[group] = 1
+      }
+      position = after[group]++
+    } else if (positionString === 'before') {
+      if (!before[group]) {
+        before[group] = []
+      }
+      before[group].push(index)
+    }
+
+    return Object.assign({}, pathGroup, { position })
+  })
+
+  let maxPosition = 1
+
+  Object.keys(before).forEach((group) => {
+    const groupLength = before[group].length
+    before[group].forEach((groupIndex, index) => {
+      transformed[groupIndex].position = -1 * (groupLength - index)
+    })
+    maxPosition = Math.max(maxPosition, groupLength)
+  })
+
+  Object.keys(after).forEach((key) => {
+    const groupNextPosition = after[key]
+    maxPosition = Math.max(maxPosition, groupNextPosition - 1)
+  })
+
+  return {
+    pathGroups: transformed,
+    maxPosition: maxPosition > 10 ? Math.pow(10, Math.ceil(Math.log10(maxPosition))) : 10,
+  }
+}
+
 function fixNewLineAfterImport(context, previousImport) {
   const prevRoot = findRootNode(previousImport.node)
   const tokensToEndOfLine = takeTokensAfterWhile(
@@ -378,6 +442,29 @@ module.exports = {
           groups: {
             type: 'array',
           },
+          pathGroups: {
+            type: 'array',
+            items: {
+              type: 'object',
+              properties: {
+                pattern: {
+                  type: 'string',
+                },
+                patternOptions: {
+                  type: 'object',
+                },
+                group: {
+                  type: 'string',
+                  enum: types,
+                },
+                position: {
+                  type: 'string',
+                  enum: ['after', 'before'],
+                },
+              },
+              required: ['pattern', 'group'],
+            },
+          },
           'newlines-between': {
             enum: [
               'ignore',
@@ -398,7 +485,12 @@ module.exports = {
     let ranks
 
     try {
-      ranks = convertGroupsToRanks(options.groups || defaultGroups)
+      const { pathGroups, maxPosition } = convertPathGroupsForRanks(options.pathGroups || [])
+      ranks = {
+        groups: convertGroupsToRanks(options.groups || defaultGroups),
+        pathGroups,
+        maxPosition,
+      }
     } catch (error) {
       // Malformed configuration
       return {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index ff71bbed25..669dc2dd02 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -204,6 +204,79 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+
+    // Using pathGroups to customize ordering, position 'after'
+    test({
+      code: `
+        import fs from 'fs';
+        import _ from 'lodash';
+        import { Input } from '~/components/Input';
+        import { Button } from '#/components/Button';
+        import { add } from './helper';`,
+      options: [{
+        pathGroups: [
+          { pattern: '~/**', group: 'external', position: 'after' },
+          { pattern: '#/**', group: 'external', position: 'after' },
+        ],
+      }],
+    }),
+    // pathGroup without position means "equal" with group
+    test({
+      code: `
+        import fs from 'fs';
+        import { Input } from '~/components/Input';
+        import async from 'async';
+        import { Button } from '#/components/Button';
+        import _ from 'lodash';
+        import { add } from './helper';`,
+      options: [{
+        pathGroups: [
+          { pattern: '~/**', group: 'external' },
+          { pattern: '#/**', group: 'external' },
+        ],
+      }],
+    }),
+    // Using pathGroups to customize ordering, position 'before'
+    test({
+      code: `
+        import fs from 'fs';
+
+        import { Input } from '~/components/Input';
+
+        import { Button } from '#/components/Button';
+
+        import _ from 'lodash';
+
+        import { add } from './helper';`,
+      options: [{
+        'newlines-between': 'always',
+        pathGroups: [
+          { pattern: '~/**', group: 'external', position: 'before' },
+          { pattern: '#/**', group: 'external', position: 'before' },
+        ],
+      }],
+    }),
+    // Using pathGroups to customize ordering, with patternOptions
+    test({
+      code: `
+        import fs from 'fs';
+
+        import _ from 'lodash';
+
+        import { Input } from '~/components/Input';
+
+        import { Button } from '!/components/Button';
+
+        import { add } from './helper';`,
+      options: [{
+        'newlines-between': 'always',
+        pathGroups: [
+          { pattern: '~/**', group: 'external', position: 'after' },
+          { pattern: '!/**', patternOptions: { nonegate: true }, group: 'external', position: 'after' },
+        ],
+      }],
+    }),
+
     // Option: newlines-between: 'always'
     test({
       code: `
@@ -573,7 +646,7 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     }),
-    // fix order of multile import
+    // fix order of multiline import
     test({
       code: `
         var async = require('async');
@@ -1396,6 +1469,153 @@ ruleTester.run('order', rule, {
         '`./local2` import should occur after import of `global4`',
       ],
     }),
+
+    // pathGroup with position 'after'
+    test({
+      code: `
+        import fs from 'fs';
+        import _ from 'lodash';
+        import { add } from './helper';
+        import { Input } from '~/components/Input';
+        `,
+      output: `
+        import fs from 'fs';
+        import _ from 'lodash';
+        import { Input } from '~/components/Input';
+        import { add } from './helper';
+        `,
+      options: [{
+        pathGroups: [
+          { pattern: '~/**', group: 'external', position: 'after' },
+        ],
+      }],
+      errors: [{
+        ruleId: 'order',
+        message: '`~/components/Input` import should occur before import of `./helper`',
+      }],
+    }),
+    // pathGroup without position
+    test({
+      code: `
+        import fs from 'fs';
+        import _ from 'lodash';
+        import { add } from './helper';
+        import { Input } from '~/components/Input';
+        import async from 'async';
+        `,
+      output: `
+        import fs from 'fs';
+        import _ from 'lodash';
+        import { Input } from '~/components/Input';
+        import async from 'async';
+        import { add } from './helper';
+        `,
+      options: [{
+        pathGroups: [
+          { pattern: '~/**', group: 'external' },
+        ],
+      }],
+      errors: [{
+        ruleId: 'order',
+        message: '`./helper` import should occur after import of `async`',
+      }],
+    }),
+    // pathGroup with position 'before'
+    test({
+      code: `
+        import fs from 'fs';
+        import _ from 'lodash';
+        import { add } from './helper';
+        import { Input } from '~/components/Input';
+        `,
+      output: `
+        import fs from 'fs';
+        import { Input } from '~/components/Input';
+        import _ from 'lodash';
+        import { add } from './helper';
+        `,
+      options: [{
+        pathGroups: [
+          { pattern: '~/**', group: 'external', position: 'before' },
+        ],
+      }],
+      errors: [{
+        ruleId: 'order',
+        message: '`~/components/Input` import should occur before import of `lodash`',
+      }],
+    }),
+    // multiple pathGroup with different positions for same group, fix for 'after'
+    test({
+      code: `
+        import fs from 'fs';
+        import { Import } from '$/components/Import';
+        import _ from 'lodash';
+        import { Output } from '~/components/Output';
+        import { Input } from '#/components/Input';
+        import { add } from './helper';
+        import { Export } from '-/components/Export';
+        `,
+      output: `
+        import fs from 'fs';
+        import { Export } from '-/components/Export';
+        import { Import } from '$/components/Import';
+        import _ from 'lodash';
+        import { Output } from '~/components/Output';
+        import { Input } from '#/components/Input';
+        import { add } from './helper';
+        `,
+      options: [{
+        pathGroups: [
+          { pattern: '~/**', group: 'external', position: 'after' },
+          { pattern: '#/**', group: 'external', position: 'after' },
+          { pattern: '-/**', group: 'external', position: 'before' },
+          { pattern: '$/**', group: 'external', position: 'before' },
+        ],
+      }],
+      errors: [
+        {
+          ruleId: 'order',
+          message: '`-/components/Export` import should occur before import of `$/components/Import`',
+        },
+      ],
+    }),
+
+    // multiple pathGroup with different positions for same group, fix for 'before'
+    test({
+      code: `
+        import fs from 'fs';
+        import { Export } from '-/components/Export';
+        import { Import } from '$/components/Import';
+        import _ from 'lodash';
+        import { Input } from '#/components/Input';
+        import { add } from './helper';
+        import { Output } from '~/components/Output';
+        `,
+      output: `
+        import fs from 'fs';
+        import { Export } from '-/components/Export';
+        import { Import } from '$/components/Import';
+        import _ from 'lodash';
+        import { Output } from '~/components/Output';
+        import { Input } from '#/components/Input';
+        import { add } from './helper';
+        `,
+      options: [{
+        pathGroups: [
+          { pattern: '~/**', group: 'external', position: 'after' },
+          { pattern: '#/**', group: 'external', position: 'after' },
+          { pattern: '-/**', group: 'external', position: 'before' },
+          { pattern: '$/**', group: 'external', position: 'before' },
+        ],
+      }],
+      errors: [
+        {
+          ruleId: 'order',
+          message: '`~/components/Output` import should occur before import of `#/components/Input`',
+        },
+      ],
+    }),
+
     // reorder fix cannot cross non import or require
     test(withoutAutofixOutput({
       code: `
@@ -1469,7 +1689,7 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     })),
-    // cannot require in case of not assignement require
+    // cannot require in case of not assignment require
     test(withoutAutofixOutput({
       code: `
         var async = require('async');
@@ -1493,7 +1713,7 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     })),
-    // reorder cannot cross variable assignemet (import statement)
+    // reorder cannot cross variable assignment (import statement)
     test(withoutAutofixOutput({
       code: `
         import async from 'async';
@@ -1517,7 +1737,7 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     })),
-    // cannot reorder in case of not assignement import
+    // cannot reorder in case of not assignment import
     test(withoutAutofixOutput({
       code: `
         import async from 'async';

From 2d3d045de9c1c2ee32872076f103934014e25fad Mon Sep 17 00:00:00 2001
From: AamuLumi <florian@kauder.fr>
Date: Tue, 1 Oct 2019 19:22:43 +0200
Subject: [PATCH 052/767] [fix] `importType`: Accept '@example' as internal

Fixes #1379
---
 CHANGELOG.md                 | 7 +++++--
 src/core/importType.js       | 2 +-
 tests/src/core/importType.js | 3 ++-
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6143e9159..2769c55447 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,11 +19,12 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`default`]: make error message less confusing ([#1470], thanks [@golopot])
 - Improve performance of `ExportMap.for` by only loading paths when necessary. ([#1519], thanks [@brendo])
 - Support export of a merged TypeScript namespace declaration ([#1495], thanks [@benmunro])
-- [`import/order`]: fix autofix to not move imports across fn calls ([#1253], thanks [@tihonove])
+- [`order`]: fix autofix to not move imports across fn calls ([#1253], thanks [@tihonove])
 - [`prefer-default-export`]: fix false positive with type export ([#1506], thanks [@golopot])
 - [`extensions`]: Fix `ignorePackages` to produce errors ([#1521], thanks [@saschanaz])
 - [`no-unused-modules`]: fix crash due to `export *` ([#1496], thanks [@Taranys])
 - [`no-cycle`]: should not warn for Flow imports ([#1494], thanks [@maxmalov])
+- [`order`]: fix `@someModule` considered as `unknown` instead of `internal` ([#1493], thanks [@aamulumi])
 
 ### Docs
 - [`no-useless-path-segments`]: add docs for option `commonjs` ([#1507], thanks [@golopot])
@@ -146,7 +147,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-cycle`]: ignore Flow imports ([#1126], thanks [@gajus])
 - fix Flow type imports ([#1106], thanks [@syymza])
 - [`no-relative-parent-imports`]: resolve paths ([#1135], thanks [@chrislloyd])
-- [`import/order`]: fix autofixer when using typescript-eslint-parser ([#1137], thanks [@justinanastos])
+- [`order`]: fix autofixer when using typescript-eslint-parser ([#1137], thanks [@justinanastos])
 - repeat fix from [#797] for [#717], in another place (thanks [@ljharb])
 
 ### Refactors
@@ -633,6 +634,7 @@ for info on changes for earlier releases.
 [#1496]: https://github.com/benmosher/eslint-plugin-import/pull/1496
 [#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
 [#1494]: https://github.com/benmosher/eslint-plugin-import/pull/1494
+[#1493]: https://github.com/benmosher/eslint-plugin-import/pull/1493
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
 [#1436]: https://github.com/benmosher/eslint-plugin-import/pull/1436
@@ -1029,3 +1031,4 @@ for info on changes for earlier releases.
 [@maxmalov]: https://github.com/maxmalov
 [@marcusdarmstrong]: https://github.com/marcusdarmstrong
 [@Mairu]: https://github.com/Mairu
+[@aamulumi]: https://github.com/aamulumi
diff --git a/src/core/importType.js b/src/core/importType.js
index a3480ae12a..722ce7b063 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -43,7 +43,7 @@ export function isExternalModuleMain(name, settings, path) {
   return externalModuleMainRegExp.test(name) && isExternalPath(path, name, settings)
 }
 
-const scopedRegExp = /^@[^/]+\/[^/]+/
+const scopedRegExp = /^@[^/]+\/?[^/]+/
 function isScoped(name) {
   return scopedRegExp.test(name)
 }
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index c85124a1f4..034b3cbbcf 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -30,6 +30,7 @@ describe('importType(name)', function () {
   })
 
   it("should return 'external' for scopes packages", function() {
+    expect(importType('@cycle/', context)).to.equal('external')
     expect(importType('@cycle/core', context)).to.equal('external')
     expect(importType('@cycle/dom', context)).to.equal('external')
     expect(importType('@some-thing/something', context)).to.equal('external')
@@ -55,6 +56,7 @@ describe('importType(name)', function () {
   it("should return 'internal' for internal modules that are referenced by aliases", function () {
     const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
     expect(importType('@my-alias/fn', pathContext)).to.equal('internal')
+    expect(importType('@importType', pathContext)).to.equal('internal')
   })
 
   it("should return 'internal' for aliased internal modules that look like core modules (node resolver)", function () {
@@ -96,7 +98,6 @@ describe('importType(name)', function () {
   })
 
   it("should return 'unknown' for any unhandled cases", function() {
-    expect(importType('@malformed', context)).to.equal('unknown')
     expect(importType('  /malformed', context)).to.equal('unknown')
     expect(importType('   foo', context)).to.equal('unknown')
   })

From f12ae59b9edfc5260f88b9335ff5b47f6eb958c7 Mon Sep 17 00:00:00 2001
From: Pascal Corpet <pascal@bayesimpact.org>
Date: Mon, 28 May 2018 21:51:36 +0200
Subject: [PATCH 053/767] [New] `no-duplicates`: add a considerQueryString
 option to handle false positives when using some webpack loaders.

Fixes #1107.
---
 CHANGELOG.md                     |  5 ++++-
 docs/rules/no-duplicates.md      | 25 +++++++++++++++++++++++++
 src/rules/no-duplicates.js       | 25 ++++++++++++++++++++++++-
 tests/src/rules/no-duplicates.js | 32 ++++++++++++++++++++++++++++++++
 4 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2769c55447..0ea8a264b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
-- [`no-extraneous-dependencies`]: Check `export from` ([#1049], thanks [@marcusdarmstrong])
 
 ### Added
 - [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
@@ -14,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-extraneous-dependencies`]: Implement support for [bundledDependencies](https://npm.github.io/using-pkgs-docs/package-json/types/bundleddependencies.html) ([#1436], thanks [@schmidsi]))
 - [`no-unused-modules`]: add flow type support ([#1542], thanks [@rfermann])
 - [`order`]: Adds support for pathGroups to allow ordering by defined patterns ([#795], [#1386], thanks [@Mairu])
+- [`no-duplicates`]: Add `considerQueryString` option : allow duplicate imports with different query strings ([#1107], thanks [@pcorpet]).
 
 ### Fixed
 - [`default`]: make error message less confusing ([#1470], thanks [@golopot])
@@ -25,6 +25,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: fix crash due to `export *` ([#1496], thanks [@Taranys])
 - [`no-cycle`]: should not warn for Flow imports ([#1494], thanks [@maxmalov])
 - [`order`]: fix `@someModule` considered as `unknown` instead of `internal` ([#1493], thanks [@aamulumi])
+- [`no-extraneous-dependencies`]: Check `export from` ([#1049], thanks [@marcusdarmstrong])
 
 ### Docs
 - [`no-useless-path-segments`]: add docs for option `commonjs` ([#1507], thanks [@golopot])
@@ -692,6 +693,7 @@ for info on changes for earlier releases.
 [#1126]: https://github.com/benmosher/eslint-plugin-import/pull/1126
 [#1122]: https://github.com/benmosher/eslint-plugin-import/pull/1122
 [#1112]: https://github.com/benmosher/eslint-plugin-import/pull/1112
+[#1107]: https://github.com/benmosher/eslint-plugin-import/pull/1107
 [#1106]: https://github.com/benmosher/eslint-plugin-import/pull/1106
 [#1093]: https://github.com/benmosher/eslint-plugin-import/pull/1093
 [#1085]: https://github.com/benmosher/eslint-plugin-import/pull/1085
@@ -1032,3 +1034,4 @@ for info on changes for earlier releases.
 [@marcusdarmstrong]: https://github.com/marcusdarmstrong
 [@Mairu]: https://github.com/Mairu
 [@aamulumi]: https://github.com/aamulumi
+[@pcorpet]: https://github.com/pcorpet
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index 0641e44186..f59b14d9cc 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -36,6 +36,31 @@ The motivation is that this is likely a result of two developers importing diffe
 names from the same module at different times (and potentially largely different
 locations in the file.) This rule brings both (or n-many) to attention.
 
+### Query Strings
+
+By default, this rule ignores query strings (i.e. paths followed by a question mark), and thus imports from `./mod?a` and `./mod?b` will be considered as duplicates. However you can use the option `considerQueryString` to handle them as different (primarily because browsers will resolve those imports differently).
+
+Config:
+
+```json
+"import/no-duplicates": ["error", {"considerQueryString": true}]
+```
+
+And then the following code becomes valid:
+```js
+import minifiedMod from './mod?minify'
+import noCommentsMod from './mod?comments=0'
+import originalMod from './mod'
+```
+
+It will still catch duplicates when using the same module and the exact same query string:
+```js
+import SomeDefaultClass from './mod?minify'
+
+// This is invalid, assuming `./mod` and `./mod.js` are the same target:
+import * from './mod.js?minify'
+```
+
 ## When Not To Use It
 
 If the core ESLint version is good enough (i.e. you're _not_ using Flow and you _are_ using [`import/extensions`](./extensions.md)), keep it and don't use this.
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 33e3357482..1334a12582 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -230,15 +230,38 @@ module.exports = {
       url: docsUrl('no-duplicates'),
     },
     fixable: 'code',
+    schema: [
+      {
+        type: 'object',
+        properties: {
+          considerQueryString: {
+            type: 'boolean',
+          },
+        },
+        additionalProperties: false,
+      },
+    ],
   },
 
   create: function (context) {
+    // Prepare the resolver from options.
+    const considerQueryStringOption = context.options[0] &&
+      context.options[0]['considerQueryString']
+    const defaultResolver = sourcePath => resolve(sourcePath, context) || sourcePath
+    const resolver = considerQueryStringOption ? (sourcePath => {
+      const parts = sourcePath.match(/^([^?]*)\?(.*)$/)
+      if (!parts) {
+        return defaultResolver(sourcePath)
+      }
+      return defaultResolver(parts[1]) + '?' + parts[2]
+    }) : defaultResolver
+
     const imported = new Map()
     const typesImported = new Map()
     return {
       'ImportDeclaration': function (n) {
         // resolved path will cover aliased duplicates
-        const resolvedPath = resolve(n.source.value, context) || n.source.value
+        const resolvedPath = resolver(n.source.value)
         const importMap = n.importKind === 'type' ? typesImported : imported
 
         if (importMap.has(resolvedPath)) {
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index a93fdfa925..a4c41f677a 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -25,6 +25,18 @@ ruleTester.run('no-duplicates', rule, {
       code: "import { x } from './foo'; import type { y } from './foo'",
       parser: require.resolve('babel-eslint'),
     }),
+
+    // #1107: Using different query strings that trigger different webpack loaders.
+    test({
+      code: "import x from './bar?optionX'; import y from './bar?optionY';",
+      options: [{'considerQueryString': true}],
+      settings: { 'import/resolver': 'webpack' },
+     }),
+    test({
+      code: "import x from './foo'; import y from './bar';",
+      options: [{'considerQueryString': true}],
+      settings: { 'import/resolver': 'webpack' },
+     }),
   ],
   invalid: [
     test({
@@ -50,6 +62,26 @@ ruleTester.run('no-duplicates', rule, {
       errors: 2, // path ends up hardcoded
      }),
 
+    // #1107: Using different query strings that trigger different webpack loaders.
+    test({
+      code: "import x from './bar.js?optionX'; import y from './bar?optionX';",
+      settings: { 'import/resolver': 'webpack' },
+      errors: 2, // path ends up hardcoded
+     }),
+    test({
+      code: "import x from './bar?optionX'; import y from './bar?optionY';",
+      settings: { 'import/resolver': 'webpack' },
+      errors: 2, // path ends up hardcoded
+     }),
+
+    // #1107: Using same query strings that trigger the same loader.
+    test({
+      code: "import x from './bar?optionX'; import y from './bar.js?optionX';",
+      options: [{'considerQueryString': true}],
+      settings: { 'import/resolver': 'webpack' },
+      errors: 2, // path ends up hardcoded
+     }),
+
     // #86: duplicate unresolved modules should be flagged
     test({
       code: "import foo from 'non-existent'; import bar from 'non-existent';",

From 8224e51670c636b4b2be8bb2895cd6fed79cd3d2 Mon Sep 17 00:00:00 2001
From: Duncan Beevers <duncan@dweebd.com>
Date: Thu, 17 May 2018 16:42:15 -0700
Subject: [PATCH 054/767] [New] `order`/`no-extraneous-dependencies`:
 Alphabetize imports within groups

Fixes #1406. Fixes #389. Closes #629. Closes #1105. Closes #1360.

Co-Authored-By: dannysindra <als478@cornell.edu>
Co-Authored-By: Radim Svoboda <radim.svoboda@socialbakers.com>
Co-Authored-By: Soma Lucz <luczsoma@gmail.com>
Co-Authored-By: Randall Reed, Jr <randallreedjr@gmail.com>
Co-Authored-By: Jordan Harband <ljharb@gmail.com>
---
 CHANGELOG.md             | 57 +++++++++++--------------
 docs/rules/order.md      | 34 ++++++++++++++-
 src/rules/order.js       | 85 +++++++++++++++++++++++++++++++++++--
 tests/src/rules/order.js | 91 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 230 insertions(+), 37 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ea8a264b9..c5562da2ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,10 @@
 # Change Log
+
 All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
-
 ### Added
 - [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: add flow type support ([#1542], thanks [@rfermann])
 - [`order`]: Adds support for pathGroups to allow ordering by defined patterns ([#795], [#1386], thanks [@Mairu])
 - [`no-duplicates`]: Add `considerQueryString` option : allow duplicate imports with different query strings ([#1107], thanks [@pcorpet]).
+- [`order`]: Add support for alphabetical sorting of import paths within import groups ([#1360], [#1105], [#629], thanks [@duncanbeevers], [@stropho], [@luczsoma], [@randallreedjr])
 
 ### Fixed
 - [`default`]: make error message less confusing ([#1470], thanks [@golopot])
@@ -34,10 +35,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]/`eslint-module-utils`: Avoid superfluous calls and code ([#1551], thanks [@brettz9])
 
 ## [2.18.2] - 2019-07-19
+### Fixed
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
 
 ## [2.18.1] - 2019-07-18
-
 ### Fixed
 - Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
 - [`prefer-default-export`]: don't warn on TypeAlias & TSTypeAliasDeclaration ([#1377], thanks [@sharmilajesupaul])
@@ -45,10 +46,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`export`]: false positive for TypeScript overloads ([#1412], thanks [@golopot])
 
 ### Refactors
- - [`no-extraneous-dependencies`], `importType`: remove lodash ([#1419], thanks [@ljharb])
+- [`no-extraneous-dependencies`], `importType`: remove lodash ([#1419], thanks [@ljharb])
 
 ## [2.18.0] - 2019-06-24
-
 ### Added
 - Support eslint v6 ([#1393], thanks [@sheepsteak])
 - [`order`]: Adds support for correctly sorting unknown types into a single group ([#1375], thanks [@swernerx])
@@ -63,7 +63,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-named-as-default-member`]: update broken link ([#1389], thanks [@fooloomanzoo])
 
 ## [2.17.3] - 2019-05-23
-
 ### Fixed
 - [`no-common-js`]: Also throw an error when assigning ([#1354], thanks [@charlessuh])
 - [`no-unused-modules`]: don't crash when lint file outside src-folder ([#1347], thanks [@rfermann])
@@ -76,22 +75,18 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Docs
 - add missing `no-unused-modules` in README ([#1358], thanks [@golopot])
 - [`no-unused-modules`]: Indicates usage, plugin defaults to no-op, and add description to main README.md ([#1352], thanks [@johndevedu])
-[@christophercurrie]: https://github.com/christophercurrie
 - Document `env` option for `eslint-import-resolver-webpack` ([#1363], thanks [@kgregory])
 
 ## [2.17.2] - 2019-04-16
-
 ### Fixed
 - [`no-unused-modules`]: avoid crash when using `ignoreExports`-option ([#1331], [#1323], thanks [@rfermann])
 - [`no-unused-modules`]: make sure that rule with no options will not fail ([#1330], [#1334], thanks [@kiwka])
 
 ## [2.17.1] - 2019-04-13
-
 ### Fixed
 - require v2.4 of `eslint-module-utils` ([#1322])
 
 ## [2.17.0] - 2019-04-13
-
 ### Added
 - [`no-useless-path-segments`]: Add `noUselessIndex` option ([#1290], thanks [@timkraut])
 - [`no-duplicates`]: Add autofix ([#1312], thanks [@lydell])
@@ -116,7 +111,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - fix broken tests on master ([#1295], thanks [@jeffshaver] and [@ljharb])
 - [`no-commonjs`]: add tests that show corner cases ([#1308], thanks [@TakeScoop])
 
-
 ## [2.16.0] - 2019-01-29
 ### Added
 - `typescript` config ([#1257], thanks [@kirill-konshin])
@@ -133,13 +127,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`dynamic-import-chunkname`]: Add proper webpack comment parsing ([#1163], thanks [@st-sloth])
 - [`named`]: fix destructuring assignment ([#1232], thanks [@ljqx])
 
-
 ## [2.14.0] - 2018-08-13
-*   69e0187 (HEAD -> master, source/master, origin/master, origin/HEAD) Merge pull request #1151 from jf248/jsx
-|\
-| * e30a757 (source/pr/1151, fork/jsx) Add JSX check to namespace rule
-|/
-* 8252344 (source/pr/1148) Add error to output when module loaded as resolver has invalid API
 ### Added
 - [`no-useless-path-segments`]: add commonJS (CJS) support ([#1128], thanks [@1pete])
 - [`namespace`]: add JSX check ([#1151], thanks [@jf248])
@@ -497,11 +485,10 @@ I'm seeing 62% improvement over my normal test codebase when executing only
 
 ## [1.1.0] - 2016-03-15
 ### Added
-- Added an [`ignore`](./docs/rules/no-unresolved.md#ignore) option to [`no-unresolved`] for those pesky files that no
-resolver can find. (still prefer enhancing the Webpack and Node resolvers to
-using it, though). See [#89] for details.
+- Added an [`ignore`](./docs/rules/no-unresolved.md#ignore) option to [`no-unresolved`] for those pesky files that no resolver can find. (still prefer enhancing the Webpack and Node resolvers to using it, though). See [#89] for details.
 
 ## [1.0.4] - 2016-03-11
+
 ### Changed
 - respect hoisting for deep namespaces ([`namespace`]/[`no-deprecated`]) ([#211])
 
@@ -510,39 +497,41 @@ using it, though). See [#89] for details.
 - correct cache behavior in `eslint_d` for deep namespaces ([#200])
 
 ## [1.0.3] - 2016-02-26
+
 ### Changed
 - no-deprecated follows deep namespaces ([#191])
 
 ### Fixed
-- [`namespace`] no longer flags modules with only a default export as having no
-names. (ns.default is valid ES6)
+- [`namespace`] no longer flags modules with only a default export as having no names. (ns.default is valid ES6)
 
 ## [1.0.2] - 2016-02-26
+
 ### Fixed
 - don't parse imports with no specifiers ([#192])
 
 ## [1.0.1] - 2016-02-25
+
 ### Fixed
 - export `stage-0` shared config
 - documented [`no-deprecated`]
 - deep namespaces are traversed regardless of how they get imported ([#189])
 
 ## [1.0.0] - 2016-02-24
+
 ### Added
-- [`no-deprecated`]: WIP rule to let you know at lint time if you're using
-deprecated functions, constants, classes, or modules.
+- [`no-deprecated`]: WIP rule to let you know at lint time if you're using deprecated functions, constants, classes, or modules.
 
 ### Changed
 - [`namespace`]: support deep namespaces ([#119] via [#157])
 
 ## [1.0.0-beta.0] - 2016-02-13
+
 ### Changed
 - support for (only) ESLint 2.x
-- no longer needs/refers to `import/parser` or `import/parse-options`. Instead,
-ESLint provides the configured parser + options to the rules, and they use that
-to parse dependencies.
+- no longer needs/refers to `import/parser` or `import/parse-options`. Instead, ESLint provides the configured parser + options to the rules, and they use that to parse dependencies.
 
 ### Removed
+
 - `babylon` as default import parser (see Breaking)
 
 ## [0.13.0] - 2016-02-08
@@ -562,14 +551,11 @@ Unpublished from npm and re-released as 0.13.0. See [#170].
 
 ## [0.12.0] - 2015-12-14
 ### Changed
-- Ignore [`import/ignore` setting] if exports are actually found in the parsed module. Does
-this to support use of `jsnext:main` in `node_modules` without the pain of
-managing an allow list or a nuanced deny list.
+- Ignore [`import/ignore` setting] if exports are actually found in the parsed module. Does this to support use of `jsnext:main` in `node_modules` without the pain of managing an allow list or a nuanced deny list.
 
 ## [0.11.0] - 2015-11-27
 ### Added
-- Resolver plugins. Now the linter can read Webpack config, properly follow
-aliases and ignore externals, dismisses inline loaders, etc. etc.!
+- Resolver plugins. Now the linter can read Webpack config, properly follow aliases and ignore externals, dismisses inline loaders, etc. etc.!
 
 ## Earlier releases (0.10.1 and younger)
 See [GitHub release notes](https://github.com/benmosher/eslint-plugin-import/releases?after=v0.11.0)
@@ -655,6 +641,7 @@ for info on changes for earlier releases.
 [#1371]: https://github.com/benmosher/eslint-plugin-import/pull/1371
 [#1370]: https://github.com/benmosher/eslint-plugin-import/pull/1370
 [#1363]: https://github.com/benmosher/eslint-plugin-import/pull/1363
+[#1360]: https://github.com/benmosher/eslint-plugin-import/pull/1360
 [#1358]: https://github.com/benmosher/eslint-plugin-import/pull/1358
 [#1356]: https://github.com/benmosher/eslint-plugin-import/pull/1356
 [#1354]: https://github.com/benmosher/eslint-plugin-import/pull/1354
@@ -695,6 +682,7 @@ for info on changes for earlier releases.
 [#1112]: https://github.com/benmosher/eslint-plugin-import/pull/1112
 [#1107]: https://github.com/benmosher/eslint-plugin-import/pull/1107
 [#1106]: https://github.com/benmosher/eslint-plugin-import/pull/1106
+[#1105]: https://github.com/benmosher/eslint-plugin-import/pull/1105
 [#1093]: https://github.com/benmosher/eslint-plugin-import/pull/1093
 [#1085]: https://github.com/benmosher/eslint-plugin-import/pull/1085
 [#1068]: https://github.com/benmosher/eslint-plugin-import/pull/1068
@@ -724,6 +712,7 @@ for info on changes for earlier releases.
 [#639]: https://github.com/benmosher/eslint-plugin-import/pull/639
 [#632]: https://github.com/benmosher/eslint-plugin-import/pull/632
 [#630]: https://github.com/benmosher/eslint-plugin-import/pull/630
+[#629]: https://github.com/benmosher/eslint-plugin-import/pull/629
 [#628]: https://github.com/benmosher/eslint-plugin-import/pull/628
 [#596]: https://github.com/benmosher/eslint-plugin-import/pull/596
 [#586]: https://github.com/benmosher/eslint-plugin-import/pull/586
@@ -774,7 +763,6 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
-
 [#1366]: https://github.com/benmosher/eslint-plugin-import/issues/1366
 [#1334]: https://github.com/benmosher/eslint-plugin-import/issues/1334
 [#1323]: https://github.com/benmosher/eslint-plugin-import/issues/1323
@@ -921,7 +909,6 @@ for info on changes for earlier releases.
 [0.12.1]: https://github.com/benmosher/eslint-plugin-import/compare/v0.12.0...v0.12.1
 [0.12.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.11.0...v0.12.0
 [0.11.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.10.1...v0.11.0
-
 [@mathieudutour]: https://github.com/mathieudutour
 [@gausie]: https://github.com/gausie
 [@singles]: https://github.com/singles
@@ -1035,3 +1022,7 @@ for info on changes for earlier releases.
 [@Mairu]: https://github.com/Mairu
 [@aamulumi]: https://github.com/aamulumi
 [@pcorpet]: https://github.com/pcorpet
+[@stropho]: https://github.com/stropho
+[@luczsoma]: https://github.com/luczsoma
+[@christophercurrie]: https://github.com/christophercurrie
+[@randallreedjr]: https://github.com/randallreedjr
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 94c0115e15..b5c4902ac8 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -122,7 +122,6 @@ Properties of the objects
 
 ### `newlines-between: [ignore|always|always-and-inside-groups|never]`:
 
-
 Enforces or forbids new lines between import groups:
 
 - If set to `ignore`, no errors related to new lines between import groups will be reported (default).
@@ -190,6 +189,39 @@ import index from './';
 import sibling from './foo';
 ```
 
+### `alphabetize: {order: asc|desc|ignore}`:
+
+Sort the order within each group in alphabetical manner based on **import path**:
+
+- `order`: use `asc` to sort in ascending order, and `desc` to sort in descending order (default: `ignore`).
+
+Example setting:
+```js
+alphabetize: {
+  order: 'asc', /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */
+}
+```
+
+This will fail the rule check:
+
+```js
+/* eslint import/order: ["error", {"alphabetize": true}] */
+import React, { PureComponent } from 'react';
+import aTypes from 'prop-types';
+import { compose, apply } from 'xcompose';
+import * as classnames from 'classnames';
+```
+
+While this will pass:
+
+```js
+/* eslint import/order: ["error", {"alphabetize": true}] */
+import * as classnames from 'classnames';
+import aTypes from 'prop-types';
+import React, { PureComponent } from 'react';
+import { compose, apply } from 'xcompose';
+```
+
 ## Related
 
 - [`import/external-module-folders`] setting
diff --git a/src/rules/order.js b/src/rules/order.js
index 9daeb5e8a2..b3ea8207e9 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -180,12 +180,12 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
   const sourceCode = context.getSourceCode()
 
   const firstRoot = findRootNode(firstNode.node)
-  let firstRootStart = findStartOfLineWithComments(sourceCode, firstRoot)
+  const firstRootStart = findStartOfLineWithComments(sourceCode, firstRoot)
   const firstRootEnd = findEndOfLineWithComments(sourceCode, firstRoot)
 
   const secondRoot = findRootNode(secondNode.node)
-  let secondRootStart = findStartOfLineWithComments(sourceCode, secondRoot)
-  let secondRootEnd = findEndOfLineWithComments(sourceCode, secondRoot)
+  const secondRootStart = findStartOfLineWithComments(sourceCode, secondRoot)
+  const secondRootEnd = findEndOfLineWithComments(sourceCode, secondRoot)
   const canFix = canReorderItems(firstRoot, secondRoot)
 
   let newCode = sourceCode.text.substring(secondRootStart, secondRootEnd)
@@ -243,6 +243,63 @@ function makeOutOfOrderReport(context, imported) {
   reportOutOfOrder(context, imported, outOfOrder, 'before')
 }
 
+function importsSorterAsc(importA, importB) {
+  if (importA < importB) {
+    return -1
+  }
+
+  if (importA > importB) {
+    return 1
+  }
+
+  return 0
+}
+
+function importsSorterDesc(importA, importB) {
+  if (importA < importB) {
+    return 1
+  }
+
+  if (importA > importB) {
+    return -1
+  }
+
+  return 0
+}
+
+function mutateRanksToAlphabetize(imported, order) {
+  const groupedByRanks = imported.reduce(function(acc, importedItem) {
+    if (!Array.isArray(acc[importedItem.rank])) { 
+      acc[importedItem.rank] = []
+    }
+    acc[importedItem.rank].push(importedItem.name)
+    return acc
+  }, {})
+
+  const groupRanks = Object.keys(groupedByRanks)
+
+  const sorterFn = order === 'asc' ? importsSorterAsc : importsSorterDesc
+  // sort imports locally within their group
+  groupRanks.forEach(function(groupRank) {
+    groupedByRanks[groupRank].sort(sorterFn)
+  })
+
+  // assign globally unique rank to each import
+  let newRank = 0
+  const alphabetizedRanks = groupRanks.sort().reduce(function(acc, groupRank) {
+    groupedByRanks[groupRank].forEach(function(importedItemName) {
+      acc[importedItemName] = newRank
+      newRank += 1
+    })
+    return acc
+  }, {})
+
+  // mutate the original group-rank with alphabetized-rank
+  imported.forEach(function(importedItem) {
+    importedItem.rank = alphabetizedRanks[importedItem.name]
+  })
+}
+
 // DETECTING
 
 function computePathRank(ranks, pathGroups, path, maxPosition) {
@@ -427,6 +484,13 @@ function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
   })
 }
 
+function getAlphabetizeConfig(options) {
+  const alphabetize = options.alphabetize || {}
+  const order = alphabetize.order || 'ignore'
+
+  return {order}
+}
+
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -473,6 +537,16 @@ module.exports = {
               'never',
             ],
           },
+          alphabetize: {
+            type: 'object',
+            properties: {
+              order: {
+                enum: ['ignore', 'asc', 'desc'],
+                default: 'ignore',
+              },
+            },
+            additionalProperties: false,
+          },
         },
         additionalProperties: false,
       },
@@ -482,6 +556,7 @@ module.exports = {
   create: function importOrderRule (context) {
     const options = context.options[0] || {}
     const newlinesBetweenImports = options['newlines-between'] || 'ignore'
+    const alphabetize = getAlphabetizeConfig(options)
     let ranks
 
     try {
@@ -524,6 +599,10 @@ module.exports = {
         registerNode(context, node, name, 'require', ranks, imported)
       },
       'Program:exit': function reportAndReset() {
+        if (alphabetize.order !== 'ignore') {
+          mutateRanksToAlphabetize(imported, alphabetize.order)
+        }
+
         makeOutOfOrderReport(context, imported)
 
         if (newlinesBetweenImports !== 'ignore') {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 669dc2dd02..2f67a89777 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -519,6 +519,47 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    // Option alphabetize: {order: 'ignore'}
+    test({
+      code: `
+        import a from 'foo';
+        import b from 'bar';
+
+        import index from './';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'ignore'},
+      }],
+    }),
+    // Option alphabetize: {order: 'asc'}
+    test({
+      code: `
+        import c from 'Bar';
+        import b from 'bar';
+        import a from 'foo';
+
+        import index from './';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'asc'},
+      }],
+    }),
+    // Option alphabetize: {order: 'desc'}
+    test({
+      code: `
+        import a from 'foo';
+        import b from 'bar';
+        import c from 'Bar';
+
+        import index from './';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'desc'},
+      }],
+    }),
   ],
   invalid: [
     // builtin before external module (require)
@@ -1764,5 +1805,55 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     })),
+    // Option alphabetize: {order: 'asc'}
+    test({
+      code: `
+        import b from 'bar';
+        import c from 'Bar';
+        import a from 'foo';
+
+        import index from './';
+      `,
+      output: `
+        import c from 'Bar';
+        import b from 'bar';
+        import a from 'foo';
+
+        import index from './';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'asc'},
+      }],
+      errors: [{
+        ruleID: 'order',
+        message: '`Bar` import should occur before import of `bar`',
+      }],
+    }),
+    // Option alphabetize: {order: 'desc'}
+    test({
+      code: `
+        import a from 'foo';
+        import c from 'Bar';
+        import b from 'bar';
+
+        import index from './';
+      `,
+      output: `
+        import a from 'foo';
+        import b from 'bar';
+        import c from 'Bar';
+
+        import index from './';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'desc'},
+      }],
+      errors: [{
+        ruleID: 'order',
+        message: '`bar` import should occur before import of `Bar`',
+      }],
+    }),
   ].filter((t) => !!t),
 })

From 414c9233386e5a4e525364f8a24a59b84dbae877 Mon Sep 17 00:00:00 2001
From: David Aghassi <3680126+Aghassi@users.noreply.github.com>
Date: Sat, 12 Oct 2019 00:40:20 -0700
Subject: [PATCH 055/767] [New] enable passing cwd as an option to
 `eslint-import-resolver-webpack`

This enables users to change the lookup of the webpack module
for the resolve functionality should it not be in the user's
local node_modules. This pertains to the case of a CLI where the
CLI may be in charge of webpack, and the user's repo doesn't have it.

Co-Authored-By: Jordan Harband <ljharb@gmail.com>
---
 resolvers/webpack/CHANGELOG.md    |  5 +++++
 resolvers/webpack/index.js        | 28 ++++++++++++++++++++++------
 resolvers/webpack/test/example.js |  9 +++++++++
 resolvers/webpack/test/root.js    | 11 ++++++++++-
 4 files changed, 46 insertions(+), 7 deletions(-)
 create mode 100644 resolvers/webpack/test/example.js

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 204e0224ab..45a89bf0aa 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Added
+- [New] enable passing cwd as an option to `eslint-import-resolver-webpack` ([#1503], thanks [@Aghassi])
+
 ## 0.11.1 - 2019-04-13
 
 ### Fixed
@@ -117,6 +120,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - `interpret` configs (such as `.babel.js`).
   Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
+[#1503]: https://github.com/benmosher/eslint-plugin-import/pull/1503
 [#1297]: https://github.com/benmosher/eslint-plugin-import/pull/1297
 [#1261]: https://github.com/benmosher/eslint-plugin-import/pull/1261
 [#1220]: https://github.com/benmosher/eslint-plugin-import/pull/1220
@@ -166,3 +170,4 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@mattkrick]: https://github.com/mattkrick
 [@idudinov]: https://github.com/idudinov
 [@keann]: https://github.com/keann
+[@Aghassi]: https://github.com/Aghassi
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 0f75a28400..dd3fc7a38a 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -20,7 +20,15 @@ exports.interfaceVersion = 2
  * resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js'
  * @param  {string} source - the module to resolve; i.e './some-module'
  * @param  {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js'
- * TODO: take options as a third param, with webpack config file name
+ * @param  {object} settings - the webpack config file name, as well as cwd
+ * @example
+ * options: {
+ *  // Path to the webpack config
+ *  config: 'webpack.config.js',
+ *  // Path to be used to determine where to resolve webpack from
+ *  // (may differ from the cwd in some cases)
+ *  cwd: process.cwd()
+ * }
  * @return {string?} the resolved path to source, undefined if not resolved, or null
  *                   if resolved to a non-FS resource (i.e. script tag at page load)
  */
@@ -41,6 +49,11 @@ exports.resolve = function (source, file, settings) {
   var webpackConfig
 
   var configPath = get(settings, 'config')
+    /**
+     * Attempt to set the current working directory.
+     * If none is passed, default to the `cwd` where the config is located.
+     */
+    , cwd = get(settings, 'cwd')
     , configIndex = get(settings, 'config-index')
     , env = get(settings, 'env')
     , argv = get(settings, 'argv', {})
@@ -114,7 +127,7 @@ exports.resolve = function (source, file, settings) {
   }
 
   // otherwise, resolve "normally"
-  var resolveSync = getResolveSync(configPath, webpackConfig)
+  var resolveSync = getResolveSync(configPath, webpackConfig, cwd)
 
   try {
     return { found: true, path: resolveSync(path.dirname(file), source) }
@@ -130,13 +143,13 @@ exports.resolve = function (source, file, settings) {
 
 var MAX_CACHE = 10
 var _cache = []
-function getResolveSync(configPath, webpackConfig) {
+function getResolveSync(configPath, webpackConfig, cwd) {
   var cacheKey = { configPath: configPath, webpackConfig: webpackConfig }
   var cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey) })
   if (!cached) {
     cached = {
       key: cacheKey,
-      value: createResolveSync(configPath, webpackConfig),
+      value: createResolveSync(configPath, webpackConfig, cwd),
     }
     // put in front and pop last item
     if (_cache.unshift(cached) > MAX_CACHE) {
@@ -146,15 +159,18 @@ function getResolveSync(configPath, webpackConfig) {
   return cached.value
 }
 
-function createResolveSync(configPath, webpackConfig) {
+function createResolveSync(configPath, webpackConfig, cwd) {
   var webpackRequire
     , basedir = null
 
   if (typeof configPath === 'string') {
-    basedir = path.dirname(configPath)
+    // This can be changed via the settings passed in when defining the resolver
+    basedir = cwd || configPath
+    log(`Attempting to load webpack path from ${basedir}`)
   }
 
   try {
+    // Attempt to resolve webpack from the given `basedir`
     var webpackFilename = resolve.sync('webpack', { basedir, preserveSymlinks: false })
     var webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false }
 
diff --git a/resolvers/webpack/test/example.js b/resolvers/webpack/test/example.js
new file mode 100644
index 0000000000..375f6b5a1e
--- /dev/null
+++ b/resolvers/webpack/test/example.js
@@ -0,0 +1,9 @@
+var path = require('path')
+
+var resolve = require('../index').resolve
+
+var file = path.join(__dirname, 'files', 'src', 'dummy.js')
+
+var webpackDir = path.join(__dirname, "different-package-location")
+
+console.log(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir}))
diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js
index 4839f3b894..4365720091 100644
--- a/resolvers/webpack/test/root.js
+++ b/resolvers/webpack/test/root.js
@@ -6,6 +6,7 @@ var resolve = require('../index').resolve
 
 
 var file = path.join(__dirname, 'files', 'src', 'dummy.js')
+var webpackDir = path.join(__dirname, "different-package-location")
 
 describe("root", function () {
   it("works", function () {
@@ -32,5 +33,13 @@ describe("root", function () {
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'))
   })
-
+  it("supports passing a different directory to load webpack from", function () {
+    // Webpack should still be able to resolve the config here
+    expect(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir}))
+      .property('path')
+      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
+    expect(resolve('typeahead', file, { config: "webpack.config.js", cwd: webpackDir}))
+      .property('path')
+      .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'))
+  })
 })

From a60e5c64541610df6d82eeddce6468067f770a18 Mon Sep 17 00:00:00 2001
From: Xiaoji Chen <xiaoji@uber.com>
Date: Sat, 3 Aug 2019 19:16:26 -0700
Subject: [PATCH 056/767] [New] `no-commonjs`: add `allowConditionalRequire`
 option

Fixes #1437
---
 CHANGELOG.md                   |  3 +++
 docs/rules/no-commonjs.md      | 19 +++++++++++++++++--
 src/rules/no-commonjs.js       | 30 ++++++++++++++++++++++++------
 tests/src/rules/no-commonjs.js | 20 ++++++++++++++++++++
 4 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5562da2ed..c7c96bcd43 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]: Adds support for pathGroups to allow ordering by defined patterns ([#795], [#1386], thanks [@Mairu])
 - [`no-duplicates`]: Add `considerQueryString` option : allow duplicate imports with different query strings ([#1107], thanks [@pcorpet]).
 - [`order`]: Add support for alphabetical sorting of import paths within import groups ([#1360], [#1105], [#629], thanks [@duncanbeevers], [@stropho], [@luczsoma], [@randallreedjr])
+- [`no-commonjs`]: add `allowConditionalRequire` option ([#1439], thanks [@Pessimistress])
 
 ### Fixed
 - [`default`]: make error message less confusing ([#1470], thanks [@golopot])
@@ -624,6 +625,7 @@ for info on changes for earlier releases.
 [#1493]: https://github.com/benmosher/eslint-plugin-import/pull/1493
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
+[#1439]: https://github.com/benmosher/eslint-plugin-import/pull/1439
 [#1436]: https://github.com/benmosher/eslint-plugin-import/pull/1436
 [#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
 [#1425]: https://github.com/benmosher/eslint-plugin-import/pull/1425
@@ -1026,3 +1028,4 @@ for info on changes for earlier releases.
 [@luczsoma]: https://github.com/luczsoma
 [@christophercurrie]: https://github.com/christophercurrie
 [@randallreedjr]: https://github.com/randallreedjr
+[@Pessimistress]: https://github.com/Pessimistress
diff --git a/docs/rules/no-commonjs.md b/docs/rules/no-commonjs.md
index 4353886bf7..7be4bb3993 100644
--- a/docs/rules/no-commonjs.md
+++ b/docs/rules/no-commonjs.md
@@ -27,15 +27,30 @@ If `allowRequire` option is set to `true`, `require` calls are valid:
 
 ```js
 /*eslint no-commonjs: [2, { allowRequire: true }]*/
+var mod = require('./mod');
+```
+
+but `module.exports` is reported as usual.
+
+### Allow conditional require
+
+By default, conditional requires are allowed:
+
+```js
+var a = b && require("c")
 
 if (typeof window !== "undefined") {
   require('that-ugly-thing');
 }
+
+var fs = null;
+try {
+  fs = require("fs")
+} catch (error) {}
 ```
 
-but `module.exports` is reported as usual.
+If the `allowConditionalRequire` option is set to `false`, they will be reported.
 
-This is useful for conditional requires.
 If you don't rely on synchronous module loading, check out [dynamic import](https://github.com/airbnb/babel-plugin-dynamic-import-node).
 
 ### Allow primitive modules
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index 261654bbf2..456f030f42 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -25,6 +25,26 @@ function allowRequire(node, options) {
   return options.allowRequire
 }
 
+function allowConditionalRequire(node, options) {
+  return options.allowConditionalRequire !== false
+}
+
+function validateScope(scope) {
+  return scope.variableScope.type === 'module'
+}
+
+// https://github.com/estree/estree/blob/master/es5.md
+function isConditional(node) {
+  if (
+    node.type === 'IfStatement'
+    || node.type === 'TryStatement'
+    || node.type === 'LogicalExpression'
+    || node.type === 'ConditionalExpression'
+  ) return true
+  if (node.parent) return isConditional(node.parent)
+  return false
+}
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -35,6 +55,7 @@ const schemaObject = {
   properties: {
     allowPrimitiveModules: { 'type': 'boolean' },
     allowRequire: { 'type': 'boolean' },
+    allowConditionalRequire: { 'type': 'boolean' },
   },
   additionalProperties: false,
 }
@@ -87,12 +108,7 @@ module.exports = {
 
       },
       'CallExpression': function (call) {
-        if (context.getScope().type !== 'module') return
-        if (
-          call.parent.type !== 'ExpressionStatement'
-          && call.parent.type !== 'VariableDeclarator'
-          && call.parent.type !== 'AssignmentExpression'
-        ) return
+        if (!validateScope(context.getScope())) return
 
         if (call.callee.type !== 'Identifier') return
         if (call.callee.name !== 'require') return
@@ -105,6 +121,8 @@ module.exports = {
 
         if (allowRequire(call, options)) return
 
+        if (allowConditionalRequire(call, options) && isConditional(call.parent)) return
+
         // keeping it simple: all 1-string-arg `require` calls are reported
         context.report({
           node: call.callee,
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index 8ca8fde509..1bcbc65ab3 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -56,6 +56,13 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
     { code: 'module.exports = function () {}', options: [{ allowPrimitiveModules: true }] },
     { code: 'module.exports = "foo"', options: ['allow-primitive-modules'] },
     { code: 'module.exports = "foo"', options: [{ allowPrimitiveModules: true }] },
+
+    { code: 'if (typeof window !== "undefined") require("x")', options: [{ allowRequire: true }] },
+    { code: 'if (typeof window !== "undefined") require("x")', options: [{ allowRequire: false }] },
+    { code: 'if (typeof window !== "undefined") { require("x") }', options: [{ allowRequire: true }] },
+    { code: 'if (typeof window !== "undefined") { require("x") }', options: [{ allowRequire: false }] },
+  
+    { code: 'try { require("x") } catch (error) {}' },
   ],
 
   invalid: [
@@ -65,6 +72,19 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
       { code: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
       { code: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
       { code: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+
+      { code: 'if (typeof window !== "undefined") require("x")',
+        options: [{ allowConditionalRequire: false }],
+        errors: [ { message: IMPORT_MESSAGE }],
+      },
+      { code: 'if (typeof window !== "undefined") { require("x") }',
+        options: [{ allowConditionalRequire: false }],
+        errors: [ { message: IMPORT_MESSAGE }],
+      },
+      { code: 'try { require("x") } catch (error) {}',
+        options: [{ allowConditionalRequire: false }],
+        errors: [ { message: IMPORT_MESSAGE }],
+      },
     ]),
 
     // exports

From 7190c3e927550e48d8e4e7d5383f4e1bff9253ea Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 7 Dec 2019 22:51:26 -0800
Subject: [PATCH 057/767] bump utils to v2.5.0

---
 utils/.npmrc       | 1 +
 utils/CHANGELOG.md | 7 +++++++
 utils/package.json | 4 ++--
 3 files changed, 10 insertions(+), 2 deletions(-)
 create mode 100644 utils/.npmrc

diff --git a/utils/.npmrc b/utils/.npmrc
new file mode 100644
index 0000000000..43c97e719a
--- /dev/null
+++ b/utils/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index c42cbced40..8165447b7d 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v2.5.0 - 2019-12-07
+
+### Added
+- support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
+
 ### Changed
  - Avoid superfluous calls and code ([#1551], thanks [@brettz9])
 
@@ -56,6 +61,7 @@ Yanked due to critical issue with cache key resulting from #839.
 
 
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
+[#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
 [#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
 [#1356]: https://github.com/benmosher/eslint-plugin-import/pull/1356
 [#1290]: https://github.com/benmosher/eslint-plugin-import/pull/1290
@@ -70,3 +76,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@bradzacher]: https://github.com/bradzacher
 [@christophercurrie]: https://github.com/christophercurrie
 [@brettz9]: https://github.com/brettz9
+[@JounQin]: https://github.com/JounQin
diff --git a/utils/package.json b/utils/package.json
index eaad9b2544..459f7c4388 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.4.1",
+  "version": "2.5.0",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"
@@ -25,7 +25,7 @@
   },
   "homepage": "https://github.com/benmosher/eslint-plugin-import#readme",
   "dependencies": {
-    "debug": "^2.6.8",
+    "debug": "^2.6.9",
     "pkg-dir": "^2.0.0"
   }
 }

From 3f0e8f3553266fa6abf74efd822e41e1991a20a6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 7 Dec 2019 23:19:15 -0800
Subject: [PATCH 058/767] [resolvers/node] [Deps] update `resolve`

---
 resolvers/node/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 76529084d6..aa971afa30 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -29,7 +29,7 @@
   "homepage": "https://github.com/benmosher/eslint-plugin-import",
   "dependencies": {
     "debug": "^2.6.9",
-    "resolve": "^1.10.0"
+    "resolve": "^1.13.1"
   },
   "devDependencies": {
     "chai": "^3.5.0",

From 26ad476cbc0da3469acd25a35ddac4d111fb565e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 7 Dec 2019 23:23:08 -0800
Subject: [PATCH 059/767] [resolvers/webpack] [deps] update `debug`,
 `enhanced-resolve`, `has`, `interpret`, `lodash`, `resolve`, `semver`

---
 resolvers/webpack/package.json | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 69a861c6ef..136d3b4dbf 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -31,15 +31,15 @@
   "homepage": "https://github.com/benmosher/eslint-plugin-import/tree/master/resolvers/webpack",
   "dependencies": {
     "array-find": "^1.0.0",
-    "debug": "^2.6.8",
-    "enhanced-resolve": "~0.9.0",
+    "debug": "^2.6.9",
+    "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",
-    "has": "^1.0.1",
-    "interpret": "^1.0.0",
-    "lodash": "^4.17.4",
+    "has": "^1.0.3",
+    "interpret": "^1.2.0",
+    "lodash": "^4.17.15",
     "node-libs-browser": "^1.0.0 || ^2.0.0",
-    "resolve": "^1.10.0",
-    "semver": "^5.3.0"
+    "resolve": "^1.13.1",
+    "semver": "^5.7.1"
   },
   "peerDependencies": {
     "eslint-plugin-import": ">=1.4.0",

From 47a232e5a8e9b14484d48c7ad7c1879dee1dc6bc Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 7 Dec 2019 23:25:24 -0800
Subject: [PATCH 060/767] [resolvers/webpack] v0.12.0

---
 resolvers/webpack/CHANGELOG.md | 2 ++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 45a89bf0aa..78e01348e4 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## 0.12.0 - 2019-12-07
+
 ### Added
 - [New] enable passing cwd as an option to `eslint-import-resolver-webpack` ([#1503], thanks [@Aghassi])
 
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 136d3b4dbf..924f2bca6c 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.11.1",
+  "version": "0.12.0",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 9b76635160cdbf4e0f1f34b9757da81aeb1882f9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 8 Dec 2019 15:12:53 -0800
Subject: [PATCH 061/767] Bump to v2.19.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7c96bcd43..f4b13c27c2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+
+## [2.19.0] - 2019-12-08
 ### Added
 - [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
@@ -849,7 +851,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.2...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.0...HEAD
+[2.19.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.2...v2.19.0
 [2.18.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.1...v2.18.2
 [2.18.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.0...v2.18.1
 [2.18.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.17.3...v2.18.0
diff --git a/package.json b/package.json
index cb6a1dbdbe..728758b921 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.18.2",
+  "version": "2.19.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From be7efb14e44c201faae9af39737a17d037162b37 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 8 Dec 2019 23:15:06 -0800
Subject: [PATCH 062/767] [Fix] `no-extraneous-dependencies`: ensure
 `node.source` exists

---
 src/rules/no-extraneous-dependencies.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index ced0f44b60..41ccb2a318 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -206,7 +206,9 @@ module.exports = {
         reportIfMissing(context, deps, depsOptions, node, node.source.value)
       },
       ExportNamedDeclaration: function (node) {
-        reportIfMissing(context, deps, depsOptions, node, node.source.value)
+        if (node.source) {
+          reportIfMissing(context, deps, depsOptions, node, node.source.value)
+        }
       },
       ExportAllDeclaration: function (node) {
         reportIfMissing(context, deps, depsOptions, node, node.source.value)

From bc3b034b59a034b4aa47b8a9e74f48fe0e14e997 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 8 Dec 2019 23:24:27 -0800
Subject: [PATCH 063/767] Bump to v2.19.1

---
 CHANGELOG.md | 7 ++++++-
 package.json | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f4b13c27c2..da83f13868 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.19.1] - 2019-12-08
+### Fixed
+- [`no-extraneous-dependencies`]: ensure `node.source` exists
+
 ## [2.19.0] - 2019-12-08
 ### Added
 - [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
@@ -851,7 +855,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.0...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.1...HEAD
+[2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.0...v2.19.1
 [2.19.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.2...v2.19.0
 [2.18.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.1...v2.18.2
 [2.18.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.0...v2.18.1
diff --git a/package.json b/package.json
index 728758b921..e196159744 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.19.0",
+  "version": "2.19.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 977da57a21077b108b642d984a3be580cc9c3a7b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 8 Dec 2019 23:48:38 -0800
Subject: [PATCH 064/767] [Tests] `no-extraneous-dependencies`: add test case
 for 2.19.1 fix

---
 tests/src/rules/no-extraneous-dependencies.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index d29f23857f..f3f7448053 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -124,6 +124,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({ code: 'export { foo } from "lodash.cond"' }),
     test({ code: 'export * from "lodash.cond"' }),
+    test({ code: 'export function getToken() {}' }),
   ],
   invalid: [
     test({

From 2d669b19da62e8d0d0cf8bb40f95823f49c02a94 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 9 Dec 2019 09:00:57 -0800
Subject: [PATCH 065/767] [meta] fix changelog internal-regex link

---
 CHANGELOG.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index da83f13868..18409a9c13 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,7 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [2.19.0] - 2019-12-08
 ### Added
-- [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
+- [`internal-regex` setting]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
 - [`no-namespace`]: Make rule fixable ([#1401], thanks [@TrevorBurnham])
 - support `parseForESLint` from custom parser ([#1435], thanks [@JounQin])
@@ -575,6 +575,7 @@ for info on changes for earlier releases.
 [`import/parsers` setting]: ./README.md#importparsers
 [`import/core-modules` setting]: ./README.md#importcore-modules
 [`import/external-module-folders` setting]: ./README.md#importexternal-module-folders
+[`internal-regex` setting]: ./README.md#importinternal-regex
 
 [`default`]: ./docs/rules/default.md
 [`dynamic-import-chunkname`]: ./docs/rules/dynamic-import-chunkname.md

From 614e55f8306cddd55066babcae653af9fb9ead92 Mon Sep 17 00:00:00 2001
From: AamuLumi <florian@kauder.fr>
Date: Mon, 9 Dec 2019 15:25:28 +0100
Subject: [PATCH 066/767] [Fix] `order`: Fix `alphabetize` bug with
 `newlines-between`

Fixes #1561.
---
 src/rules/order.js       |  8 ++++----
 tests/src/rules/order.js | 15 +++++++++++++++
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/rules/order.js b/src/rules/order.js
index b3ea8207e9..7a7629bf7f 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -599,16 +599,16 @@ module.exports = {
         registerNode(context, node, name, 'require', ranks, imported)
       },
       'Program:exit': function reportAndReset() {
+        if (newlinesBetweenImports !== 'ignore') {
+          makeNewlinesBetweenReport(context, imported, newlinesBetweenImports)
+        }
+
         if (alphabetize.order !== 'ignore') {
           mutateRanksToAlphabetize(imported, alphabetize.order)
         }
 
         makeOutOfOrderReport(context, imported)
 
-        if (newlinesBetweenImports !== 'ignore') {
-          makeNewlinesBetweenReport(context, imported, newlinesBetweenImports)
-        }
-
         imported = []
       },
       FunctionDeclaration: incrementLevel,
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 2f67a89777..153a923380 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -560,6 +560,21 @@ ruleTester.run('order', rule, {
         alphabetize: {order: 'desc'},
       }],
     }),
+    // Option alphabetize with newlines-between: {order: 'asc', newlines-between: 'always'}
+    test({
+      code: `
+        import b from 'Bar';
+        import c from 'bar';
+        import a from 'foo';
+
+        import index from './';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'asc'},
+        'newlines-between': 'always',
+      }],
+    }),
   ],
   invalid: [
     // builtin before external module (require)

From f507f38b5c51593e9528bbc1f54f02f747b5c966 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 9 Dec 2019 13:14:36 -0800
Subject: [PATCH 067/767] [Fix] `memo-parser`: add missing dependency

---
 memo-parser/package.json | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/memo-parser/package.json b/memo-parser/package.json
index fa7d12973e..2c81bb88a3 100644
--- a/memo-parser/package.json
+++ b/memo-parser/package.json
@@ -26,5 +26,8 @@
   "homepage": "https://github.com/benmosher/eslint-plugin-import#readme",
   "peerDependencies": {
     "eslint": ">=3.5.0"
+  },
+  "dependencies": {
+    "eslint-module-utils": "^2.5.0"
   }
 }

From e51773956a63a67eb510d34eb27d1d353b08bfd3 Mon Sep 17 00:00:00 2001
From: Kagami Sascha Rosylight <saschanaz@outlook.com>
Date: Tue, 10 Dec 2019 12:51:07 +0900
Subject: [PATCH 068/767] [Fix] `import/extensions`: ignore non-main modules

---
 CHANGELOG.md                  |  4 ++++
 src/core/importType.js        |  4 ++--
 src/rules/extensions.js       | 12 ++++++------
 tests/src/rules/extensions.js | 10 ++--------
 4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 18409a9c13..6c0bfec244 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`import/extensions`]: ignore non-main modules ([#1563], thanks [@saschanaz])
+
 ## [2.19.1] - 2019-12-08
 ### Fixed
 - [`no-extraneous-dependencies`]: ensure `node.source` exists
@@ -620,6 +623,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1563]: https://github.com/benmosher/eslint-plugin-import/pull/1563
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1542]: https://github.com/benmosher/eslint-plugin-import/pull/1542
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
diff --git a/src/core/importType.js b/src/core/importType.js
index 722ce7b063..57558cbd82 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -34,7 +34,7 @@ function isExternalPath(path, name, settings) {
 }
 
 const externalModuleRegExp = /^\w/
-function isExternalModule(name, settings, path) {
+export function isExternalModule(name, settings, path) {
   return externalModuleRegExp.test(name) && isExternalPath(path, name, settings)
 }
 
@@ -44,7 +44,7 @@ export function isExternalModuleMain(name, settings, path) {
 }
 
 const scopedRegExp = /^@[^/]+\/?[^/]+/
-function isScoped(name) {
+export function isScoped(name) {
   return scopedRegExp.test(name)
 }
 
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 0fe605adcb..c6077fb2c8 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -1,7 +1,7 @@
 import path from 'path'
 
 import resolve from 'eslint-module-utils/resolve'
-import { isBuiltIn, isExternalModuleMain, isScopedMain } from '../core/importType'
+import { isBuiltIn, isExternalModule, isScoped } from '../core/importType'
 import docsUrl from '../docsUrl'
 
 const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] }
@@ -110,8 +110,8 @@ module.exports = {
       return props.pattern[extension] || props.defaultConfig
     }
 
-    function isUseOfExtensionRequired(extension, isPackageMain) {
-      return getModifier(extension) === 'always' && (!props.ignorePackages || !isPackageMain)
+    function isUseOfExtensionRequired(extension, isPackage) {
+      return getModifier(extension) === 'always' && (!props.ignorePackages || !isPackage)
     }
 
     function isUseOfExtensionForbidden(extension) {
@@ -144,11 +144,11 @@ module.exports = {
       const extension = path.extname(resolvedPath || importPath).substring(1)
 
       // determine if this is a module
-      const isPackageMain = isExternalModuleMain(importPath, context.settings)
-        || isScopedMain(importPath)
+      const isPackage = isExternalModule(importPath, context.settings)
+        || isScoped(importPath)
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
-        const extensionRequired = isUseOfExtensionRequired(extension, isPackageMain)
+        const extensionRequired = isUseOfExtensionRequired(extension, isPackage)
         const extensionForbidden = isUseOfExtensionForbidden(extension)
         if (extensionRequired && !extensionForbidden) {
           context.report({
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index a1629335c6..720867c219 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -293,6 +293,7 @@ ruleTester.run('extensions', rule, {
         import bar from './bar.json'
         import Component from './Component'
         import baz from 'foo/baz'
+        import baw from '@scoped/baw/import'
         import express from 'express'
       `,
       options: [ 'always', {ignorePackages: true} ],
@@ -301,10 +302,6 @@ ruleTester.run('extensions', rule, {
           message: 'Missing file extension for "./Component"',
           line: 4,
           column: 31,
-        }, {
-          message: 'Missing file extension for "foo/baz"',
-          line: 5,
-          column: 25,
         },
       ],
     }),
@@ -315,6 +312,7 @@ ruleTester.run('extensions', rule, {
         import bar from './bar.json'
         import Component from './Component'
         import baz from 'foo/baz'
+        import baw from '@scoped/baw/import'
         import express from 'express'
       `,
       options: [ 'ignorePackages' ],
@@ -323,10 +321,6 @@ ruleTester.run('extensions', rule, {
           message: 'Missing file extension for "./Component"',
           line: 4,
           column: 31,
-        }, {
-          message: 'Missing file extension for "foo/baz"',
-          line: 5,
-          column: 25,
         },
       ],
     }),

From 4e8960dca0790388cde253bd2e016711b8dce21b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20S=CC=8Ctekl?= <martin.stekl@gmail.com>
Date: Mon, 9 Dec 2019 11:55:34 +0100
Subject: [PATCH 069/767] [Fix] `no-unused-modules`: fix usage of
 `import/extensions` settings

---
 CHANGELOG.md                                  |  4 ++
 src/rules/no-unused-modules.js                | 64 +++++++++++++++----
 .../no-unused-modules/jsx/file-jsx-a.jsx      |  3 +
 .../no-unused-modules/jsx/file-jsx-b.jsx      |  1 +
 .../no-unused-modules/typescript/file-ts-a.ts |  3 +
 .../no-unused-modules/typescript/file-ts-b.ts |  1 +
 tests/src/rules/no-unused-modules.js          | 64 +++++++++++++++++++
 7 files changed, 127 insertions(+), 13 deletions(-)
 create mode 100644 tests/files/no-unused-modules/jsx/file-jsx-a.jsx
 create mode 100644 tests/files/no-unused-modules/jsx/file-jsx-b.jsx
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-a.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-b.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6c0bfec244..b64f1d8240 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+### Fixed
+- [`no-unused-modules`]: fix usage of `import/extensions` settings ([#1560], thanks [@stekycz])
 
 ### Fixed
 - [`import/extensions`]: ignore non-main modules ([#1563], thanks [@saschanaz])
@@ -624,6 +626,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1563]: https://github.com/benmosher/eslint-plugin-import/pull/1563
+[#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1542]: https://github.com/benmosher/eslint-plugin-import/pull/1542
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
@@ -1042,3 +1045,4 @@ for info on changes for earlier releases.
 [@christophercurrie]: https://github.com/christophercurrie
 [@randallreedjr]: https://github.com/randallreedjr
 [@Pessimistress]: https://github.com/Pessimistress
+[@stekycz]: https://github.com/stekycz
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 9bbafe99db..5c6a73d828 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -5,6 +5,7 @@
  */
 
 import Exports from '../ExportMap'
+import { getFileExtensions } from 'eslint-module-utils/ignore'
 import resolve from 'eslint-module-utils/resolve'
 import docsUrl from '../docsUrl'
 import { dirname, join } from 'path'
@@ -16,19 +17,40 @@ import includes from 'array-includes'
 // and has been moved to eslint/lib/cli-engine/file-enumerator in version 6
 let listFilesToProcess
 try {
-  var FileEnumerator = require('eslint/lib/cli-engine/file-enumerator').FileEnumerator
-  listFilesToProcess = function (src) {
-    var e = new FileEnumerator()
+  const FileEnumerator = require('eslint/lib/cli-engine/file-enumerator').FileEnumerator
+  listFilesToProcess = function (src, extensions) {
+    const e = new FileEnumerator({
+      extensions: extensions,
+    })
     return Array.from(e.iterateFiles(src), ({ filePath, ignored }) => ({
       ignored,
       filename: filePath,
     }))
   }
 } catch (e1) {
+  // Prevent passing invalid options (extensions array) to old versions of the function.
+  // https://github.com/eslint/eslint/blob/v5.16.0/lib/util/glob-utils.js#L178-L280
+  // https://github.com/eslint/eslint/blob/v5.2.0/lib/util/glob-util.js#L174-L269
+  let originalListFilesToProcess
   try {
-    listFilesToProcess = require('eslint/lib/util/glob-utils').listFilesToProcess
+    originalListFilesToProcess = require('eslint/lib/util/glob-utils').listFilesToProcess
+    listFilesToProcess = function (src, extensions) {
+      return originalListFilesToProcess(src, {
+        extensions: extensions,
+      })
+    }
   } catch (e2) {
-    listFilesToProcess = require('eslint/lib/util/glob-util').listFilesToProcess
+    originalListFilesToProcess = require('eslint/lib/util/glob-util').listFilesToProcess
+
+    listFilesToProcess = function (src, extensions) {
+      const patterns = src.reduce((carry, pattern) => {
+        return carry.concat(extensions.map((extension) => {
+          return /\*\*|\*\./.test(pattern) ? pattern : `${pattern}/**/*${extension}`
+        }))
+      }, src.slice())
+
+      return originalListFilesToProcess(patterns)
+    }
   }
 }
 
@@ -44,7 +66,6 @@ const CLASS_DECLARATION = 'ClassDeclaration'
 const DEFAULT = 'default'
 const TYPE_ALIAS = 'TypeAlias'
 
-let preparationDone = false
 const importList = new Map()
 const exportList = new Map()
 const ignoredFiles = new Set()
@@ -59,12 +80,14 @@ const isNodeModule = path => {
  *
  * return all files matching src pattern, which are not matching the ignoreExports pattern
  */
-const resolveFiles = (src, ignoreExports) => {
+const resolveFiles = (src, ignoreExports, context) => {
+  const extensions = Array.from(getFileExtensions(context.settings))
+
   const srcFiles = new Set()
-  const srcFileList = listFilesToProcess(src)
+  const srcFileList = listFilesToProcess(src, extensions)
 
   // prepare list of ignored files
-  const ignoredFilesList =  listFilesToProcess(ignoreExports)
+  const ignoredFilesList =  listFilesToProcess(ignoreExports, extensions)
   ignoredFilesList.forEach(({ filename }) => ignoredFiles.add(filename))
 
   // prepare list of source files, don't consider files from node_modules
@@ -200,11 +223,26 @@ const getSrc = src => {
  * the start of a new eslint run
  */
 let srcFiles
+let lastPrepareKey
 const doPreparation = (src, ignoreExports, context) => {
-  srcFiles = resolveFiles(getSrc(src), ignoreExports)
+  const prepareKey = JSON.stringify({
+    src: (src || []).sort(),
+    ignoreExports: (ignoreExports || []).sort(),
+    extensions: Array.from(getFileExtensions(context.settings)).sort(),
+  })
+  if (prepareKey === lastPrepareKey) {
+    return
+  }
+
+  importList.clear()
+  exportList.clear()
+  ignoredFiles.clear()
+  filesOutsideSrc.clear()
+
+  srcFiles = resolveFiles(getSrc(src), ignoreExports, context)
   prepareImportsAndExports(srcFiles, context)
   determineUsage()
-  preparationDone = true
+  lastPrepareKey = prepareKey
 }
 
 const newNamespaceImportExists = specifiers =>
@@ -340,7 +378,7 @@ module.exports = {
       unusedExports,
     } = context.options[0] || {}
 
-    if (unusedExports && !preparationDone) {
+    if (unusedExports) {
       doPreparation(src, ignoreExports, context)
     }
 
@@ -389,7 +427,7 @@ module.exports = {
 
       // make sure file to be linted is included in source files
       if (!srcFiles.has(file)) {
-        srcFiles = resolveFiles(getSrc(src), ignoreExports)
+        srcFiles = resolveFiles(getSrc(src), ignoreExports, context)
         if (!srcFiles.has(file)) {
           filesOutsideSrc.add(file)
           return
diff --git a/tests/files/no-unused-modules/jsx/file-jsx-a.jsx b/tests/files/no-unused-modules/jsx/file-jsx-a.jsx
new file mode 100644
index 0000000000..1de6d020c8
--- /dev/null
+++ b/tests/files/no-unused-modules/jsx/file-jsx-a.jsx
@@ -0,0 +1,3 @@
+import {b} from './file-jsx-b';
+
+export const a = b + 1;
diff --git a/tests/files/no-unused-modules/jsx/file-jsx-b.jsx b/tests/files/no-unused-modules/jsx/file-jsx-b.jsx
new file mode 100644
index 0000000000..202103085c
--- /dev/null
+++ b/tests/files/no-unused-modules/jsx/file-jsx-b.jsx
@@ -0,0 +1 @@
+export const b = 2;
diff --git a/tests/files/no-unused-modules/typescript/file-ts-a.ts b/tests/files/no-unused-modules/typescript/file-ts-a.ts
new file mode 100644
index 0000000000..a4272256e6
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-a.ts
@@ -0,0 +1,3 @@
+import {b} from './file-ts-b';
+
+export const a = b + 1;
diff --git a/tests/files/no-unused-modules/typescript/file-ts-b.ts b/tests/files/no-unused-modules/typescript/file-ts-b.ts
new file mode 100644
index 0000000000..202103085c
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-b.ts
@@ -0,0 +1 @@
+export const b = 2;
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 5afae4dfac..cb3d4c103d 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -1,9 +1,13 @@
 import { test, testFilePath } from '../utils'
+import jsxConfig from '../../../config/react'
+import typescriptConfig from '../../../config/typescript'
 
 import { RuleTester } from 'eslint'
 import fs from 'fs'
 
 const ruleTester = new RuleTester()
+    , typescriptRuleTester = new RuleTester(typescriptConfig)
+    , jsxRuleTester = new RuleTester(jsxConfig)
     , rule = require('rules/no-unused-modules')
 
 const error = message => ({ ruleId: 'no-unused-modules', message })
@@ -18,6 +22,18 @@ const unusedExportsOptions = [{
   ignoreExports: [testFilePath('./no-unused-modules/*ignored*.js')],
 }]
 
+const unusedExportsTypescriptOptions = [{
+  unusedExports: true,
+  src: [testFilePath('./no-unused-modules/typescript')],
+  ignoreExports: undefined,
+}]
+
+const unusedExportsJsxOptions = [{
+  unusedExports: true,
+  src: [testFilePath('./no-unused-modules/jsx')],
+  ignoreExports: undefined,
+}]
+
 // tests for missing exports
 ruleTester.run('no-unused-modules', rule, {
   valid: [
@@ -686,3 +702,51 @@ describe('Avoid errors if re-export all from umd compiled library', () => {
     invalid: [],
   })
 })
+
+describe('correctly work with Typescript only files', () => {
+  typescriptRuleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsTypescriptOptions,
+        code: 'import a from "file-ts-a";',
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      }),
+    ],
+    invalid: [
+      test({
+        options: unusedExportsTypescriptOptions,
+        code: `export const b = 2;`,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'),
+        errors: [
+          error(`exported declaration 'b' not used within other modules`),
+        ],
+      }),
+    ],
+  })
+})
+
+describe('correctly work with JSX only files', () => {
+  jsxRuleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsJsxOptions,
+        code: 'import a from "file-jsx-a";',
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/jsx/file-jsx-a.jsx'),
+      }),
+    ],
+    invalid: [
+      test({
+        options: unusedExportsJsxOptions,
+        code: `export const b = 2;`,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/jsx/file-jsx-b.jsx'),
+        errors: [
+          error(`exported declaration 'b' not used within other modules`),
+        ],
+      }),
+    ],
+  })
+})

From c28fa7cc8af6c2277fa697212e9de7362bb1cd60 Mon Sep 17 00:00:00 2001
From: dbrewer5 <damonbrewer7@gmail.com>
Date: Thu, 26 Dec 2019 17:05:14 -0800
Subject: [PATCH 070/767] [New] `order`: added `caseInsensitive` as an
 additional option to `alphabetize`

 - imp: mutateRanksToAlphabetizeV2 added to handle case insensitive sorting
 - tests: add two test cases for alphabetize.caseInsensitive: true
 - docs: added documentation for new options: alphabetize.caseInsensitive
 - imp: merged mutateRanksToAlphabetizeV2 to original
 - changelog: updated with caseInsensitive addition
---
 CHANGELOG.md             |  5 +++++
 docs/rules/order.md      |  6 +++++-
 src/rules/order.js       | 16 +++++++++-----
 tests/src/rules/order.js | 46 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b64f1d8240..cbd12b251a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+### Added
+- [`order`]: added `caseInsensitive` as an additional option to `alphabetize` ([#1586], thanks [@dbrewer5])
+
 ### Fixed
 - [`no-unused-modules`]: fix usage of `import/extensions` settings ([#1560], thanks [@stekycz])
 
@@ -625,6 +628,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
 [#1563]: https://github.com/benmosher/eslint-plugin-import/pull/1563
 [#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
@@ -1046,3 +1050,4 @@ for info on changes for earlier releases.
 [@randallreedjr]: https://github.com/randallreedjr
 [@Pessimistress]: https://github.com/Pessimistress
 [@stekycz]: https://github.com/stekycz
+[@dbrewer5]: https://github.com/dbrewer5
diff --git a/docs/rules/order.md b/docs/rules/order.md
index b5c4902ac8..8012e637f7 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -189,16 +189,18 @@ import index from './';
 import sibling from './foo';
 ```
 
-### `alphabetize: {order: asc|desc|ignore}`:
+### `alphabetize: {order: asc|desc|ignore, caseInsensitive: true|false}`:
 
 Sort the order within each group in alphabetical manner based on **import path**:
 
 - `order`: use `asc` to sort in ascending order, and `desc` to sort in descending order (default: `ignore`).
+- `caseInsensitive`: use `true` to ignore case, and `false` to consider case (default: `false`).
 
 Example setting:
 ```js
 alphabetize: {
   order: 'asc', /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */
+  caseInsensitive: true /* ignore case. Options: [true, false] */
 }
 ```
 
@@ -210,12 +212,14 @@ import React, { PureComponent } from 'react';
 import aTypes from 'prop-types';
 import { compose, apply } from 'xcompose';
 import * as classnames from 'classnames';
+import blist from 'BList';
 ```
 
 While this will pass:
 
 ```js
 /* eslint import/order: ["error", {"alphabetize": true}] */
+import blist from 'BList';
 import * as classnames from 'classnames';
 import aTypes from 'prop-types';
 import React, { PureComponent } from 'react';
diff --git a/src/rules/order.js b/src/rules/order.js
index 7a7629bf7f..a842f60afb 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -267,7 +267,7 @@ function importsSorterDesc(importA, importB) {
   return 0
 }
 
-function mutateRanksToAlphabetize(imported, order) {
+function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
   const groupedByRanks = imported.reduce(function(acc, importedItem) {
     if (!Array.isArray(acc[importedItem.rank])) { 
       acc[importedItem.rank] = []
@@ -278,10 +278,11 @@ function mutateRanksToAlphabetize(imported, order) {
 
   const groupRanks = Object.keys(groupedByRanks)
 
-  const sorterFn = order === 'asc' ? importsSorterAsc : importsSorterDesc
+  const sorterFn = alphabetizeOptions.order === 'asc' ? importsSorterAsc : importsSorterDesc
+  const comparator = alphabetizeOptions.caseInsensitive ? (a, b) => sorterFn(String(a).toLowerCase(), String(b).toLowerCase()) : (a, b) => sorterFn(a, b)
   // sort imports locally within their group
   groupRanks.forEach(function(groupRank) {
-    groupedByRanks[groupRank].sort(sorterFn)
+    groupedByRanks[groupRank].sort(comparator)
   })
 
   // assign globally unique rank to each import
@@ -487,8 +488,9 @@ function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
 function getAlphabetizeConfig(options) {
   const alphabetize = options.alphabetize || {}
   const order = alphabetize.order || 'ignore'
+  const caseInsensitive = alphabetize.caseInsensitive || false
 
-  return {order}
+  return {order, caseInsensitive}
 }
 
 module.exports = {
@@ -540,6 +542,10 @@ module.exports = {
           alphabetize: {
             type: 'object',
             properties: {
+              caseInsensitive: {
+                type: 'boolean',
+                default: false,
+              },
               order: {
                 enum: ['ignore', 'asc', 'desc'],
                 default: 'ignore',
@@ -604,7 +610,7 @@ module.exports = {
         }
 
         if (alphabetize.order !== 'ignore') {
-          mutateRanksToAlphabetize(imported, alphabetize.order)
+          mutateRanksToAlphabetize(imported, alphabetize)
         }
 
         makeOutOfOrderReport(context, imported)
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 153a923380..11309f933b 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1870,5 +1870,51 @@ ruleTester.run('order', rule, {
         message: '`bar` import should occur before import of `Bar`',
       }],
     }),
+    // Option alphabetize {order: 'asc': caseInsensitive: true}
+    test({
+      code: `
+        import b from 'foo';
+        import a from 'Bar';
+
+        import index from './';
+      `,
+      output: `
+        import a from 'Bar';
+        import b from 'foo';
+
+        import index from './';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'asc', caseInsensitive: true},
+      }],
+      errors: [{
+        ruleID: 'order',
+        message: '`Bar` import should occur before import of `foo`',
+      }],
+    }),
+    // Option alphabetize {order: 'desc': caseInsensitive: true}
+    test({
+      code: `
+        import a from 'Bar';
+        import b from 'foo';
+
+        import index from './';
+      `,
+      output: `
+        import b from 'foo';
+        import a from 'Bar';
+
+        import index from './';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'desc', caseInsensitive: true},
+      }],
+      errors: [{
+        ruleID: 'order',
+        message: '`foo` import should occur before import of `Bar`',
+      }],
+    }),
   ].filter((t) => !!t),
 })

From 078b6f746b5766511822a95b54c280e900028d1f Mon Sep 17 00:00:00 2001
From: Ross Solomon <ross.solomon@airbnb.com>
Date: Mon, 19 Nov 2018 17:33:51 -0800
Subject: [PATCH 071/767] [New] `no-restricted-paths`: Allow exceptions to
 zones

 - Make exceptions relative to from paths, plus enforcement
---
 CHANGELOG.md                                 |  3 ++
 docs/rules/no-restricted-paths.md            | 42 ++++++++++++++-
 src/rules/no-restricted-paths.js             | 53 +++++++++++++++++--
 tests/files/restricted-paths/server/one/a.js |  0
 tests/files/restricted-paths/server/one/b.js |  0
 tests/files/restricted-paths/server/two/a.js |  0
 tests/src/rules/no-restricted-paths.js       | 55 ++++++++++++++++++++
 7 files changed, 147 insertions(+), 6 deletions(-)
 create mode 100644 tests/files/restricted-paths/server/one/a.js
 create mode 100644 tests/files/restricted-paths/server/one/b.js
 create mode 100644 tests/files/restricted-paths/server/two/a.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cbd12b251a..ae9f5bca7e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 ### Added
 - [`order`]: added `caseInsensitive` as an additional option to `alphabetize` ([#1586], thanks [@dbrewer5])
+- [`no-restricted-paths`]: New `except` option per `zone`, allowing exceptions to be defined for a restricted zone ([#1238], thanks [@rsolomon])
 
 ### Fixed
 - [`no-unused-modules`]: fix usage of `import/extensions` settings ([#1560], thanks [@stekycz])
@@ -685,6 +686,7 @@ for info on changes for earlier releases.
 [#1277]: https://github.com/benmosher/eslint-plugin-import/pull/1277
 [#1257]: https://github.com/benmosher/eslint-plugin-import/pull/1257
 [#1253]: https://github.com/benmosher/eslint-plugin-import/pull/1253
+[#1238]: https://github.com/benmosher/eslint-plugin-import/pull/1238
 [#1235]: https://github.com/benmosher/eslint-plugin-import/pull/1235
 [#1234]: https://github.com/benmosher/eslint-plugin-import/pull/1234
 [#1232]: https://github.com/benmosher/eslint-plugin-import/pull/1232
@@ -1051,3 +1053,4 @@ for info on changes for earlier releases.
 [@Pessimistress]: https://github.com/Pessimistress
 [@stekycz]: https://github.com/stekycz
 [@dbrewer5]: https://github.com/dbrewer5
+[@rsolomon]: https://github.com/rsolomon
diff --git a/docs/rules/no-restricted-paths.md b/docs/rules/no-restricted-paths.md
index bad65ab8e1..3776699836 100644
--- a/docs/rules/no-restricted-paths.md
+++ b/docs/rules/no-restricted-paths.md
@@ -9,7 +9,7 @@ In order to prevent such scenarios this rule allows you to define restricted zon
 
 This rule has one option. The option is an object containing the definition of all restricted `zones` and the optional `basePath` which is used to resolve relative paths within.
 The default value for `basePath` is the current working directory.
-Each zone consists of the `target` path and a `from` path. The `target` is the path where the restricted imports should be applied. The `from` path defines the folder that is not allowed to be used in an import.
+Each zone consists of the `target` path and a `from` path. The `target` is the path where the restricted imports should be applied. The `from` path defines the folder that is not allowed to be used in an import. An optional `except` may be defined for a zone, allowing exception paths that would otherwise violate the related `from`. Note that `except` is relative to `from` and cannot backtrack to a parent directory.
 
 ### Examples
 
@@ -37,3 +37,43 @@ The following patterns are not considered problems when configuration set to `{
 ```js
 import baz from '../client/baz';
 ```
+
+---------------
+
+Given the following folder structure:
+
+```
+my-project
+├── client
+│   └── foo.js
+│   └── baz.js
+└── server
+    ├── one
+    │   └── a.js
+    │   └── b.js
+    └── two
+```
+
+and the current file being linted is `my-project/server/one/a.js`.
+
+and the current configuration is set to:
+
+```
+{ "zones": [ {
+    "target": "./tests/files/restricted-paths/server/one",
+    "from": "./tests/files/restricted-paths/server",
+    "except": ["./one"]
+} ] }
+```
+
+The following pattern is considered a problem:
+
+```js
+import a from '../two/a'
+```
+
+The following pattern is not considered a problem:
+
+```js
+import b from './b'
+```
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 0d906f6318..221457b1c9 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -4,6 +4,7 @@ import path from 'path'
 import resolve from 'eslint-module-utils/resolve'
 import isStaticRequire from '../core/staticRequire'
 import docsUrl from '../docsUrl'
+import importType from '../core/importType'
 
 module.exports = {
   meta: {
@@ -24,6 +25,13 @@ module.exports = {
               properties: {
                 target: { type: 'string' },
                 from: { type: 'string' },
+                except: {
+                  type: 'array',
+                  items: {
+                    type: 'string',
+                  },
+                  uniqueItems: true,
+                },
               },
               additionalProperties: false,
             },
@@ -46,6 +54,19 @@ module.exports = {
       return containsPath(currentFilename, targetPath)
     })
 
+    function isValidExceptionPath(absoluteFromPath, absoluteExceptionPath) {
+      const relativeExceptionPath = path.relative(absoluteFromPath, absoluteExceptionPath)
+
+      return importType(relativeExceptionPath, context) !== 'parent'
+    }
+
+    function reportInvalidExceptionPath(node) {
+      context.report({
+        node,
+        message: 'Restricted path exceptions must be descendants of the configured `from` path for that zone.',
+      })
+    }
+
     function checkForRestrictedImportPath(importPath, node) {
         const absoluteImportPath = resolve(importPath, context)
 
@@ -54,14 +75,36 @@ module.exports = {
         }
 
         matchingZones.forEach((zone) => {
+          const exceptionPaths = zone.except || []
           const absoluteFrom = path.resolve(basePath, zone.from)
 
-          if (containsPath(absoluteImportPath, absoluteFrom)) {
-            context.report({
-              node,
-              message: `Unexpected path "${importPath}" imported in restricted zone.`,
-            })
+          if (!containsPath(absoluteImportPath, absoluteFrom)) {
+            return
+          }
+
+          const absoluteExceptionPaths = exceptionPaths.map((exceptionPath) =>
+            path.resolve(absoluteFrom, exceptionPath)
+          )
+          const hasValidExceptionPaths = absoluteExceptionPaths
+            .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath))
+
+          if (!hasValidExceptionPaths) {
+            reportInvalidExceptionPath(node)
+            return
+          }
+
+          const pathIsExcepted = absoluteExceptionPaths
+            .some((absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath))
+
+          if (pathIsExcepted) {
+            return
           }
+
+          context.report({
+            node,
+            message: `Unexpected path "{{importPath}}" imported in restricted zone.`,
+            data: { importPath },
+          })
         })
     }
 
diff --git a/tests/files/restricted-paths/server/one/a.js b/tests/files/restricted-paths/server/one/a.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/restricted-paths/server/one/b.js b/tests/files/restricted-paths/server/one/b.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/restricted-paths/server/two/a.js b/tests/files/restricted-paths/server/two/a.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index ba7d650994..1c3edb3dae 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -28,6 +28,28 @@ ruleTester.run('no-restricted-paths', rule, {
         zones: [ { target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/other' } ],
       } ],
     }),
+    test({
+      code: 'import a from "./a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [ {
+        zones: [ {
+          target: './tests/files/restricted-paths/server/one',
+          from: './tests/files/restricted-paths/server',
+          except: ['./one'],
+        } ],
+      } ],
+    }),
+    test({
+      code: 'import a from "../two/a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [ {
+        zones: [ {
+          target: './tests/files/restricted-paths/server/one',
+          from: './tests/files/restricted-paths/server',
+          except: ['./two'],
+        } ],
+      } ],
+    }),
 
 
     // irrelevant function calls
@@ -107,5 +129,38 @@ ruleTester.run('no-restricted-paths', rule, {
         column: 19,
       } ],
     }),
+    test({
+      code: 'import b from "../two/a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [ {
+        zones: [ {
+          target: './tests/files/restricted-paths/server/one',
+          from: './tests/files/restricted-paths/server',
+          except: ['./one'],
+        } ],
+      } ],
+      errors: [ {
+        message: 'Unexpected path "../two/a.js" imported in restricted zone.',
+        line: 1,
+        column: 15,
+      } ],
+    }),
+    test({
+      code: 'import b from "../two/a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [ {
+        zones: [ {
+          target: './tests/files/restricted-paths/server/one',
+          from: './tests/files/restricted-paths/server',
+          except: ['../client/a'],
+        } ],
+      } ],
+      errors: [ {
+        message: 'Restricted path exceptions must be descendants of the configured ' +
+          '`from` path for that zone.',
+        line: 1,
+        column: 15,
+      } ],
+    }),
   ],
 })

From ae747c0cc34e6105486fe6334bac49183c7c01ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joa=CC=83o=20Vieira?= <joaoguerravieira@gmail.com>
Date: Tue, 29 Oct 2019 23:57:58 +0000
Subject: [PATCH 072/767] [fix] TypeScript config: lookup for external modules
 in @types folder

---
 CHANGELOG.md                   |  5 +++--
 config/typescript.js           |  1 +
 tests/src/config/typescript.js | 14 ++++++++++++++
 3 files changed, 18 insertions(+), 2 deletions(-)
 create mode 100644 tests/src/config/typescript.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae9f5bca7e..fac8b782c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,9 +11,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`no-unused-modules`]: fix usage of `import/extensions` settings ([#1560], thanks [@stekycz])
-
-### Fixed
 - [`import/extensions`]: ignore non-main modules ([#1563], thanks [@saschanaz])
+- TypeScript config: lookup for external modules in @types folder ([#1526], thanks [@joaovieira])
 
 ## [2.19.1] - 2019-12-08
 ### Fixed
@@ -634,6 +633,7 @@ for info on changes for earlier releases.
 [#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1542]: https://github.com/benmosher/eslint-plugin-import/pull/1542
+[#1526]: https://github.com/benmosher/eslint-plugin-import/pull/1526
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
 [#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
 [#1507]: https://github.com/benmosher/eslint-plugin-import/pull/1507
@@ -1054,3 +1054,4 @@ for info on changes for earlier releases.
 [@stekycz]: https://github.com/stekycz
 [@dbrewer5]: https://github.com/dbrewer5
 [@rsolomon]: https://github.com/rsolomon
+[@joaovieira]: https://github.com/joaovieira
diff --git a/config/typescript.js b/config/typescript.js
index fdd1d5910b..262e3c7999 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -8,6 +8,7 @@ module.exports = {
 
   settings: {
     'import/extensions': allExtensions,
+    'import/external-module-folders': ['node_modules', 'node_modules/@types'],
     'import/parsers': {
       '@typescript-eslint/parser': ['.ts', '.tsx', '.d.ts'],
     },
diff --git a/tests/src/config/typescript.js b/tests/src/config/typescript.js
new file mode 100644
index 0000000000..d5e3ec8507
--- /dev/null
+++ b/tests/src/config/typescript.js
@@ -0,0 +1,14 @@
+import path from 'path'
+import { expect } from 'chai'
+
+const config = require(path.join(__dirname, '..', '..', '..', 'config', 'typescript'))
+
+describe('config typescript', () => {
+  // https://github.com/benmosher/eslint-plugin-import/issues/1525
+  it('should mark @types paths as external', () => {
+    const externalModuleFolders = config.settings['import/external-module-folders']
+    expect(externalModuleFolders).to.exist
+    expect(externalModuleFolders).to.contain('node_modules')
+    expect(externalModuleFolders).to.contain('node_modules/@types')
+  })
+})

From f790737c07f39058592b7eb8b6cda3de72c239b9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 1 Jan 2020 11:26:01 -0800
Subject: [PATCH 073/767] [patch] `no-extraneous-dependencies`: ensure
 `node.source` is truthy

These tests already passed, implying that #1589 is a non-issue. However,
the guards are still good to add.
---
 CHANGELOG.md                                  | 2 ++
 src/rules/no-extraneous-dependencies.js       | 8 ++++++--
 tests/src/rules/no-extraneous-dependencies.js | 3 +++
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fac8b782c4..8632f23868 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: fix usage of `import/extensions` settings ([#1560], thanks [@stekycz])
 - [`import/extensions`]: ignore non-main modules ([#1563], thanks [@saschanaz])
 - TypeScript config: lookup for external modules in @types folder ([#1526], thanks [@joaovieira])
+- [`no-extraneous-dependencies`]: ensure `node.source` is truthy ([#1589], thanks [@ljharb])
 
 ## [2.19.1] - 2019-12-08
 ### Fixed
@@ -628,6 +629,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
 [#1563]: https://github.com/benmosher/eslint-plugin-import/pull/1563
 [#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 41ccb2a318..7746f489ec 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -203,7 +203,9 @@ module.exports = {
     // todo: use module visitor from module-utils core
     return {
       ImportDeclaration: function (node) {
-        reportIfMissing(context, deps, depsOptions, node, node.source.value)
+        if (node.source) {
+          reportIfMissing(context, deps, depsOptions, node, node.source.value)
+        }
       },
       ExportNamedDeclaration: function (node) {
         if (node.source) {
@@ -211,7 +213,9 @@ module.exports = {
         }
       },
       ExportAllDeclaration: function (node) {
-        reportIfMissing(context, deps, depsOptions, node, node.source.value)
+        if (node.source) {
+          reportIfMissing(context, deps, depsOptions, node, node.source.value)
+        }
       },
       CallExpression: function handleRequires(node) {
         if (isStaticRequire(node)) {
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index f3f7448053..114a733af7 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -125,6 +125,9 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({ code: 'export { foo } from "lodash.cond"' }),
     test({ code: 'export * from "lodash.cond"' }),
     test({ code: 'export function getToken() {}' }),
+    test({ code: 'export class Component extends React.Component {}' }),
+    test({ code: 'export function Component() {}' }),
+    test({ code: 'export const Component = () => {}' }),
   ],
   invalid: [
     test({

From b791ba59f5d33f448ba70dddc095039eb4e93b13 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 1 Jan 2020 13:35:11 -0800
Subject: [PATCH 074/767] [Tests] on node `v13`

---
 .travis.yml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index 03c405436d..4c50e3012c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
 language: node_js
 node_js:
+  - '13'
   - '12'
   - '10'
   - '8'
@@ -18,6 +19,8 @@ env:
 # osx backlog is often deep, so to be polite we can just hit these highlights
 matrix:
   include:
+  - env: PACKAGE=resolvers/node
+    node_js: 13
   - env: PACKAGE=resolvers/node
     node_js: 12
   - env: PACKAGE=resolvers/node

From 982493d03acb30a05f46a9d41c31cf85f9acf4cb Mon Sep 17 00:00:00 2001
From: Pascal Corpet <pascal@bayesimpact.org>
Date: Sun, 15 Dec 2019 23:42:50 +0100
Subject: [PATCH 075/767] [Fix] `extensions`: Ignore query strings when
 checking for extensions.

Fixes #1567.
---
 CHANGELOG.md                  |  2 ++
 src/rules/extensions.js       | 10 ++++++----
 tests/src/rules/extensions.js | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8632f23868..b3061594a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`import/extensions`]: ignore non-main modules ([#1563], thanks [@saschanaz])
 - TypeScript config: lookup for external modules in @types folder ([#1526], thanks [@joaovieira])
 - [`no-extraneous-dependencies`]: ensure `node.source` is truthy ([#1589], thanks [@ljharb])
+- [`extensions`]: Ignore query strings when checking for extensions ([#1572], thanks [@pcorpet])
 
 ## [2.19.1] - 2019-12-08
 ### Fixed
@@ -631,6 +632,7 @@ for info on changes for earlier releases.
 
 [#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
+[#1572]: https://github.com/benmosher/eslint-plugin-import/pull/1572
 [#1563]: https://github.com/benmosher/eslint-plugin-import/pull/1563
 [#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index c6077fb2c8..c0213cad2f 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -132,10 +132,12 @@ module.exports = {
       // bail if the declaration doesn't have a source, e.g. "export { foo };"
       if (!source) return
 
-      const importPath = source.value
+      const importPathWithQueryString = source.value
 
       // don't enforce anything on builtins
-      if (isBuiltIn(importPath, context.settings)) return
+      if (isBuiltIn(importPathWithQueryString, context.settings)) return
+
+      const importPath = importPathWithQueryString.replace(/\?(.*)$/, '')
 
       const resolvedPath = resolve(importPath, context)
 
@@ -154,14 +156,14 @@ module.exports = {
           context.report({
             node: source,
             message:
-              `Missing file extension ${extension ? `"${extension}" ` : ''}for "${importPath}"`,
+              `Missing file extension ${extension ? `"${extension}" ` : ''}for "${importPathWithQueryString}"`,
           })
         }
       } else if (extension) {
         if (isUseOfExtensionForbidden(extension) && isResolvableWithoutExtension(importPath)) {
           context.report({
             node: source,
-            message: `Unexpected use of file extension "${extension}" for "${importPath}"`,
+            message: `Unexpected use of file extension "${extension}" for "${importPathWithQueryString}"`,
           })
         }
       }
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 720867c219..5f0a254f53 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -116,6 +116,16 @@ ruleTester.run('extensions', rule, {
       ].join('\n'),
       options: [ 'never' ],
     }),
+
+    // Query strings.
+    test({
+      code: 'import bare from "./foo?a=True.ext"',
+      options: [ 'never' ],
+    }),
+    test({
+      code: 'import bare from "./foo.js?a=True"',
+      options: [ 'always' ],
+    }),
   ],
 
   invalid: [
@@ -375,5 +385,29 @@ ruleTester.run('extensions', rule, {
         },
       ],
     }),
+
+    // Query strings.
+    test({
+      code: 'import withExtension from "./foo.js?a=True"',
+      options: [ 'never' ],
+      errors: [
+        {
+          message: 'Unexpected use of file extension "js" for "./foo.js?a=True"',
+          line: 1,
+          column: 27,
+        },
+      ],
+    }),
+    test({
+      code: 'import withoutExtension from "./foo?a=True.ext"',
+      options: [ 'always' ],
+      errors: [
+        {
+          message: 'Missing file extension for "./foo?a=True.ext"',
+          line: 1,
+          column: 30,
+        },
+      ],
+    }),
   ],
 })

From 16ae652d4524775bbbc52934d9b0114e6be5455c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= <mairu@gmx.net>
Date: Sat, 14 Dec 2019 15:21:03 +0100
Subject: [PATCH 076/767] [New] `order` rule: add option
 pathGroupsExcludedImportTypes to allow ordering of external import types

---
 CHANGELOG.md             |  4 ++++
 docs/rules/order.md      | 24 +++++++++++++++++++++++-
 src/rules/order.js       | 34 +++++++++++++++++++++++++++-------
 tests/src/rules/order.js | 22 ++++++++++++++++++++++
 4 files changed, 76 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b3061594a1..c05d4a045c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-extraneous-dependencies`]: ensure `node.source` is truthy ([#1589], thanks [@ljharb])
 - [`extensions`]: Ignore query strings when checking for extensions ([#1572], thanks [@pcorpet])
 
+### Added
+- [`order`]: add option pathGroupsExcludedImportTypes to allow ordering of external import types ([#1565], thanks [@Mairu])
+
 ## [2.19.1] - 2019-12-08
 ### Fixed
 - [`no-extraneous-dependencies`]: ensure `node.source` exists
@@ -789,6 +792,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
+[#1565]: https://github.com/benmosher/eslint-plugin-import/issues/1565
 [#1366]: https://github.com/benmosher/eslint-plugin-import/issues/1366
 [#1334]: https://github.com/benmosher/eslint-plugin-import/issues/1334
 [#1323]: https://github.com/benmosher/eslint-plugin-import/issues/1323
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 8012e637f7..667b63374f 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -96,7 +96,7 @@ You can set the options like this:
 
 ### `pathGroups: [array of objects]`:
 
-To be able so group by paths mostly needed with aliases pathGroups can be defined.
+To be able to group by paths mostly needed with aliases pathGroups can be defined.
 
 Properties of the objects
 
@@ -120,6 +120,28 @@ Properties of the objects
 }
 ```
 
+### `pathGroupsExcludedImportTypes: [array]`:
+
+This defines import types that are not handled by configured pathGroups.
+This is mostly needed when you want to handle path groups that look like external imports.
+
+Example:
+```json
+{
+  "import/order": ["error", {
+    "pathGroups": [
+      {
+        "pattern": "@app/**",
+        "group": "external",
+        "position": "after"
+      }
+    ],
+    "pathGroupsExcludedImportTypes": ["builtin"]
+  }]
+}
+```
+The default value is `["builtin", "external"]`.
+
 ### `newlines-between: [ignore|always|always-and-inside-groups|never]`:
 
 Enforces or forbids new lines between import groups:
diff --git a/src/rules/order.js b/src/rules/order.js
index a842f60afb..fcdf12bda5 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -269,7 +269,7 @@ function importsSorterDesc(importA, importB) {
 
 function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
   const groupedByRanks = imported.reduce(function(acc, importedItem) {
-    if (!Array.isArray(acc[importedItem.rank])) { 
+    if (!Array.isArray(acc[importedItem.rank])) {
       acc[importedItem.rank] = []
     }
     acc[importedItem.rank].push(importedItem.name)
@@ -312,10 +312,10 @@ function computePathRank(ranks, pathGroups, path, maxPosition) {
   }
 }
 
-function computeRank(context, ranks, name, type) {
+function computeRank(context, ranks, name, type, excludedImportTypes) {
   const impType = importType(name, context)
   let rank
-  if (impType !== 'builtin' && impType !== 'external') {
+  if (!excludedImportTypes.has(impType)) {
     rank = computePathRank(ranks.groups, ranks.pathGroups, name, ranks.maxPosition)
   }
   if (!rank) {
@@ -328,8 +328,8 @@ function computeRank(context, ranks, name, type) {
   return rank
 }
 
-function registerNode(context, node, name, type, ranks, imported) {
-  const rank = computeRank(context, ranks, name, type)
+function registerNode(context, node, name, type, ranks, imported, excludedImportTypes) {
+  const rank = computeRank(context, ranks, name, type, excludedImportTypes)
   if (rank !== -1) {
     imported.push({name, rank, node})
   }
@@ -508,6 +508,9 @@ module.exports = {
           groups: {
             type: 'array',
           },
+          pathGroupsExcludedImportTypes: {
+            type: 'array',
+          },
           pathGroups: {
             type: 'array',
             items: {
@@ -562,6 +565,7 @@ module.exports = {
   create: function importOrderRule (context) {
     const options = context.options[0] || {}
     const newlinesBetweenImports = options['newlines-between'] || 'ignore'
+    const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external'])
     const alphabetize = getAlphabetizeConfig(options)
     let ranks
 
@@ -594,7 +598,15 @@ module.exports = {
       ImportDeclaration: function handleImports(node) {
         if (node.specifiers.length) { // Ignoring unassigned imports
           const name = node.source.value
-          registerNode(context, node, name, 'import', ranks, imported)
+          registerNode(
+            context,
+            node,
+            name,
+            'import',
+            ranks,
+            imported,
+            pathGroupsExcludedImportTypes
+          )
         }
       },
       CallExpression: function handleRequires(node) {
@@ -602,7 +614,15 @@ module.exports = {
           return
         }
         const name = node.arguments[0].value
-        registerNode(context, node, name, 'require', ranks, imported)
+        registerNode(
+          context,
+          node,
+          name,
+          'require',
+          ranks,
+          imported,
+          pathGroupsExcludedImportTypes
+        )
       },
       'Program:exit': function reportAndReset() {
         if (newlinesBetweenImports !== 'ignore') {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 11309f933b..8ba8b9f1eb 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -276,6 +276,28 @@ ruleTester.run('order', rule, {
         ],
       }],
     }),
+    // Using pathGroups to customize ordering for imports that are recognized as 'external'
+    // by setting pathGroupsExcludedImportTypes without 'external'
+    test({
+      code: `
+        import fs from 'fs';
+
+        import { Input } from '@app/components/Input';
+
+        import { Button } from '@app2/components/Button';
+
+        import _ from 'lodash';
+
+        import { add } from './helper';`,
+      options: [{
+        'newlines-between': 'always',
+        pathGroupsExcludedImportTypes: ['builtin'],
+        pathGroups: [
+          { pattern: '@app/**', group: 'external', position: 'before' },
+          { pattern: '@app2/**', group: 'external', position: 'before' },
+        ],
+      }],
+    }),
 
     // Option: newlines-between: 'always'
     test({

From fb0cbebf02cb2b00383cc044129c1ac852c513af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ma=C3=ABl=20Nison?= <nison.mael@gmail.com>
Date: Thu, 2 Jan 2020 11:18:57 +0100
Subject: [PATCH 077/767] utils: Uses createRequireFromPath to resolve loaders

---
 .../eslint-import-resolver-foo/index.js       |  1 +
 tests/src/core/resolve.js                     |  8 +++++++
 tests/src/rules/no-unresolved.js              |  8 +++----
 utils/CHANGELOG.md                            |  6 ++++-
 utils/resolve.js                              | 24 +++++++++++++++----
 5 files changed, 38 insertions(+), 9 deletions(-)
 create mode 120000 tests/files/node_modules/eslint-import-resolver-foo/index.js

diff --git a/tests/files/node_modules/eslint-import-resolver-foo/index.js b/tests/files/node_modules/eslint-import-resolver-foo/index.js
new file mode 120000
index 0000000000..d194dba0df
--- /dev/null
+++ b/tests/files/node_modules/eslint-import-resolver-foo/index.js
@@ -0,0 +1 @@
+../../foo-bar-resolver-v2.js
\ No newline at end of file
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index 5d5bd3a206..3bf46cd1a3 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -94,6 +94,14 @@ describe('resolve', function () {
                       )).to.equal(utils.testFilePath('./bar.jsx'))
   })
 
+  it('finds resolvers from the source files rather than eslint-module-utils', function () {
+    const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } })
+
+    expect(resolve( '../files/foo'
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
+                      )).to.equal(utils.testFilePath('./bar.jsx'))
+  })
+
   it('reports invalid import/resolver config', function () {
     const testContext = utils.testContext({ 'import/resolver': 123.456 })
     const testContextReports = []
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index cae6e8468b..cc3aca8844 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -343,9 +343,9 @@ ruleTester.run('no-unresolved unknown resolver', rule, {
     // logs resolver load error
     test({
       code: 'import "./malformed.js"',
-      settings: { 'import/resolver': 'foo' },
+      settings: { 'import/resolver': 'doesnt-exist' },
       errors: [
-        `Resolve error: unable to load resolver "foo".`,
+        `Resolve error: unable to load resolver "doesnt-exist".`,
         `Unable to resolve path to module './malformed.js'.`,
       ],
     }),
@@ -353,9 +353,9 @@ ruleTester.run('no-unresolved unknown resolver', rule, {
     // only logs resolver message once
     test({
       code: 'import "./malformed.js"; import "./fake.js"',
-      settings: { 'import/resolver': 'foo' },
+      settings: { 'import/resolver': 'doesnt-exist' },
       errors: [
-        `Resolve error: unable to load resolver "foo".`,
+        `Resolve error: unable to load resolver "doesnt-exist".`,
         `Unable to resolve path to module './malformed.js'.`,
         `Unable to resolve path to module './fake.js'.`,
       ],
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 8165447b7d..6a7fe6764f 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Fixed
+- Uses createRequireFromPath to resolve loaders ([#1591], thanks [@arcanis])
+
 ## v2.5.0 - 2019-12-07
 
 ### Added
@@ -59,7 +62,7 @@ Yanked due to critical issue with cache key resulting from #839.
 - `unambiguous.test()` regex is now properly in multiline mode
 
 
-
+[#1591]: https://github.com/benmosher/eslint-plugin-import/pull/1591
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
 [#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
@@ -77,3 +80,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@christophercurrie]: https://github.com/christophercurrie
 [@brettz9]: https://github.com/brettz9
 [@JounQin]: https://github.com/JounQin
+[@arcanis]: https://github.com/arcanis
diff --git a/utils/resolve.js b/utils/resolve.js
index 92c8f35002..945ba4b6f8 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -4,6 +4,7 @@ exports.__esModule = true
 const pkgDir = require('pkg-dir')
 
 const fs = require('fs')
+const Module = require('module')
 const path = require('path')
 
 const hashObject = require('./hash').hashObject
@@ -14,11 +15,26 @@ exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS
 
 const fileExistsCache = new ModuleCache()
 
-function tryRequire(target) {
+// Polyfill Node's `Module.createRequireFromPath` if not present (added in Node v10.12.0)
+const createRequireFromPath = Module.createRequireFromPath || function (filename) {
+  const mod = new Module(filename, null)
+  mod.filename = filename
+  mod.paths = Module._nodeModulePaths(path.dirname(filename))
+
+  mod._compile(`module.exports = require;`, filename)
+
+  return mod.exports
+}
+
+function tryRequire(target, sourceFile) {
   let resolved
   try {
     // Check if the target exists
-    resolved = require.resolve(target)
+    if (sourceFile != null) {
+      resolved = createRequireFromPath(sourceFile).resolve(target)
+    } else {
+      resolved = require.resolve(target)
+    }
   } catch(e) {
     // If the target does not exist then just return undefined
     return undefined
@@ -154,8 +170,8 @@ function getBaseDir(sourceFile) {
 }
 function requireResolver(name, sourceFile) {
   // Try to resolve package with conventional name
-  let resolver = tryRequire(`eslint-import-resolver-${name}`) ||
-    tryRequire(name) ||
+  let resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile) ||
+    tryRequire(name, sourceFile) ||
     tryRequire(path.resolve(getBaseDir(sourceFile), name))
 
   if (!resolver) {

From b511da2011d77f601a228ffa1bad6792c1830749 Mon Sep 17 00:00:00 2001
From: Ivo Stefchev <ivakaetuk@gmail.com>
Date: Tue, 6 Aug 2019 00:42:36 +0300
Subject: [PATCH 078/767] [Docs] `extensions`: improve `ignorePackages` docs

Closes #1248.
---
 CHANGELOG.md             |  5 +++++
 docs/rules/extensions.md | 19 ++++++++++++++++++-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c05d4a045c..de44575690 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-extraneous-dependencies`]: ensure `node.source` is truthy ([#1589], thanks [@ljharb])
 - [`extensions`]: Ignore query strings when checking for extensions ([#1572], thanks [@pcorpet])
 
+### Docs
+- [`extensions`]: improve `ignorePackages` docs ([#1248], thanks [@ivo-stefchev])
+
 ### Added
 - [`order`]: add option pathGroupsExcludedImportTypes to allow ordering of external import types ([#1565], thanks [@Mairu])
 
@@ -693,6 +696,7 @@ for info on changes for earlier releases.
 [#1277]: https://github.com/benmosher/eslint-plugin-import/pull/1277
 [#1257]: https://github.com/benmosher/eslint-plugin-import/pull/1257
 [#1253]: https://github.com/benmosher/eslint-plugin-import/pull/1253
+[#1248]: https://github.com/benmosher/eslint-plugin-import/pull/1248
 [#1238]: https://github.com/benmosher/eslint-plugin-import/pull/1238
 [#1235]: https://github.com/benmosher/eslint-plugin-import/pull/1235
 [#1234]: https://github.com/benmosher/eslint-plugin-import/pull/1234
@@ -1063,3 +1067,4 @@ for info on changes for earlier releases.
 [@dbrewer5]: https://github.com/dbrewer5
 [@rsolomon]: https://github.com/rsolomon
 [@joaovieira]: https://github.com/joaovieira
+[@ivo-stefchev]: https://github.com/ivo-stefchev
diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md
index 6e1d2b50a0..2f6d4a9c7a 100644
--- a/docs/rules/extensions.md
+++ b/docs/rules/extensions.md
@@ -29,13 +29,30 @@ By providing both a string and an object, the string will set the default settin
   <severity>,
   "never" | "always" | "ignorePackages",
   {
-    <extension>: "never" | "always" | "ignorePackages" 
+    <extension>: "never" | "always" | "ignorePackages"
   }
 ]
 ```
 
 For example, `["error", "never", { "svg": "always" }]` would require that all extensions are omitted, except for "svg".
 
+`ignorePackages` can be set as a separate boolean option like this:
+```
+"import/extensions": [
+  <severity>,
+  "never" | "always" | "ignorePackages",
+  {
+    ignorePackages: true | false,
+    pattern: {
+      <extension>: "never" | "always" | "ignorePackages"
+    }
+  }
+]
+```
+In that case, if you still want to specify extensions, you can do so inside the **pattern** property.
+Default value of `ignorePackages` is `false`.
+
+
 ### Exception
 
 When disallowing the use of certain extensions this rule makes an exception and allows the use of extension when the file would not be resolvable without extension.

From aed7a7391d014594b034fa92c4daf1a6d50e3f5a Mon Sep 17 00:00:00 2001
From: John Babak <babak.john@gmail.com>
Date: Sun, 2 Oct 2016 03:43:37 +0300
Subject: [PATCH 079/767] utils: [Fix] report the error stack on a resolution
 error

Fixes #536.

Resolve errors are most likely caused by invalid configuration,
and the reason is easier to determine with the full details
rather than just `err.message`.

With this change, it reports something like:
```
import/no-unresolved: Resolve error: SyntaxError: Unexpected token import
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:387:25)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at module.exports (/__censored__/webpack/configFactory.js:216:3)
    at configProdClient (/__censored__/webpack/configProdClient.js:5:36)
    at Object.<anonymous> (/__censored__/webpack/configForEslintImportResolver.js:1:126)
```
---
 tests/files/load-error-resolver.js |  2 +-
 tests/src/core/resolve.js          |  9 +++++++--
 utils/CHANGELOG.md                 |  3 +++
 utils/resolve.js                   | 22 ++++++++++++++++++----
 4 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/tests/files/load-error-resolver.js b/tests/files/load-error-resolver.js
index aa9d33010d..7cf7cfa1bc 100644
--- a/tests/files/load-error-resolver.js
+++ b/tests/files/load-error-resolver.js
@@ -1 +1 @@
-throw new Error('TEST ERROR')
+throw new SyntaxError('TEST SYNTAX ERROR')
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index 3bf46cd1a3..1aa2071db6 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -8,6 +8,11 @@ import * as fs from 'fs'
 import * as utils from '../utils'
 
 describe('resolve', function () {
+  // We don't want to test for a specific stack, just that it was there in the error message.
+  function replaceErrorStackForTest(str) {
+    return typeof str === 'string' ? str.replace(/(\n\s+at .+:\d+\)?)+$/, '\n<stack-was-here>') : str
+  }
+
   it('throws on bad parameters', function () {
     expect(resolve.bind(null, null, null)).to.throw(Error)
   })
@@ -60,7 +65,7 @@ describe('resolve', function () {
                       , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
                     )).to.equal(undefined)
     expect(testContextReports[0]).to.be.an('object')
-    expect(testContextReports[0].message).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception')
+    expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>')
     expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 })
 
     testContextReports.length = 0
@@ -153,7 +158,7 @@ describe('resolve', function () {
                       , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
                     )).to.equal(undefined)
     expect(testContextReports[0]).to.be.an('object')
-    expect(testContextReports[0].message).to.equal('Resolve error: TEST ERROR')
+    expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>')
     expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 })
   })
 
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 6a7fe6764f..4573f794bc 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - Uses createRequireFromPath to resolve loaders ([#1591], thanks [@arcanis])
+- report the error stack on a resolution error ([#599], thanks [@sompylasar])
 
 ## v2.5.0 - 2019-12-07
 
@@ -72,6 +73,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [#1166]: https://github.com/benmosher/eslint-plugin-import/issues/1166
 [#1160]: https://github.com/benmosher/eslint-plugin-import/pull/1160
 [#1035]: https://github.com/benmosher/eslint-plugin-import/issues/1035
+[#599]: https://github.com/benmosher/eslint-plugin-import/pull/599
 
 [@hulkish]: https://github.com/hulkish
 [@timkraut]: https://github.com/timkraut
@@ -81,3 +83,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@brettz9]: https://github.com/brettz9
 [@JounQin]: https://github.com/JounQin
 [@arcanis]: https://github.com/arcanis
+[@sompylasar]: https://github.com/sompylasar
diff --git a/utils/resolve.js b/utils/resolve.js
index 945ba4b6f8..3dc15f022a 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -13,6 +13,8 @@ const hashObject = require('./hash').hashObject
 const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname, 'reSOLVE.js'))
 exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS
 
+const ERROR_NAME = 'EslintPluginImportResolveError'
+
 const fileExistsCache = new ModuleCache()
 
 // Polyfill Node's `Module.createRequireFromPath` if not present (added in Node v10.12.0)
@@ -162,7 +164,9 @@ function resolverReducer(resolvers, map) {
     return map
   }
 
-  throw new Error('invalid resolver config')
+  const err = new Error('invalid resolver config')
+  err.name = ERROR_NAME
+  throw err
 }
 
 function getBaseDir(sourceFile) {
@@ -175,10 +179,14 @@ function requireResolver(name, sourceFile) {
     tryRequire(path.resolve(getBaseDir(sourceFile), name))
 
   if (!resolver) {
-    throw new Error(`unable to load resolver "${name}".`)
+    const err = new Error(`unable to load resolver "${name}".`)
+    err.name = ERROR_NAME
+    throw err
   }
   if (!isResolverValid(resolver)) {
-    throw new Error(`${name} with invalid interface loaded as resolver`)
+    const err = new Error(`${name} with invalid interface loaded as resolver`)
+    err.name = ERROR_NAME
+    throw err
   }
 
   return resolver
@@ -210,8 +218,14 @@ function resolve(p, context) {
                    )
   } catch (err) {
     if (!erroredContexts.has(context)) {
+      // The `err.stack` string starts with `err.name` followed by colon and `err.message`.
+      // We're filtering out the default `err.name` because it adds little value to the message.
+      let errMessage = err.message
+      if (err.name !== ERROR_NAME && err.stack) {
+        errMessage = err.stack.replace(/^Error: /, '')
+      }
       context.report({
-        message: `Resolve error: ${err.message}`,
+        message: `Resolve error: ${errMessage}`,
         loc: { line: 1, column: 0 },
       })
       erroredContexts.add(context)

From cd25d9da3a3d9f6d76a96767f3e5296c12a81e70 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adria=CC=81n=20Seijo?= <kileras@gmail.com>
Date: Fri, 11 Nov 2016 12:03:49 +0000
Subject: [PATCH 080/767] [Fix] `extensions`: Ignore root external modules when
 checking for extensions

---
 src/core/importType.js        |  4 +++
 src/rules/extensions.js       | 14 ++++++++-
 tests/src/rules/extensions.js | 56 ++++++++++++++++++++++++++++-------
 3 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/src/core/importType.js b/src/core/importType.js
index 57558cbd82..8ec01c29e8 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -84,6 +84,10 @@ function typeTest(name, settings, path) {
   return 'unknown'
 }
 
+export function isScopedModule(name) {
+  return name.indexOf('@') === 0
+}
+
 export default function resolveImportType(name, context) {
   return typeTest(name, context.settings, resolve(name, context))
 }
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index c0213cad2f..fd9d177adf 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -1,7 +1,7 @@
 import path from 'path'
 
 import resolve from 'eslint-module-utils/resolve'
-import { isBuiltIn, isExternalModule, isScoped } from '../core/importType'
+import { isBuiltIn, isExternalModule, isScoped, isScopedModule } from '../core/importType'
 import docsUrl from '../docsUrl'
 
 const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] }
@@ -126,6 +126,14 @@ module.exports = {
       return resolvedFileWithoutExtension === resolve(file, context)
     }
 
+    function isExternalRootModule(file) {
+      const slashCount = file.split('/').length - 1
+
+      if (isScopedModule(file) && slashCount <= 1) return true
+      if (isExternalModule(file, context, resolve(file, context)) && !slashCount) return true
+      return false
+    }
+
     function checkFileExtension(node) {
       const { source } = node
 
@@ -139,6 +147,10 @@ module.exports = {
 
       const importPath = importPathWithQueryString.replace(/\?(.*)$/, '')
 
+      // don't enforce in root external packages as they may have names with `.js`.
+      // Like `import Decimal from decimal.js`)
+      if (isExternalRootModule(importPath)) return
+
       const resolvedPath = resolve(importPath, context)
 
       // get extension from resolved path, if possible.
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 5f0a254f53..562802eef3 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -117,6 +117,16 @@ ruleTester.run('extensions', rule, {
       options: [ 'never' ],
     }),
 
+    // Root packages should be ignored and they are names not files
+    test({
+      code: [
+        'import lib from "pkg.js"',
+        'import lib2 from "pgk/package"',
+        'import lib3 from "@name/pkg.js"',
+      ].join('\n'),
+      options: [ 'never' ],
+    }),
+
     // Query strings.
     test({
       code: 'import bare from "./foo?a=True.ext"',
@@ -126,6 +136,15 @@ ruleTester.run('extensions', rule, {
       code: 'import bare from "./foo.js?a=True"',
       options: [ 'always' ],
     }),
+
+    test({
+      code: [
+        'import lib from "pkg"',
+        'import lib2 from "pgk/package.js"',
+        'import lib3 from "@name/pkg"',
+      ].join('\n'),
+      options: [ 'always' ],
+    }),
   ],
 
   invalid: [
@@ -137,15 +156,6 @@ ruleTester.run('extensions', rule, {
         column: 15,
       } ],
     }),
-    test({
-      code: 'import a from "a"',
-      options: [ 'always' ],
-      errors: [ {
-        message: 'Missing file extension "js" for "a"',
-        line: 1,
-        column: 15,
-      } ],
-    }),
     test({
       code: 'import dot from "./file.with.dot"',
       options: [ 'always' ],
@@ -285,11 +295,35 @@ ruleTester.run('extensions', rule, {
       ],
     }),
     test({
-      code: 'import thing from "non-package"',
+      code: 'import thing from "non-package/test"',
       options: [ 'always' ],
       errors: [
         {
-            message: 'Missing file extension for "non-package"',
+            message: 'Missing file extension for "non-package/test"',
+            line: 1,
+            column: 19,
+        },
+      ],
+    }),
+
+    test({
+      code: 'import thing from "@name/pkg/test"',
+      options: [ 'always' ],
+      errors: [
+        {
+            message: 'Missing file extension for "@name/pkg/test"',
+            line: 1,
+            column: 19,
+        },
+      ],
+    }),
+
+    test({
+      code: 'import thing from "@name/pkg/test.js"',
+      options: [ 'never' ],
+      errors: [
+        {
+            message: 'Unexpected use of file extension "js" for "@name/pkg/test.js"',
             line: 1,
             column: 19,
         },

From ed41b9c8b1339b2c401388f05a735753b425f06b Mon Sep 17 00:00:00 2001
From: Standa Opichal <opichals@gmail.com>
Date: Mon, 6 Jan 2020 11:21:55 +0100
Subject: [PATCH 081/767] [meta] copy LICENSE file to all npm packages on
 prepublish

---
 .gitignore                     | 10 ++++++++++
 .travis.yml                    |  3 ++-
 memo-parser/package.json       |  1 +
 package.json                   |  4 +++-
 resolvers/node/.npmrc          |  1 -
 resolvers/node/package.json    |  1 +
 resolvers/webpack/.npmrc       |  1 -
 resolvers/webpack/package.json |  1 +
 utils/.npmrc                   |  1 -
 utils/package.json             |  1 +
 10 files changed, 19 insertions(+), 5 deletions(-)
 delete mode 100644 resolvers/node/.npmrc
 delete mode 120000 resolvers/webpack/.npmrc
 delete mode 100644 utils/.npmrc

diff --git a/.gitignore b/.gitignore
index 0bf60608a0..a01de720c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,16 @@ coverage
 # Compiled binary addons (http://nodejs.org/api/addons.html)
 build/Release
 
+# Copied from ./LICENSE for the npm module releases
+memo-parser/LICENSE
+resolvers/node/LICENSE
+resolvers/webpack/LICENSE
+utils/LICENSE
+memo-parser/.npmrc
+resolvers/node/.npmrc
+resolvers/webpack/.npmrc
+utils/.npmrc
+
 # Dependency directory
 # Commenting this out is preferred by some people, see
 # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
diff --git a/.travis.yml b/.travis.yml
index 4c50e3012c..cd5650c65a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -74,9 +74,10 @@ matrix:
 
 before_install:
   - 'nvm install-latest-npm'
+  - 'npm run copy-metafiles'
   - 'if [ -n "${PACKAGE-}" ]; then cd "${PACKAGE}"; fi'
 install:
-  - npm install
+  - 'npm install'
   - 'if [ -n "${ESLINT_VERSION}" ]; then ./tests/dep-time-travel.sh; fi'
 
 script:
diff --git a/memo-parser/package.json b/memo-parser/package.json
index 2c81bb88a3..09577967c6 100644
--- a/memo-parser/package.json
+++ b/memo-parser/package.json
@@ -7,6 +7,7 @@
   "description": "Memoizing wrapper for any ESLint-compatible parser module.",
   "main": "index.js",
   "scripts": {
+    "prepublishOnly": "cp ../{LICENSE,.npmrc} ./",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "repository": {
diff --git a/package.json b/package.json
index e196159744..b303dbfb86 100644
--- a/package.json
+++ b/package.json
@@ -15,8 +15,10 @@
     "memo-parser"
   ],
   "scripts": {
-    "build": "babel --quiet --out-dir lib src",
     "prebuild": "rimraf lib",
+    "build": "babel --quiet --out-dir lib src",
+    "postbuild": "npm run copy-metafiles",
+    "copy-metafiles": "for DIR in memo-parser resolvers/node resolvers/webpack utils; do cp LICENSE .npmrc \"${DIR}/\"; done",
     "watch": "npm run mocha -- --watch tests/src",
     "pretest": "linklocal",
     "posttest": "eslint .",
diff --git a/resolvers/node/.npmrc b/resolvers/node/.npmrc
deleted file mode 100644
index 43c97e719a..0000000000
--- a/resolvers/node/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-package-lock=false
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index aa971afa30..5621965b57 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -7,6 +7,7 @@
     "index.js"
   ],
   "scripts": {
+    "prepublishOnly": "cp ../{LICENSE,.npmrc} ./",
     "test": "nyc mocha",
     "coveralls": "nyc report --reporter lcovonly && cd ../.. && coveralls < ./resolvers/node/coverage/lcov.info"
   },
diff --git a/resolvers/webpack/.npmrc b/resolvers/webpack/.npmrc
deleted file mode 120000
index cba44bb384..0000000000
--- a/resolvers/webpack/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-../../.npmrc
\ No newline at end of file
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 924f2bca6c..fbdac10235 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -4,6 +4,7 @@
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {
+    "prepublishOnly": "cp ../{LICENSE,.npmrc} ./",
     "test": "nyc mocha -t 5s",
     "report": "nyc report --reporter=html",
     "coveralls": "nyc report --reporter lcovonly && cd ../.. && coveralls < ./resolvers/webpack/coverage/lcov.info"
diff --git a/utils/.npmrc b/utils/.npmrc
deleted file mode 100644
index 43c97e719a..0000000000
--- a/utils/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-package-lock=false
diff --git a/utils/package.json b/utils/package.json
index 459f7c4388..0a7a7fe008 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -6,6 +6,7 @@
     "node": ">=4"
   },
   "scripts": {
+    "prepublishOnly": "cp ../{LICENSE,.npmrc} ./",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "repository": {

From 25895d7de4d6b8dbc0dd21f85fea62404f560315 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 10 Jan 2020 22:28:47 -0800
Subject: [PATCH 082/767] [memo-parser] v0.2.1

---
 memo-parser/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/memo-parser/package.json b/memo-parser/package.json
index 09577967c6..69996d33eb 100644
--- a/memo-parser/package.json
+++ b/memo-parser/package.json
@@ -1,6 +1,6 @@
 {
   "name": "memo-parser",
-  "version": "0.2.0",
+  "version": "0.2.1",
   "engines": {
     "node": ">=4"
   },

From 24ce28df2c5991e52e99c27b9dd9c855478862a4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 10 Jan 2020 22:31:53 -0800
Subject: [PATCH 083/767] utils: v2.5.1

---
 utils/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/utils/package.json b/utils/package.json
index 0a7a7fe008..8bf67a9252 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.5.0",
+  "version": "2.5.1",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From b9459f0ea3bc6a24f73276d5bd52651a606f965b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 10 Jan 2020 22:33:52 -0800
Subject: [PATCH 084/767] resolvers/node: v0.3.3

---
 resolvers/node/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 5621965b57..22237d71ff 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-node",
-  "version": "0.3.2",
+  "version": "0.3.3",
   "description": "Node default behavior import resolution plugin for eslint-plugin-import.",
   "main": "index.js",
   "files": [

From a5c6908bac4f5201b38cd1378765ae8dc6af5c83 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 10 Jan 2020 22:35:39 -0800
Subject: [PATCH 085/767] resolvers/webpack: v0.12.1

---
 resolvers/webpack/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index fbdac10235..a8f8ae7102 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.12.0",
+  "version": "0.12.1",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 8001916392c281f288eb5c33c6cf23dd7ab99673 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 10 Jan 2020 22:26:57 -0800
Subject: [PATCH 086/767] Bump to v2.20.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index de44575690..e89efd1bee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+
+## [2.20.0] - 2020-01-10
 ### Added
 - [`order`]: added `caseInsensitive` as an additional option to `alphabetize` ([#1586], thanks [@dbrewer5])
 - [`no-restricted-paths`]: New `except` option per `zone`, allowing exceptions to be defined for a restricted zone ([#1238], thanks [@rsolomon])
@@ -881,7 +883,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.1...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.0...HEAD
+[2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.1...v2.20.0
 [2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.0...v2.19.1
 [2.19.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.2...v2.19.0
 [2.18.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.1...v2.18.2
diff --git a/package.json b/package.json
index b303dbfb86..906cf8fa46 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.19.1",
+  "version": "2.20.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From d8c679584123d376d9256a6965ae5c69af7a5f95 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 10 Jan 2020 23:03:43 -0800
Subject: [PATCH 087/767] [meta] resolvers/*: fix prepublish script

---
 resolvers/node/package.json    | 2 +-
 resolvers/webpack/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 22237d71ff..f197babbf7 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -7,7 +7,7 @@
     "index.js"
   ],
   "scripts": {
-    "prepublishOnly": "cp ../{LICENSE,.npmrc} ./",
+    "prepublishOnly": "cp ../../{LICENSE,.npmrc} ./",
     "test": "nyc mocha",
     "coveralls": "nyc report --reporter lcovonly && cd ../.. && coveralls < ./resolvers/node/coverage/lcov.info"
   },
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index a8f8ae7102..d48d3f7a98 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -4,7 +4,7 @@
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {
-    "prepublishOnly": "cp ../{LICENSE,.npmrc} ./",
+    "prepublishOnly": "cp ../../{LICENSE,.npmrc} ./",
     "test": "nyc mocha -t 5s",
     "report": "nyc report --reporter=html",
     "coveralls": "nyc report --reporter lcovonly && cd ../.. && coveralls < ./resolvers/webpack/coverage/lcov.info"

From bcd9fe80557e4824bfe27a6690d96e7e25108fba Mon Sep 17 00:00:00 2001
From: Napoleon Oikonomou <Napoleonoikon@gmail.com>
Date: Sat, 11 Jan 2020 21:47:01 +0200
Subject: [PATCH 088/767] utils: [fix] prefer `createRequire` if available

---
 utils/CHANGELOG.md | 7 ++++++-
 utils/resolve.js   | 5 +++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 4573f794bc..0a1f721060 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+- Use `createRequire` instead of `createRequireFromPath` if available ([#1602], thanks [@iamnapo])
+
+## v2.5.1 - 2020-01-11
+
 ### Fixed
 - Uses createRequireFromPath to resolve loaders ([#1591], thanks [@arcanis])
 - report the error stack on a resolution error ([#599], thanks [@sompylasar])
@@ -62,7 +66,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
-
+[#1602]: https://github.com/benmosher/eslint-plugin-import/pull/1602
 [#1591]: https://github.com/benmosher/eslint-plugin-import/pull/1591
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
@@ -84,3 +88,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@JounQin]: https://github.com/JounQin
 [@arcanis]: https://github.com/arcanis
 [@sompylasar]: https://github.com/sompylasar
+[@iamnapo]: https://github.com/iamnapo
diff --git a/utils/resolve.js b/utils/resolve.js
index 3dc15f022a..14fe01a9cf 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -18,7 +18,8 @@ const ERROR_NAME = 'EslintPluginImportResolveError'
 const fileExistsCache = new ModuleCache()
 
 // Polyfill Node's `Module.createRequireFromPath` if not present (added in Node v10.12.0)
-const createRequireFromPath = Module.createRequireFromPath || function (filename) {
+// Use `Module.createRequire` if available (added in Node v12.2.0)
+const createRequire = Module.createRequire || Module.createRequireFromPath || function (filename) {
   const mod = new Module(filename, null)
   mod.filename = filename
   mod.paths = Module._nodeModulePaths(path.dirname(filename))
@@ -33,7 +34,7 @@ function tryRequire(target, sourceFile) {
   try {
     // Check if the target exists
     if (sourceFile != null) {
-      resolved = createRequireFromPath(sourceFile).resolve(target)
+      resolved = createRequire(path.resolve(sourceFile)).resolve(target)
     } else {
       resolved = require.resolve(target)
     }

From cd14858e32b246bad9ecccd1c766bacf31d0aa7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ma=C3=ABl=20Nison?= <nison.mael@gmail.com>
Date: Sun, 12 Jan 2020 10:13:19 +0100
Subject: [PATCH 089/767] utils: [Fix] Makes the loader resolution more
 tolerant

Fixes #1604. Fixes #1603.
---
 utils/CHANGELOG.md | 2 ++
 utils/resolve.js   | 6 +++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 0a1f721060..8eb57e525e 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+- Makes the loader resolution more tolerant ([#1606], thanks [@arcanis])
 - Use `createRequire` instead of `createRequireFromPath` if available ([#1602], thanks [@iamnapo])
 
 ## v2.5.1 - 2020-01-11
@@ -66,6 +67,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#1606]: https://github.com/benmosher/eslint-plugin-import/pull/1606
 [#1602]: https://github.com/benmosher/eslint-plugin-import/pull/1602
 [#1591]: https://github.com/benmosher/eslint-plugin-import/pull/1591
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
diff --git a/utils/resolve.js b/utils/resolve.js
index 14fe01a9cf..3138194a94 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -34,7 +34,11 @@ function tryRequire(target, sourceFile) {
   try {
     // Check if the target exists
     if (sourceFile != null) {
-      resolved = createRequire(path.resolve(sourceFile)).resolve(target)
+      try {
+        resolved = createRequire(path.resolve(sourceFile)).resolve(target)
+      } catch (e) {
+        resolved = require.resolve(target)
+      }
     } else {
       resolved = require.resolve(target)
     }

From 2c57742ca3f7517f8d6a01b6a4333d9b8ef91578 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 12 Jan 2020 13:43:47 -0800
Subject: [PATCH 090/767] utils: v2.5.2

---
 utils/CHANGELOG.md | 3 +++
 utils/package.json | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 8eb57e525e..61671ba89c 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v2.5.2 - 2020-01-12
+
+### Fixed
 - Makes the loader resolution more tolerant ([#1606], thanks [@arcanis])
 - Use `createRequire` instead of `createRequireFromPath` if available ([#1602], thanks [@iamnapo])
 
diff --git a/utils/package.json b/utils/package.json
index 8bf67a9252..b8d4033e66 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.5.1",
+  "version": "2.5.2",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From 71e87da176b849c90db24b0f63fd0ecab702610b Mon Sep 17 00:00:00 2001
From: Masataka Pocke Kuwabara <kuwabara@pocke.me>
Date: Tue, 14 Jan 2020 12:37:08 +0900
Subject: [PATCH 091/767] [meta] Merge duplicated `Added` section; fix link

---
 CHANGELOG.md | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e89efd1bee..b2816d768d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,10 +10,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Added
 - [`order`]: added `caseInsensitive` as an additional option to `alphabetize` ([#1586], thanks [@dbrewer5])
 - [`no-restricted-paths`]: New `except` option per `zone`, allowing exceptions to be defined for a restricted zone ([#1238], thanks [@rsolomon])
+- [`order`]: add option pathGroupsExcludedImportTypes to allow ordering of external import types ([#1565], thanks [@Mairu])
 
 ### Fixed
 - [`no-unused-modules`]: fix usage of `import/extensions` settings ([#1560], thanks [@stekycz])
-- [`import/extensions`]: ignore non-main modules ([#1563], thanks [@saschanaz])
+- [`extensions`]: ignore non-main modules ([#1563], thanks [@saschanaz])
 - TypeScript config: lookup for external modules in @types folder ([#1526], thanks [@joaovieira])
 - [`no-extraneous-dependencies`]: ensure `node.source` is truthy ([#1589], thanks [@ljharb])
 - [`extensions`]: Ignore query strings when checking for extensions ([#1572], thanks [@pcorpet])
@@ -21,9 +22,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Docs
 - [`extensions`]: improve `ignorePackages` docs ([#1248], thanks [@ivo-stefchev])
 
-### Added
-- [`order`]: add option pathGroupsExcludedImportTypes to allow ordering of external import types ([#1565], thanks [@Mairu])
-
 ## [2.19.1] - 2019-12-08
 ### Fixed
 - [`no-extraneous-dependencies`]: ensure `node.source` exists

From bbe456c13e91cdd64f564e2bd9540058366b38ea Mon Sep 17 00:00:00 2001
From: Sam Kozin <sam.kozin@gmail.com>
Date: Sun, 12 Jan 2020 01:28:55 +0300
Subject: [PATCH 092/767] [Tests] enable a skipped test that's not failing
 anymore

This test was added and skipped in #794 (probably since it was failing then), but it's not failing anymore on current master
---
 tests/src/core/importType.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 034b3cbbcf..f1e951cc47 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -48,7 +48,7 @@ describe('importType(name)', function () {
     expect(importType('importType', pathContext)).to.equal('internal')
   })
 
-  it.skip("should return 'internal' for scoped packages resolved outside of node_modules", function () {
+  it("should return 'internal' for scoped packages resolved outside of node_modules", function () {
     const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
     expect(importType('@importType/index', pathContext)).to.equal('internal')
   })

From b4d5fd38a29073e273523e262d7d59a7c48e30fe Mon Sep 17 00:00:00 2001
From: Sam Kozin <sam.kozin@gmail.com>
Date: Sun, 12 Jan 2020 01:32:33 +0300
Subject: [PATCH 093/767] [Fix] make 'import/order' work in a monorepo setup
 with scoped modules

Fixes #1597
---
 CHANGELOG.md                              |  7 ++
 README.md                                 | 14 +++-
 package.json                              |  1 +
 src/core/importType.js                    | 17 +++--
 tests/files/symlinked-module/index.js     |  1 +
 tests/files/symlinked-module/package.json |  5 ++
 tests/src/core/importType.js              | 81 ++++++++++++++++++++++-
 tests/src/rules/order.js                  | 48 ++++++++++++++
 8 files changed, 167 insertions(+), 7 deletions(-)
 create mode 100644 tests/files/symlinked-module/index.js
 create mode 100644 tests/files/symlinked-module/package.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b2816d768d..02c5a0d260 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+### Fixed
+- [`import/external-module-folders` setting] now correctly works with directories containing modules symlinked from `node_modules` ([#1605], thanks [@skozin])
+
+### Changed
+- [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
 
 ## [2.20.0] - 2020-01-10
 ### Added
@@ -636,6 +641,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
 [#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
 [#1572]: https://github.com/benmosher/eslint-plugin-import/pull/1572
@@ -1069,3 +1075,4 @@ for info on changes for earlier releases.
 [@rsolomon]: https://github.com/rsolomon
 [@joaovieira]: https://github.com/joaovieira
 [@ivo-stefchev]: https://github.com/ivo-stefchev
+[@skozin]: https://github.com/skozin
diff --git a/README.md b/README.md
index 814d5fc28d..2bd73a3ba3 100644
--- a/README.md
+++ b/README.md
@@ -339,7 +339,19 @@ Contribution of more such shared configs for other platforms are welcome!
 
 #### `import/external-module-folders`
 
-An array of folders. Resolved modules only from those folders will be considered as "external". By default - `["node_modules"]`. Makes sense if you have configured your path or webpack to handle your internal paths differently and want to considered modules from some folders, for example `bower_components` or `jspm_modules`, as "external".
+An array of folders. Resolved modules only from those folders will be considered as "external". By default - `["node_modules"]`. Makes sense if you have configured your path or webpack to handle your internal paths differently and want to consider modules from some folders, for example `bower_components` or `jspm_modules`, as "external".
+
+This option is also useful in a monorepo setup: list here all directories that contain monorepo's packages and they will be treated as external ones no matter which resolver is used.
+
+Each item in this array is either a folder's name, its subpath, or its absolute prefix path:
+
+- `jspm_modules` will match any file or folder named `jspm_modules` or which has a direct or non-direct parent named `jspm_modules`, e.g. `/home/me/project/jspm_modules` or `/home/me/project/jspm_modules/some-pkg/index.js`.
+
+- `packages/core` will match any path that contains these two segments, for example `/home/me/project/packages/core/src/utils.js`.
+
+- `/home/me/project/packages` will only match files and directories inside this directory, and the directory itself.
+
+Please note that incomplete names are not allowed here so `components` won't match `bower_components` and `packages/ui` won't match `packages/ui-utils` (but will match `packages/ui/utils`).
 
 #### `import/parsers`
 
diff --git a/package.json b/package.json
index 906cf8fa46..bfb70de07d 100644
--- a/package.json
+++ b/package.json
@@ -50,6 +50,7 @@
   "homepage": "https://github.com/benmosher/eslint-plugin-import",
   "devDependencies": {
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
+    "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "1.10.3-alpha.13",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
diff --git a/src/core/importType.js b/src/core/importType.js
index 8ec01c29e8..d99f9a3481 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -1,5 +1,4 @@
 import coreModules from 'resolve/lib/core'
-import { join } from 'path'
 
 import resolve from 'eslint-module-utils/resolve'
 
@@ -26,11 +25,19 @@ export function isBuiltIn(name, settings, path) {
 
 function isExternalPath(path, name, settings) {
   const folders = (settings && settings['import/external-module-folders']) || ['node_modules']
+  return !path || folders.some(folder => isSubpath(folder, path))
+}
 
-  // extract the part before the first / (redux-saga/effects => redux-saga)
-  const packageName = name.match(/([^/]+)/)[0]
-
-  return !path || folders.some(folder => -1 < path.indexOf(join(folder, packageName)))
+function isSubpath(subpath, path) {
+  const normSubpath = subpath.replace(/[/]$/, '')
+  if (normSubpath.length === 0) {
+    return false
+  }
+  const left = path.indexOf(normSubpath)
+  const right = left + normSubpath.length
+  return left !== -1 &&
+        (left === 0 || normSubpath[0] !== '/' && path[left - 1] === '/') &&
+        (right >= path.length || path[right] === '/')
 }
 
 const externalModuleRegExp = /^\w/
diff --git a/tests/files/symlinked-module/index.js b/tests/files/symlinked-module/index.js
new file mode 100644
index 0000000000..b1c6ea436a
--- /dev/null
+++ b/tests/files/symlinked-module/index.js
@@ -0,0 +1 @@
+export default {}
diff --git a/tests/files/symlinked-module/package.json b/tests/files/symlinked-module/package.json
new file mode 100644
index 0000000000..722be5c3c4
--- /dev/null
+++ b/tests/files/symlinked-module/package.json
@@ -0,0 +1,5 @@
+{
+  "name": "@test-scope/some-module",
+  "version": "1.0.0",
+  "private": true
+}
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index f1e951cc47..75be3101ed 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -3,7 +3,7 @@ import * as path from 'path'
 
 import importType from 'core/importType'
 
-import { testContext } from '../utils'
+import { testContext, testFilePath } from '../utils'
 
 describe('importType(name)', function () {
   const context = testContext()
@@ -145,4 +145,83 @@ describe('importType(name)', function () {
     const foldersContext = testContext({ 'import/external-module-folders': ['node_modules'] })
     expect(importType('resolve', foldersContext)).to.equal('external')
   })
+
+  it('returns "external" for a scoped symlinked module', function() {
+    const foldersContext = testContext({
+      'import/resolver': 'node',
+      'import/external-module-folders': ['node_modules'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
+  })
+
+  // We're using Webpack resolver here since it resolves all symlinks, which means that
+  // directory path will not contain node_modules/<package-name> but will point to the
+  // actual directory inside 'files' instead
+  it('returns "external" for a scoped module from a symlinked directory which name is contained in "external-module-folders" (webpack resolver)', function() {
+    const foldersContext = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': ['symlinked-module'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
+  })
+
+  it('returns "internal" for a scoped module from a symlinked directory which incomplete name is contained in "external-module-folders" (webpack resolver)', function() {
+    const foldersContext_1 = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': ['symlinked-mod'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext_1)).to.equal('internal')
+
+    const foldersContext_2 = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': ['linked-module'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal')
+  })
+
+  it('returns "external" for a scoped module from a symlinked directory which partial path is contained in "external-module-folders" (webpack resolver)', function() {
+    const foldersContext = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': ['files/symlinked-module'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
+  })
+
+  it('returns "internal" for a scoped module from a symlinked directory which partial path w/ incomplete segment is contained in "external-module-folders" (webpack resolver)', function() {
+    const foldersContext_1 = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': ['files/symlinked-mod'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext_1)).to.equal('internal')
+
+    const foldersContext_2 = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': ['les/symlinked-module'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal')
+  })
+
+  it('returns "external" for a scoped module from a symlinked directory which partial path ending w/ slash is contained in "external-module-folders" (webpack resolver)', function() {
+    const foldersContext = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': ['files/symlinked-module/'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
+  })
+
+  it('returns "internal" for a scoped module from a symlinked directory when "external-module-folders" contains an absolute path resembling directory‘s relative path (webpack resolver)', function() {
+    const foldersContext = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': ['/files/symlinked-module'],
+    })
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('internal')
+  })
+
+  it('returns "external" for a scoped module from a symlinked directory which absolute path is contained in "external-module-folders" (webpack resolver)', function() {
+    const foldersContext = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': [testFilePath('symlinked-module')],
+    })
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
+  })
 })
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 8ba8b9f1eb..29ecc28e2d 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -298,7 +298,55 @@ ruleTester.run('order', rule, {
         ],
       }],
     }),
+    // Monorepo setup, using Webpack resolver, workspace folder name in external-module-folders
+    test({
+      code: `
+        import _ from 'lodash';
+        import m from '@test-scope/some-module';
+
+        import bar from './bar';
+      `,
+      options: [{
+        'newlines-between': 'always',
+      }],
+      settings: {
+        'import/resolver': 'webpack',
+        'import/external-module-folders': ['node_modules', 'symlinked-module'],
+      },
+    }),
+    // Monorepo setup, using Webpack resolver, partial workspace folder path
+    // in external-module-folders
+    test({
+      code: `
+        import _ from 'lodash';
+        import m from '@test-scope/some-module';
+
+        import bar from './bar';
+      `,
+      options: [{
+        'newlines-between': 'always',
+      }],
+      settings: {
+        'import/resolver': 'webpack',
+        'import/external-module-folders': ['node_modules', 'files/symlinked-module'],
+      },
+    }),
+    // Monorepo setup, using Node resolver (doesn't resolve symlinks)
+    test({
+      code: `
+        import _ from 'lodash';
+        import m from '@test-scope/some-module';
 
+        import bar from './bar';
+      `,
+      options: [{
+        'newlines-between': 'always',
+      }],
+      settings: {
+        'import/resolver': 'node',
+        'import/external-module-folders': ['node_modules', 'files/symlinked-module'],
+      },
+    }),
     // Option: newlines-between: 'always'
     test({
       code: `

From 3908e6d349f04b5726b09479f67f937783bb7c1b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 15 Jan 2020 12:17:30 -0800
Subject: [PATCH 094/767] [Fix] `extensions`: for invalid code where `name`
 does not exist, do not crash

Fixes #1613
---
 CHANGELOG.md           | 2 ++
 src/core/importType.js | 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02c5a0d260..96b12e1577 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 ### Fixed
 - [`import/external-module-folders` setting] now correctly works with directories containing modules symlinked from `node_modules` ([#1605], thanks [@skozin])
+- [`extensions`]: for invalid code where `name` does not exist, do not crash ([#1613], thanks [@ljharb])
 
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
@@ -641,6 +642,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
 [#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
 [#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
diff --git a/src/core/importType.js b/src/core/importType.js
index d99f9a3481..311fd1e289 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -17,7 +17,7 @@ export function isAbsolute(name) {
 
 // path is defined only when a resolver resolves to a non-standard path
 export function isBuiltIn(name, settings, path) {
-  if (path) return false
+  if (path || !name) return false
   const base = baseModule(name)
   const extras = (settings && settings['import/core-modules']) || []
   return coreModules[base] || extras.indexOf(base) > -1
@@ -52,12 +52,12 @@ export function isExternalModuleMain(name, settings, path) {
 
 const scopedRegExp = /^@[^/]+\/?[^/]+/
 export function isScoped(name) {
-  return scopedRegExp.test(name)
+  return name && scopedRegExp.test(name)
 }
 
 const scopedMainRegExp = /^@[^/]+\/?[^/]+$/
 export function isScopedMain(name) {
-  return scopedMainRegExp.test(name)
+  return name && scopedMainRegExp.test(name)
 }
 
 function isInternalModule(name, settings, path) {

From 7e71b5090d18c0736778c6c8b5301b00c06c880b Mon Sep 17 00:00:00 2001
From: Yordis Prieto Lazo <yordis.prieto@gmail.com>
Date: Tue, 14 Jan 2020 15:16:32 -0800
Subject: [PATCH 095/767] [Fix] `extensions`: Fix scope regex

Fixes #1598.
---
 CHANGELOG.md                  | 3 +++
 src/core/importType.js        | 2 +-
 tests/src/rules/extensions.js | 1 +
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 96b12e1577..cfd4ad5eb3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`import/external-module-folders` setting] now correctly works with directories containing modules symlinked from `node_modules` ([#1605], thanks [@skozin])
 - [`extensions`]: for invalid code where `name` does not exist, do not crash ([#1613], thanks [@ljharb])
+- [`extentions`]: Fix scope regex ([#1611], thanks [@yordis])
 
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
@@ -643,6 +644,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
+[#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
 [#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
 [#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
@@ -1078,3 +1080,4 @@ for info on changes for earlier releases.
 [@joaovieira]: https://github.com/joaovieira
 [@ivo-stefchev]: https://github.com/ivo-stefchev
 [@skozin]: https://github.com/skozin
+[@yordis]: https://github.com/yordis
diff --git a/src/core/importType.js b/src/core/importType.js
index 311fd1e289..df60575c01 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -50,7 +50,7 @@ export function isExternalModuleMain(name, settings, path) {
   return externalModuleMainRegExp.test(name) && isExternalPath(path, name, settings)
 }
 
-const scopedRegExp = /^@[^/]+\/?[^/]+/
+const scopedRegExp = /^@[^/]*\/?[^/]+/
 export function isScoped(name) {
   return name && scopedRegExp.test(name)
 }
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 562802eef3..8cdb3399d8 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -6,6 +6,7 @@ const ruleTester = new RuleTester()
 
 ruleTester.run('extensions', rule, {
   valid: [
+    test({ code: 'import a from "@/a"' }),
     test({ code: 'import a from "a"' }),
     test({ code: 'import dot from "./file.with.dot"' }),
     test({

From f84d4577dc94600e28b2071ae365d671bfc6420e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Veyret?= <stephane@neptura.org>
Date: Wed, 15 Jan 2020 17:24:02 +0100
Subject: [PATCH 096/767] `no-duplicates`: allow duplicate if one is namespace
 and other not

It is a syntax error to put both namespace and non namespace import on the same line, so allow it.

Fixes #1538
---
 CHANGELOG.md                     |  3 +++
 src/rules/no-duplicates.js       |  5 ++++-
 tests/src/rules/no-duplicates.js | 27 +++++++++++++++++++++------
 3 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cfd4ad5eb3..db4aec82a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`import/external-module-folders` setting] now correctly works with directories containing modules symlinked from `node_modules` ([#1605], thanks [@skozin])
 - [`extensions`]: for invalid code where `name` does not exist, do not crash ([#1613], thanks [@ljharb])
 - [`extentions`]: Fix scope regex ([#1611], thanks [@yordis])
+- [`no-duplicates`]: allow duplicate imports if one is a namespace and the other not ([#1612], thanks [@sveyret])
 
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
@@ -644,6 +645,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
+[#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
 [#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
 [#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
 [#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
@@ -1081,3 +1083,4 @@ for info on changes for earlier releases.
 [@ivo-stefchev]: https://github.com/ivo-stefchev
 [@skozin]: https://github.com/skozin
 [@yordis]: https://github.com/yordis
+[@sveyret]: https://github.com/sveyret
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 1334a12582..69e5a23a02 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -257,12 +257,14 @@ module.exports = {
     }) : defaultResolver
 
     const imported = new Map()
+    const nsImported = new Map()
     const typesImported = new Map()
     return {
       'ImportDeclaration': function (n) {
         // resolved path will cover aliased duplicates
         const resolvedPath = resolver(n.source.value)
-        const importMap = n.importKind === 'type' ? typesImported : imported
+        const importMap = n.importKind === 'type' ? typesImported :
+          (hasNamespace(n) ? nsImported : imported)
 
         if (importMap.has(resolvedPath)) {
           importMap.get(resolvedPath).push(n)
@@ -273,6 +275,7 @@ module.exports = {
 
       'Program:exit': function () {
         checkImports(imported, context)
+        checkImports(nsImported, context)
         checkImports(typesImported, context)
       },
     }
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index a4c41f677a..468c7ab982 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -31,12 +31,20 @@ ruleTester.run('no-duplicates', rule, {
       code: "import x from './bar?optionX'; import y from './bar?optionY';",
       options: [{'considerQueryString': true}],
       settings: { 'import/resolver': 'webpack' },
-     }),
+    }),
     test({
       code: "import x from './foo'; import y from './bar';",
       options: [{'considerQueryString': true}],
       settings: { 'import/resolver': 'webpack' },
-     }),
+    }),
+
+    // #1538: It is impossible to import namespace and other in one line, so allow this.
+    test({
+      code: "import * as ns from './foo'; import {y} from './foo'",
+    }),
+    test({
+      code: "import {y} from './foo'; import * as ns from './foo'",
+    }),
   ],
   invalid: [
     test({
@@ -179,9 +187,16 @@ ruleTester.run('no-duplicates', rule, {
     }),
 
     test({
-      code: "import * as ns from './foo'; import {y} from './foo'",
-      // Autofix bail because first import is a namespace import.
-      output: "import * as ns from './foo'; import {y} from './foo'",
+      code: "import * as ns1 from './foo'; import * as ns2 from './foo'",
+      // Autofix bail because cannot merge namespace imports.
+      output: "import * as ns1 from './foo'; import * as ns2 from './foo'",
+      errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
+    }),
+
+    test({
+      code: "import * as ns from './foo'; import {x} from './foo'; import {y} from './foo'",
+      // Autofix could merge some imports, but not the namespace import.
+      output: "import * as ns from './foo'; import {x,y} from './foo'; ",
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
 
@@ -189,7 +204,7 @@ ruleTester.run('no-duplicates', rule, {
       code: "import {x} from './foo'; import * as ns from './foo'; import {y} from './foo'; import './foo'",
       // Autofix could merge some imports, but not the namespace import.
       output: "import {x,y} from './foo'; import * as ns from './foo';  ",
-      errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
+      errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
 
     test({

From 99647f1f9f5887e846182affb3f667343485bcee Mon Sep 17 00:00:00 2001
From: Blaine Bublitz <blaine@tidelift.com>
Date: Thu, 23 Jan 2020 11:50:34 -0700
Subject: [PATCH 097/767] [Docs]: Update Tidelift language to enterprise

---
 README.md | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 2bd73a3ba3..285bc18266 100644
--- a/README.md
+++ b/README.md
@@ -112,9 +112,11 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 [`no-named-export`]: ./docs/rules/no-named-export.md
 [`dynamic-import-chunkname`]: ./docs/rules/dynamic-import-chunkname.md
 
-## Support
+## `eslint-plugin-import` for enterprise
 
-[Get supported eslint-plugin-import with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-eslint-plugin-import?utm_source=npm-eslint-plugin-import&utm_medium=referral&utm_campaign=readme)
+Available as part of the Tidelift Subscription.
+
+The maintainers of `eslint-plugin-import` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-eslint-plugin-import?utm_source=npm-eslint-plugin-import&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
 
 ## Installation
 

From 26f232bb678463c8030840ffbd1af491200dffa0 Mon Sep 17 00:00:00 2001
From: Bryan Mishkin <698306+bmish@users.noreply.github.com>
Date: Mon, 20 Jan 2020 11:34:18 -0800
Subject: [PATCH 098/767] [Tests] add eslint-plugin-eslint-plugin internally
 and fix violations

This PR adds [eslint-plugin-eslint-plugin](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin) (a popular plugin for linting eslint plugins), enables relevant rules from it, and fixes violations.

The primary changes included are:
1. Adds missing rule schemas ([require-meta-schema](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/require-meta-schema.md)). Note that `schema: []` is added to enforce when a rule should have no schema.
2. Adds missing rule `type` property to `no-unused-modules` rule ([require-meta-type](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/require-meta-type.md)).
3. Removes duplicate test cases ([no-identical-tests](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-identical-tests.md)).
---
 .eslintrc.yml                                 | 12 ++++++++++++
 CHANGELOG.md                                  |  1 +
 package.json                                  |  1 +
 src/rules/default.js                          |  1 +
 src/rules/export.js                           |  1 +
 src/rules/exports-last.js                     |  1 +
 src/rules/first.js                            |  6 ++++++
 src/rules/named.js                            |  1 +
 src/rules/newline-after-import.js             |  2 +-
 src/rules/no-amd.js                           |  1 +
 src/rules/no-default-export.js                |  1 +
 src/rules/no-deprecated.js                    |  1 +
 src/rules/no-dynamic-require.js               |  1 +
 src/rules/no-mutable-exports.js               |  1 +
 src/rules/no-named-as-default-member.js       |  1 +
 src/rules/no-named-as-default.js              |  1 +
 src/rules/no-named-default.js                 |  1 +
 src/rules/no-named-export.js                  |  1 +
 src/rules/no-namespace.js                     |  1 +
 src/rules/no-nodejs-modules.js                | 15 +++++++++++++++
 src/rules/no-unused-modules.js                |  1 +
 src/rules/no-useless-path-segments.js         |  4 ++--
 src/rules/no-webpack-loader-syntax.js         |  1 +
 src/rules/prefer-default-export.js            |  1 +
 src/rules/unambiguous.js                      |  1 +
 tests/src/rules/default.js                    |  5 -----
 tests/src/rules/export.js                     |  2 --
 tests/src/rules/named.js                      |  1 -
 tests/src/rules/newline-after-import.js       | 10 ----------
 tests/src/rules/no-commonjs.js                |  3 +--
 tests/src/rules/no-extraneous-dependencies.js |  9 ---------
 tests/src/rules/no-unassigned-import.js       |  1 -
 32 files changed, 57 insertions(+), 33 deletions(-)

diff --git a/.eslintrc.yml b/.eslintrc.yml
index 5ee1be595b..c09d4f599e 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -1,8 +1,10 @@
 ---
 plugins:
+  - eslint-plugin
   - import
 extends:
   - eslint:recommended
+  - plugin:eslint-plugin/recommended
   - plugin:import/recommended
 
 env:
@@ -26,6 +28,16 @@ rules:
     - allowTemplateLiterals: true
       avoidEscape: true
 
+  eslint-plugin/consistent-output: "error"
+  eslint-plugin/meta-property-ordering: "error"
+  eslint-plugin/no-deprecated-context-methods: "error"
+  eslint-plugin/no-deprecated-report-api: "off"
+  eslint-plugin/prefer-output-null: "error"
+  eslint-plugin/prefer-replace-text: "error"
+  eslint-plugin/report-message-format: "error"
+  eslint-plugin/require-meta-schema: "error"
+  eslint-plugin/require-meta-type: "error"
+
   # dog fooding
   import/no-extraneous-dependencies: "error"
   import/unambiguous: "off"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index db4aec82a9..eee2fa8125 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extensions`]: for invalid code where `name` does not exist, do not crash ([#1613], thanks [@ljharb])
 - [`extentions`]: Fix scope regex ([#1611], thanks [@yordis])
 - [`no-duplicates`]: allow duplicate imports if one is a namespace and the other not ([#1612], thanks [@sveyret])
+- Add some missing rule meta schemas and types ([#1620], thanks [@bmish])
 
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
diff --git a/package.json b/package.json
index bfb70de07d..a06548bcd6 100644
--- a/package.json
+++ b/package.json
@@ -68,6 +68,7 @@
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
     "eslint-import-test-order-redirect": "file:./tests/files/order-redirect",
     "eslint-module-utils": "file:./utils",
+    "eslint-plugin-eslint-plugin": "^2.2.1",
     "eslint-plugin-import": "2.x",
     "linklocal": "^2.8.2",
     "mocha": "^3.5.3",
diff --git a/src/rules/default.js b/src/rules/default.js
index a524dcdc72..09efa0d880 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -7,6 +7,7 @@ module.exports = {
     docs: {
       url: docsUrl('default'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/export.js b/src/rules/export.js
index 9402bc9d87..dc73462285 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -45,6 +45,7 @@ module.exports = {
     docs: {
       url: docsUrl('export'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/exports-last.js b/src/rules/exports-last.js
index fc40cc8271..65dd8a30fa 100644
--- a/src/rules/exports-last.js
+++ b/src/rules/exports-last.js
@@ -12,6 +12,7 @@ module.exports = {
     docs: {
       url: docsUrl('exports-last'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/first.js b/src/rules/first.js
index 7bcd1fa22e..393cadb1fa 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -7,6 +7,12 @@ module.exports = {
       url: docsUrl('first'),
     },
     fixable: 'code',
+    schema: [
+      {
+        type: 'string',
+        enum: ['absolute-first'],
+      },
+    ],
   },
 
   create: function (context) {
diff --git a/src/rules/named.js b/src/rules/named.js
index cc9199d480..6853229b45 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -8,6 +8,7 @@ module.exports = {
     docs: {
       url: docsUrl('named'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index f5724ef4a3..690826eb42 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -49,6 +49,7 @@ module.exports = {
     docs: {
       url: docsUrl('newline-after-import'),
     },
+    fixable: 'whitespace',
     schema: [
       {
         'type': 'object',
@@ -61,7 +62,6 @@ module.exports = {
         'additionalProperties': false,
       },
     ],
-    fixable: 'whitespace',
   },
   create: function (context) {
     let level = 0
diff --git a/src/rules/no-amd.js b/src/rules/no-amd.js
index bb7c8ed826..a6a460bcf8 100644
--- a/src/rules/no-amd.js
+++ b/src/rules/no-amd.js
@@ -15,6 +15,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-amd'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index e1c687c9f7..0a46fd35f7 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -2,6 +2,7 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {},
+    schema: [],
   },
 
   create(context) {
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index 7a3130b20c..fc01d9dd10 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -21,6 +21,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-deprecated'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/no-dynamic-require.js b/src/rules/no-dynamic-require.js
index b9ccad27b3..9e7af8e283 100644
--- a/src/rules/no-dynamic-require.js
+++ b/src/rules/no-dynamic-require.js
@@ -19,6 +19,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-dynamic-require'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index 0908162bd1..7e94bfbe9b 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -6,6 +6,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-mutable-exports'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index b7c3c75827..b6e50cd713 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -18,6 +18,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-named-as-default-member'),
     },
+    schema: [],
   },
 
   create: function(context) {
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index ad6a8ee6d1..b4c64a34c9 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -8,6 +8,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-named-as-default'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/no-named-default.js b/src/rules/no-named-default.js
index 86f24ef6d1..f0b74a2ffb 100644
--- a/src/rules/no-named-default.js
+++ b/src/rules/no-named-default.js
@@ -6,6 +6,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-named-default'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/no-named-export.js b/src/rules/no-named-export.js
index 2fa6392014..e7d4b08351 100644
--- a/src/rules/no-named-export.js
+++ b/src/rules/no-named-export.js
@@ -4,6 +4,7 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: { url: docsUrl('no-named-export') },
+    schema: [],
   },
 
   create(context) {
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index a3a6913646..0b63132508 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -17,6 +17,7 @@ module.exports = {
       url: docsUrl('no-namespace'),
     },
     fixable: 'code',
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/no-nodejs-modules.js b/src/rules/no-nodejs-modules.js
index 125bb5f3f1..fb9bc23e28 100644
--- a/src/rules/no-nodejs-modules.js
+++ b/src/rules/no-nodejs-modules.js
@@ -14,6 +14,21 @@ module.exports = {
     docs: {
       url: docsUrl('no-nodejs-modules'),
     },
+    schema: [
+      {
+        type: 'object',
+        properties: {
+          allow: {
+            type: 'array',
+            uniqueItems: true,
+            items: {
+              type: 'string',
+            },
+          },
+        },
+        additionalProperties: false,
+      },
+    ],
   },
 
   create: function (context) {
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 5c6a73d828..44606dc857 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -305,6 +305,7 @@ const fileIsInPkg = file => {
 
 module.exports = {
   meta: {
+    type: 'suggestion',
     docs: { url: docsUrl('no-unused-modules') },
     schema: [{
       properties: {
diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index ea72e6c54b..785b98f0d6 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -43,6 +43,8 @@ module.exports = {
       url: docsUrl('no-useless-path-segments'),
     },
 
+    fixable: 'code',
+
     schema: [
       {
         type: 'object',
@@ -53,8 +55,6 @@ module.exports = {
         additionalProperties: false,
       },
     ],
-
-    fixable: 'code',
   },
 
   create(context) {
diff --git a/src/rules/no-webpack-loader-syntax.js b/src/rules/no-webpack-loader-syntax.js
index 723f472692..8075a6f9eb 100644
--- a/src/rules/no-webpack-loader-syntax.js
+++ b/src/rules/no-webpack-loader-syntax.js
@@ -15,6 +15,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-webpack-loader-syntax'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 17a07688c3..f1db4eaaa6 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -8,6 +8,7 @@ module.exports = {
     docs: {
       url: docsUrl('prefer-default-export'),
     },
+    schema: [],
   },
 
   create: function(context) {
diff --git a/src/rules/unambiguous.js b/src/rules/unambiguous.js
index 7ec38c2cb2..52c2f5ac19 100644
--- a/src/rules/unambiguous.js
+++ b/src/rules/unambiguous.js
@@ -12,6 +12,7 @@ module.exports = {
     docs: {
       url: docsUrl('unambiguous'),
     },
+    schema: [],
   },
 
   create: function (context) {
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index c21f1fd8c2..4544285afb 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -105,11 +105,6 @@ ruleTester.run('default', rule, {
       errors: [{ message: 'No default export found in imported module "./named-exports".'
                , type: 'ImportDefaultSpecifier'}]}),
 
-    test({
-      code: "import Foo from './jsx/FooES7.js';",
-      errors: ["Parse errors in imported module './jsx/FooES7.js': Unexpected token = (6:16)"],
-    }),
-
     // es7 export syntax
     test({
       code: 'export baz from "./named-exports"',
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index c7f303c4dd..bfe509065a 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -15,8 +15,6 @@ ruleTester.run('export', rule, {
     test({ code: 'export var foo = "foo", bar = "bar";' }),
     test({ code: 'export var { foo, bar } = object;' }),
     test({ code: 'export var [ foo, bar ] = array;' }),
-    test({ code: 'export var { foo, bar } = object;' }),
-    test({ code: 'export var [ foo, bar ] = array;' }),
     test({ code: 'let foo; export { foo, foo as bar }' }),
     test({ code: 'let bar; export { bar }; export * from "./export-all"' }),
     test({ code: 'export * from "./export-all"' }),
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 8318066496..a189fbfd12 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -173,7 +173,6 @@ ruleTester.run('named', rule, {
 
     test({
       code: 'import { a } from "./re-export-names"',
-      options: [2, 'es6-only'],
       errors: [error('a', './re-export-names')],
     }),
 
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 490fad97dd..220b217d77 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -210,16 +210,6 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       } ],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
-    {
-      code: `var foo = require('foo-module');\nvar something = 123;`,
-      output: `var foo = require('foo-module');\n\nvar something = 123;`,
-      errors: [ {
-        line: 1,
-        column: 1,
-        message: REQUIRE_ERROR_MESSAGE,
-      } ],
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
     {
       code: `import foo from 'foo';\nvar a = 123;\n\nimport { bar } from './bar-lib';\nvar b=456;`,
       output: `import foo from 'foo';\n\nvar a = 123;\n\nimport { bar } from './bar-lib';\n\nvar b=456;`,
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index 1bcbc65ab3..d471693154 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -13,7 +13,6 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
     // imports
     { code: 'import "x";', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
     { code: 'import x from "x"', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
-    { code: 'import x from "x"', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
     { code: 'import { x } from "x"', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
 
     // exports
@@ -61,7 +60,7 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
     { code: 'if (typeof window !== "undefined") require("x")', options: [{ allowRequire: false }] },
     { code: 'if (typeof window !== "undefined") { require("x") }', options: [{ allowRequire: true }] },
     { code: 'if (typeof window !== "undefined") { require("x") }', options: [{ allowRequire: false }] },
-  
+
     { code: 'try { require("x") } catch (error) {}' },
   ],
 
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 114a733af7..e70a601746 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -66,11 +66,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       options: [{devDependencies: ['*.test.js', '*.spec.js']}],
       filename: path.join(process.cwd(), 'foo.spec.js'),
     }),
-    test({
-      code: 'import chai from "chai"',
-      options: [{devDependencies: ['*.test.js', '*.spec.js']}],
-      filename: path.join(process.cwd(), 'foo.spec.js'),
-    }),
     test({ code: 'require(6)' }),
     test({
       code: 'import "doctrine"',
@@ -101,10 +96,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import leftpad from "left-pad";',
       options: [{packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested]}],
     }),
-    test({
-      code: 'import leftpad from "left-pad";',
-      options: [{packageDir: [packageDirMonoRepoWithNested, packageDirMonoRepoRoot]}],
-    }),
     test({
       code: 'import rightpad from "right-pad";',
       options: [{packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested]}],
diff --git a/tests/src/rules/no-unassigned-import.js b/tests/src/rules/no-unassigned-import.js
index 97be736134..414bfca90f 100644
--- a/tests/src/rules/no-unassigned-import.js
+++ b/tests/src/rules/no-unassigned-import.js
@@ -23,7 +23,6 @@ ruleTester.run('no-unassigned-import', rule, {
     test({ code: 'const {foo} = require("lodash")'}),
     test({ code: 'const {foo: bar} = require("lodash")'}),
     test({ code: 'const [a, b] = require("lodash")'}),
-    test({ code: 'const _ = require("lodash")'}),
     test({ code: 'const _ = require("./")'}),
     test({ code: 'foo(require("lodash"))'}),
     test({ code: 'require("lodash").foo'}),

From 2d424643b659b4bae542999c34425ab1485ae9c8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 25 Jan 2020 23:59:31 -0800
Subject: [PATCH 099/767] [Tests] only run the linter once, not on every build

---
 .travis.yml                    | 4 +++-
 package.json                   | 3 ++-
 resolvers/node/package.json    | 3 ++-
 resolvers/webpack/package.json | 3 ++-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index cd5650c65a..a6824a6c5c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,6 +19,8 @@ env:
 # osx backlog is often deep, so to be polite we can just hit these highlights
 matrix:
   include:
+  - env: LINT=true
+    node_js: lts/*
   - env: PACKAGE=resolvers/node
     node_js: 13
   - env: PACKAGE=resolvers/node
@@ -81,7 +83,7 @@ install:
   - 'if [ -n "${ESLINT_VERSION}" ]; then ./tests/dep-time-travel.sh; fi'
 
 script:
-  - 'npm test'
+  - 'if [ -n "${LINT-}" ]; then npm run posttest ; else npm run tests-only ; fi'
 
 after_success:
   - npm run coveralls
diff --git a/package.json b/package.json
index a06548bcd6..68e09f7d36 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,8 @@
     "pretest": "linklocal",
     "posttest": "eslint .",
     "mocha": "cross-env BABEL_ENV=test NODE_PATH=./src nyc -s mocha -R dot --recursive -t 5s",
-    "test": "npm run mocha tests/src",
+    "tests-only": "npm run mocha tests/src",
+    "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && NODE_PATH=./lib mocha --compilers js:babel-register --recursive tests/src",
     "test-all": "npm test && for resolver in ./resolvers/*; do cd $resolver && npm test && cd ../..; done",
     "prepublish": "npm run build",
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index f197babbf7..03eadafbf6 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -8,7 +8,8 @@
   ],
   "scripts": {
     "prepublishOnly": "cp ../../{LICENSE,.npmrc} ./",
-    "test": "nyc mocha",
+    "tests-only": "nyc mocha",
+    "test": "npm run tests-only",
     "coveralls": "nyc report --reporter lcovonly && cd ../.. && coveralls < ./resolvers/node/coverage/lcov.info"
   },
   "repository": {
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index d48d3f7a98..72959fa886 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -5,7 +5,8 @@
   "main": "index.js",
   "scripts": {
     "prepublishOnly": "cp ../../{LICENSE,.npmrc} ./",
-    "test": "nyc mocha -t 5s",
+    "tests-only": "nyc mocha -t 5s",
+    "test": "npm run tests-only",
     "report": "nyc report --reporter=html",
     "coveralls": "nyc report --reporter lcovonly && cd ../.. && coveralls < ./resolvers/webpack/coverage/lcov.info"
   },

From a4d301bac81551d16be7cc4737d8c66e7b46c38a Mon Sep 17 00:00:00 2001
From: Bryan Mishkin <698306+bmish@users.noreply.github.com>
Date: Sun, 26 Jan 2020 10:54:35 -0800
Subject: [PATCH 100/767] [meta] add missing changelog links

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index eee2fa8125..8d26428210 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -645,6 +645,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
 [#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
 [#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
 [#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
@@ -1085,3 +1086,4 @@ for info on changes for earlier releases.
 [@skozin]: https://github.com/skozin
 [@yordis]: https://github.com/yordis
 [@sveyret]: https://github.com/sveyret
+[@bmish]: https://github.com/bmish

From 6274d965340a7cedeb6e9a9d40e3df0b2a4275f1 Mon Sep 17 00:00:00 2001
From: Bryan Mishkin <698306+bmish@users.noreply.github.com>
Date: Sun, 26 Jan 2020 10:41:57 -0800
Subject: [PATCH 101/767] [Tests] set `eslint-plugin/consistent-output` lint
 rule to always require test case output assertions

Use the more strict option for this internal lint rule.

If a rule has no autofix, we should assert that there is no output. All of the test cases I fixed have no autofix, so the output matches the input. In eslint > v2, we can switch to `output: null` to represent this, and re-enable the `eslint-plugin/prefer-output-null` internal lint rule.

https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/consistent-output.md
https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/prefer-output-null.md
---
 .eslintrc.yml                               |  3 +-
 tests/src/rules/dynamic-import-chunkname.js | 83 +++++++++++++++++++++
 tests/src/rules/no-commonjs.js              | 21 ++++--
 tests/src/rules/unambiguous.js              |  1 +
 4 files changed, 98 insertions(+), 10 deletions(-)

diff --git a/.eslintrc.yml b/.eslintrc.yml
index c09d4f599e..8c270e9533 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -28,11 +28,10 @@ rules:
     - allowTemplateLiterals: true
       avoidEscape: true
 
-  eslint-plugin/consistent-output: "error"
+  eslint-plugin/consistent-output: ["error", "always"]
   eslint-plugin/meta-property-ordering: "error"
   eslint-plugin/no-deprecated-context-methods: "error"
   eslint-plugin/no-deprecated-report-api: "off"
-  eslint-plugin/prefer-output-null: "error"
   eslint-plugin/prefer-replace-text: "error"
   eslint-plugin/report-message-format: "error"
   eslint-plugin/require-meta-schema: "error"
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index d19667c162..e8cbb9c6f9 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -154,6 +154,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        // webpackChunkName: "someModule"
+        'someModule'
+      )`,
       errors: [{
         message: nonBlockCommentError,
         type: 'CallExpression',
@@ -163,6 +167,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       code: 'import(\'test\')',
       options,
       parser,
+      output: 'import(\'test\')',
       errors: [{
         message: noLeadingCommentError,
         type: 'CallExpression',
@@ -175,6 +180,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* webpackChunkName: someModule */
+        'someModule'
+      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
@@ -187,6 +196,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* webpackChunkName: 'someModule' */
+        'someModule'
+      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
@@ -199,6 +212,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* webpackChunkName "someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
@@ -211,6 +228,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* webpackChunkName:"someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
@@ -223,6 +244,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /*webpackChunkName: "someModule"*/
+        'someModule'
+      )`,
       errors: [{
         message: noPaddingCommentError,
         type: 'CallExpression',
@@ -235,6 +260,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* webpackChunkName  :  "someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
@@ -247,6 +276,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* webpackChunkName: "someModule" ; */
+        'someModule'
+      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
@@ -259,6 +292,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* totally not webpackChunkName: "someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
@@ -272,6 +309,11 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* webpackPrefetch: true */
+        /* webpackChunk: "someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
@@ -284,6 +326,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
+      output: `import(
+        /* webpackPrefetch: true, webpackChunk: "someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
@@ -296,6 +342,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options: pickyCommentOptions,
       parser,
+      output: `import(
+        /* webpackChunkName: "someModule123" */
+        'someModule'
+      )`,
       errors: [{
         message: pickyCommentFormatError,
         type: 'CallExpression',
@@ -307,6 +357,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options: multipleImportFunctionOptions,
+      output: `dynamicImport(
+        /* webpackChunkName "someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
@@ -318,6 +372,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options: multipleImportFunctionOptions,
+      output: `definitelyNotStaticImport(
+        /* webpackChunkName "someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
@@ -329,6 +387,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options,
+      output: `dynamicImport(
+        // webpackChunkName: "someModule"
+        'someModule'
+      )`,
       errors: [{
         message: nonBlockCommentError,
         type: 'CallExpression',
@@ -337,6 +399,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
     {
       code: 'dynamicImport(\'test\')',
       options,
+      output: 'dynamicImport(\'test\')',
       errors: [{
         message: noLeadingCommentError,
         type: 'CallExpression',
@@ -348,6 +411,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options,
+      output: `dynamicImport(
+        /* webpackChunkName: someModule */
+        'someModule'
+      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
@@ -359,6 +426,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options,
+      output: `dynamicImport(
+        /* webpackChunkName: 'someModule' */
+        'someModule'
+      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
@@ -370,6 +441,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options,
+      output: `dynamicImport(
+        /* webpackChunkName "someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
@@ -381,6 +456,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options,
+      output: `dynamicImport(
+        /* webpackChunkName:"someModule" */
+        'someModule'
+      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
@@ -392,6 +471,10 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options: pickyCommentOptions,
+      output: `dynamicImport(
+        /* webpackChunkName: "someModule123" */
+        'someModule'
+      )`,
       errors: [{
         message: pickyCommentFormatError,
         type: 'CallExpression',
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index d471693154..d2c4ed3100 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -68,36 +68,41 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
 
     // imports
     ...(semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
-      { code: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
-      { code: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
-      { code: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+      { code: 'var x = require("x")', output: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+      { code: 'x = require("x")', output: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+      { code: 'require("x")', output: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] },
 
       { code: 'if (typeof window !== "undefined") require("x")',
         options: [{ allowConditionalRequire: false }],
+        output: 'if (typeof window !== "undefined") require("x")',
         errors: [ { message: IMPORT_MESSAGE }],
       },
       { code: 'if (typeof window !== "undefined") { require("x") }',
         options: [{ allowConditionalRequire: false }],
+        output: 'if (typeof window !== "undefined") { require("x") }',
         errors: [ { message: IMPORT_MESSAGE }],
       },
       { code: 'try { require("x") } catch (error) {}',
         options: [{ allowConditionalRequire: false }],
+        output: 'try { require("x") } catch (error) {}',
         errors: [ { message: IMPORT_MESSAGE }],
       },
     ]),
 
     // exports
-    { code: 'exports.face = "palm"', errors: [ { message: EXPORT_MESSAGE }] },
-    { code: 'module.exports.face = "palm"', errors: [ { message: EXPORT_MESSAGE }] },
-    { code: 'module.exports = face', errors: [ { message: EXPORT_MESSAGE }] },
-    { code: 'exports = module.exports = {}', errors: [ { message: EXPORT_MESSAGE }] },
-    { code: 'var x = module.exports = {}', errors: [ { message: EXPORT_MESSAGE }] },
+    { code: 'exports.face = "palm"', output: 'exports.face = "palm"', errors: [ { message: EXPORT_MESSAGE }] },
+    { code: 'module.exports.face = "palm"', output: 'module.exports.face = "palm"', errors: [ { message: EXPORT_MESSAGE }] },
+    { code: 'module.exports = face', output: 'module.exports = face', errors: [ { message: EXPORT_MESSAGE }] },
+    { code: 'exports = module.exports = {}', output: 'exports = module.exports = {}', errors: [ { message: EXPORT_MESSAGE }] },
+    { code: 'var x = module.exports = {}', output: 'var x = module.exports = {}', errors: [ { message: EXPORT_MESSAGE }] },
     { code: 'module.exports = {}',
       options: ['allow-primitive-modules'],
+      output: 'module.exports = {}',
       errors: [ { message: EXPORT_MESSAGE }],
     },
     { code: 'var x = module.exports',
       options: ['allow-primitive-modules'],
+      output: 'var x = module.exports',
       errors: [ { message: EXPORT_MESSAGE }],
     },
   ],
diff --git a/tests/src/rules/unambiguous.js b/tests/src/rules/unambiguous.js
index 09ca57ef9a..705ce79d10 100644
--- a/tests/src/rules/unambiguous.js
+++ b/tests/src/rules/unambiguous.js
@@ -50,6 +50,7 @@ ruleTester.run('unambiguous', rule, {
     {
       code: 'function x() {}',
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      output: 'function x() {}',
       errors: ['This module could be parsed as a valid script.'],
     },
   ],

From 986ba749fec01b5e49922c215e0c0de8db9562c1 Mon Sep 17 00:00:00 2001
From: Bryan Mishkin <698306+bmish@users.noreply.github.com>
Date: Mon, 27 Jan 2020 12:56:05 -0800
Subject: [PATCH 102/767] docs: fix a few spelling mistakes

Searched using cspell.
---
 README.md            | 4 ++--
 src/ExportMap.js     | 2 +-
 utils/ModuleCache.js | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 285bc18266..cc9d1d789b 100644
--- a/README.md
+++ b/README.md
@@ -420,9 +420,9 @@ settings:
 
 A regex for packages should be treated as internal. Useful when you are utilizing a monorepo setup or developing a set of packages that depend on each other.
 
-By default, any package referenced from [`import/external-module-folders`](#importexternal-module-folders) will be considered as "external", including packages in a monorepo like yarn workspace or lerna emvironentment. If you want to mark these packages as "internal" this will be useful.
+By default, any package referenced from [`import/external-module-folders`](#importexternal-module-folders) will be considered as "external", including packages in a monorepo like yarn workspace or lerna environment. If you want to mark these packages as "internal" this will be useful.
 
-For example, if you pacakges in a monorepo are all in `@scope`, you can configure `import/internal-regex` like this
+For example, if your packages in a monorepo are all in `@scope`, you can configure `import/internal-regex` like this
 
 ```yaml
 # .eslintrc.yml
diff --git a/src/ExportMap.js b/src/ExportMap.js
index ba455e3685..5f95efa1ac 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -319,7 +319,7 @@ ExportMap.for = function (context) {
 
   const content = fs.readFileSync(path, { encoding: 'utf8' })
 
-  // check for and cache unambigious modules
+  // check for and cache unambiguous modules
   if (!unambiguous.test(content)) {
     log('ignored path due to unambiguous regex:', path)
     exportCache.set(cacheKey, null)
diff --git a/utils/ModuleCache.js b/utils/ModuleCache.js
index ab0266fe58..b910a5810a 100644
--- a/utils/ModuleCache.js
+++ b/utils/ModuleCache.js
@@ -22,7 +22,7 @@ class ModuleCache {
   get(cacheKey, settings) {
     if (this.map.has(cacheKey)) {
       const f = this.map.get(cacheKey)
-      // check fresness
+      // check freshness
       if (process.hrtime(f.lastSeen)[0] < settings.lifetime) return f.result
     } else log('cache miss for', cacheKey)
     // cache miss

From aff3a467f0a7cb982b3e82ef3bf3732ee0fbf449 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 29 Jan 2020 11:01:04 -0800
Subject: [PATCH 103/767] [meta] fix "files" field to include/exclude the
 proper files

Fixes #1635.
---
 CHANGELOG.md | 2 ++
 package.json | 5 ++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8d26428210..c3ae3a21ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
+- [meta] fix "files" field to include/exclude the proper files ([#1635], thanks [@ljharb])
 
 ## [2.20.0] - 2020-01-10
 ### Added
@@ -645,6 +646,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
 [#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
 [#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
 [#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
diff --git a/package.json b/package.json
index 68e09f7d36..4877320d36 100644
--- a/package.json
+++ b/package.json
@@ -10,9 +10,12 @@
     "test": "tests"
   },
   "files": [
+    "*.md",
+    "LICENSE",
+    "docs",
     "lib",
     "config",
-    "memo-parser"
+    "memo-parser/{*.js,LICENSE,*.md}"
   ],
   "scripts": {
     "prebuild": "rimraf lib",

From cc5bde5a526136530ceb4966c4245eeb36c3fc2c Mon Sep 17 00:00:00 2001
From: "Kent C. Dodds" <kent@doddsfamily.us>
Date: Wed, 7 Aug 2019 13:07:09 -0600
Subject: [PATCH 104/767] [Tests] `named`: add failing test for #1446

---
 tests/files/re-export-node_modules.js | 1 +
 tests/src/rules/named.js              | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 tests/files/re-export-node_modules.js

diff --git a/tests/files/re-export-node_modules.js b/tests/files/re-export-node_modules.js
new file mode 100644
index 0000000000..53a8ed162f
--- /dev/null
+++ b/tests/files/re-export-node_modules.js
@@ -0,0 +1 @@
+export * from 'eslint'
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index a189fbfd12..b010dfd255 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -26,6 +26,7 @@ ruleTester.run('named', rule, {
     test({code: 'import { destructingRenamedAssign } from "./named-exports"'}),
     test({code: 'import { ActionTypes } from "./qc"'}),
     test({code: 'import {a, b, c, d} from "./re-export"'}),
+    test({code: 'import {RuleTester} from "./re-export-node_modules"'}),
 
     test({ code: 'import { jsxFoo } from "./jsx/AnotherComponent"'
          , settings: { 'import/resolve': { 'extensions': ['.js', '.jsx'] } } }),

From 392c6b9c44b8fab54d973b9e344ce1c0c6d1a1cc Mon Sep 17 00:00:00 2001
From: redbugz <allredlt@familysearch.org>
Date: Thu, 12 Dec 2019 01:43:02 -0700
Subject: [PATCH 105/767] [Fix] `named`: for importing from a module which
 re-exports named exports from a `node_modules` module

Fixes #1446.
---
 CHANGELOG.md                         | 5 +++++
 src/ExportMap.js                     | 1 +
 tests/files/re-export-common-star.js | 1 +
 tests/src/rules/named.js             | 1 +
 4 files changed, 8 insertions(+)
 create mode 100644 tests/files/re-export-common-star.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c3ae3a21ad..609762ffbe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extentions`]: Fix scope regex ([#1611], thanks [@yordis])
 - [`no-duplicates`]: allow duplicate imports if one is a namespace and the other not ([#1612], thanks [@sveyret])
 - Add some missing rule meta schemas and types ([#1620], thanks [@bmish])
+- [`named`]: for importing from a module which re-exports named exports from a `node_modules` module ([#1569], [#1447], thanks [@redbugz], [@kentcdodds])
 
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
@@ -655,6 +656,7 @@ for info on changes for earlier releases.
 [#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
 [#1572]: https://github.com/benmosher/eslint-plugin-import/pull/1572
+[#1569]: https://github.com/benmosher/eslint-plugin-import/pull/1569
 [#1563]: https://github.com/benmosher/eslint-plugin-import/pull/1563
 [#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
@@ -670,6 +672,7 @@ for info on changes for earlier releases.
 [#1493]: https://github.com/benmosher/eslint-plugin-import/pull/1493
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
+[#1447]: https://github.com/benmosher/eslint-plugin-import/pull/1447
 [#1439]: https://github.com/benmosher/eslint-plugin-import/pull/1439
 [#1436]: https://github.com/benmosher/eslint-plugin-import/pull/1436
 [#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
@@ -1089,3 +1092,5 @@ for info on changes for earlier releases.
 [@yordis]: https://github.com/yordis
 [@sveyret]: https://github.com/sveyret
 [@bmish]: https://github.com/bmish
+[@redbugz]: https://github.com/redbugz
+[@kentcdodds]: https://github.com/kentcdodds
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 5f95efa1ac..525f64a48a 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -106,6 +106,7 @@ export default class ExportMap {
     if (name !== 'default') {
       for (let dep of this.dependencies) {
         let innerMap = dep()
+        if (innerMap == null) return { found: true, path: [this] }
         // todo: report as unresolved?
         if (!innerMap) continue
 
diff --git a/tests/files/re-export-common-star.js b/tests/files/re-export-common-star.js
new file mode 100644
index 0000000000..89a3196b12
--- /dev/null
+++ b/tests/files/re-export-common-star.js
@@ -0,0 +1 @@
+export * from './common'
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index b010dfd255..303df1e145 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -26,6 +26,7 @@ ruleTester.run('named', rule, {
     test({code: 'import { destructingRenamedAssign } from "./named-exports"'}),
     test({code: 'import { ActionTypes } from "./qc"'}),
     test({code: 'import {a, b, c, d} from "./re-export"'}),
+    test({code: 'import {a, b, c} from "./re-export-common-star"'}),
     test({code: 'import {RuleTester} from "./re-export-node_modules"'}),
 
     test({ code: 'import { jsxFoo } from "./jsx/AnotherComponent"'

From 4665ec5a687d068e4e4ab19e3dbde7d0c65bbee4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 1 Feb 2020 14:12:02 -0800
Subject: [PATCH 106/767] [Fix] `no-absolute-path`: fix a crash with invalid
 import syntax

Fixes #1616
---
 CHANGELOG.md                  | 2 ++
 src/rules/no-absolute-path.js | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 609762ffbe..bd7f900ef9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 ### Fixed
+- [`no-absolute-path`]: fix a crash with invalid import syntax ([#1616], thanks [@ljharb])
 - [`import/external-module-folders` setting] now correctly works with directories containing modules symlinked from `node_modules` ([#1605], thanks [@skozin])
 - [`extensions`]: for invalid code where `name` does not exist, do not crash ([#1613], thanks [@ljharb])
 - [`extentions`]: Fix scope regex ([#1611], thanks [@yordis])
@@ -649,6 +650,7 @@ for info on changes for earlier releases.
 
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
 [#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
+[#1616]: https://github.com/benmosher/eslint-plugin-import/issues/1616
 [#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
 [#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
 [#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index 4b7a8fcc2a..2cc0f6ae0f 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -13,7 +13,7 @@ module.exports = {
 
   create: function (context) {
     function reportIfAbsolute(source) {
-      if (isAbsolute(source.value)) {
+      if (typeof source.value === 'string' && isAbsolute(source.value)) {
         context.report(source, 'Do not import modules using an absolute path')
       }
     }

From bbd166bfe2e5a12b58cbe803acda3e67e099562c Mon Sep 17 00:00:00 2001
From: Ivan Goncharov <ivan.goncharov.ua@gmail.com>
Date: Tue, 21 Jan 2020 01:03:40 +0800
Subject: [PATCH 107/767] [Fix] `export`: Handle function overloading in
 `*.d.ts`

---
 CHANGELOG.md              | 3 +++
 src/rules/export.js       | 8 +++++++-
 tests/src/rules/export.js | 7 +++++++
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd7f900ef9..165df6e544 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 ### Fixed
+- [`export`]: Handle function overloading in `*.d.ts` ([#1619], thanks [@IvanGoncharov])
 - [`no-absolute-path`]: fix a crash with invalid import syntax ([#1616], thanks [@ljharb])
 - [`import/external-module-folders` setting] now correctly works with directories containing modules symlinked from `node_modules` ([#1605], thanks [@skozin])
 - [`extensions`]: for invalid code where `name` does not exist, do not crash ([#1613], thanks [@ljharb])
@@ -650,6 +651,7 @@ for info on changes for earlier releases.
 
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
 [#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
+[#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
 [#1616]: https://github.com/benmosher/eslint-plugin-import/issues/1616
 [#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
 [#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
@@ -1096,3 +1098,4 @@ for info on changes for earlier releases.
 [@bmish]: https://github.com/bmish
 [@redbugz]: https://github.com/redbugz
 [@kentcdodds]: https://github.com/kentcdodds
+[@IvanGoncharov]: https://github.com/IvanGoncharov
diff --git a/src/rules/export.js b/src/rules/export.js
index dc73462285..f131374df3 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -36,7 +36,13 @@ const tsTypePrefix = 'type:'
  */
 function isTypescriptFunctionOverloads(nodes) {
   const types = new Set(Array.from(nodes, node => node.parent.type))
-  return types.size === 2 && types.has('TSDeclareFunction') && types.has('FunctionDeclaration')
+  return (
+    types.has('TSDeclareFunction') &&
+    (
+      types.size === 1 ||
+      (types.size === 2 && types.has('FunctionDeclaration'))
+    )
+  )
 }
 
 module.exports = {
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index bfe509065a..76fae45676 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -132,6 +132,13 @@ context('TypeScript', function () {
           `,
         }, parserConfig)),
 
+        test(Object.assign({
+          code: `
+            export function fff(a: string);
+            export function fff(a: number);
+          `,
+        }, parserConfig)),
+
         test(Object.assign({
           code: `
             export function fff(a: string);

From 5d00854f3c59a497f0a850c6ccab01a012d6b8db Mon Sep 17 00:00:00 2001
From: William Schurman <wschurman@gmail.com>
Date: Thu, 23 Jan 2020 17:45:24 -0700
Subject: [PATCH 108/767] [Fix] `order`: Fix alphabetize for mixed requires and
 imports

Fixes #1625
---
 CHANGELOG.md             |  3 +++
 src/rules/order.js       |  2 +-
 tests/src/rules/order.js | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 165df6e544..4701322eeb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-duplicates`]: allow duplicate imports if one is a namespace and the other not ([#1612], thanks [@sveyret])
 - Add some missing rule meta schemas and types ([#1620], thanks [@bmish])
 - [`named`]: for importing from a module which re-exports named exports from a `node_modules` module ([#1569], [#1447], thanks [@redbugz], [@kentcdodds])
+- [`order`]: Fix alphabetize for mixed requires and imports ([#5625], thanks [@wschurman])
 
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
@@ -650,6 +651,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
+[#1625]: https://github.com/benmosher/eslint-plugin-import/pull/1625
 [#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
 [#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
 [#1616]: https://github.com/benmosher/eslint-plugin-import/issues/1616
@@ -1099,3 +1101,4 @@ for info on changes for earlier releases.
 [@redbugz]: https://github.com/redbugz
 [@kentcdodds]: https://github.com/kentcdodds
 [@IvanGoncharov]: https://github.com/IvanGoncharov
+[@wschurman]: https://github.com/wschurman
diff --git a/src/rules/order.js b/src/rules/order.js
index fcdf12bda5..948c5f4272 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -289,7 +289,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
   let newRank = 0
   const alphabetizedRanks = groupRanks.sort().reduce(function(acc, groupRank) {
     groupedByRanks[groupRank].forEach(function(importedItemName) {
-      acc[importedItemName] = newRank
+      acc[importedItemName] = parseInt(groupRank, 10) + newRank
       newRank += 1
     })
     return acc
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 29ecc28e2d..d5a0dd98bc 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -645,6 +645,22 @@ ruleTester.run('order', rule, {
         'newlines-between': 'always',
       }],
     }),
+    // Alphabetize with require
+    test({
+      code: `
+        import { hello } from './hello';
+        import { int } from './int';
+        const blah = require('./blah');
+        const { cello } = require('./cello');
+      `,
+      options: [
+        {
+          alphabetize: {
+            order: 'asc',
+          },
+        },
+      ],
+    }),
   ],
   invalid: [
     // builtin before external module (require)
@@ -1986,5 +2002,21 @@ ruleTester.run('order', rule, {
         message: '`foo` import should occur before import of `Bar`',
       }],
     }),
+    // Alphabetize with require
+    test({
+      code: `
+        const { cello } = require('./cello');
+        import { int } from './int';
+        const blah = require('./blah');
+        import { hello } from './hello';
+      `,
+      errors: [{
+        ruleId: 'order',
+        message: '`./int` import should occur before import of `./cello`',
+      }, {
+        ruleId: 'order',
+        message: '`./hello` import should occur before import of `./cello`',
+      }],
+    }),
   ].filter((t) => !!t),
 })

From 45f08609e0dd79f2a061c3411a43169c20e80d3a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 1 Feb 2020 23:23:04 -0800
Subject: [PATCH 109/767] Bump to v2.20.1

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4701322eeb..80912e5320 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+
+## [2.20.1] - 2020-02-01
 ### Fixed
 - [`export`]: Handle function overloading in `*.d.ts` ([#1619], thanks [@IvanGoncharov])
 - [`no-absolute-path`]: fix a crash with invalid import syntax ([#1616], thanks [@ljharb])
@@ -906,7 +908,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.0...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.1...HEAD
+[2.20.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.0...v2.20.1
 [2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.1...v2.20.0
 [2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.0...v2.19.1
 [2.19.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.2...v2.19.0
diff --git a/package.json b/package.json
index 4877320d36..841128fb6e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.20.0",
+  "version": "2.20.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 1fbef73ac4f2452c5cbdc20a13aa3b02be16a615 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 12 Feb 2020 20:53:59 -0800
Subject: [PATCH 110/767] [meta] fix changelog link

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 80912e5320..6e6e9d025e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,7 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-absolute-path`]: fix a crash with invalid import syntax ([#1616], thanks [@ljharb])
 - [`import/external-module-folders` setting] now correctly works with directories containing modules symlinked from `node_modules` ([#1605], thanks [@skozin])
 - [`extensions`]: for invalid code where `name` does not exist, do not crash ([#1613], thanks [@ljharb])
-- [`extentions`]: Fix scope regex ([#1611], thanks [@yordis])
+- [`extensions`]: Fix scope regex ([#1611], thanks [@yordis])
 - [`no-duplicates`]: allow duplicate imports if one is a namespace and the other not ([#1612], thanks [@sveyret])
 - Add some missing rule meta schemas and types ([#1620], thanks [@bmish])
 - [`named`]: for importing from a module which re-exports named exports from a `node_modules` module ([#1569], [#1447], thanks [@redbugz], [@kentcdodds])

From 2beec94604f7180836120fff044478c188be5d4d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 7 Feb 2020 19:27:19 -1000
Subject: [PATCH 111/767] [meta] use `in-publish` in `prepublish`

---
 package.json | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 841128fb6e..28e45eeb56 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
     "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && NODE_PATH=./lib mocha --compilers js:babel-register --recursive tests/src",
     "test-all": "npm test && for resolver in ./resolvers/*; do cd $resolver && npm test && cd ../..; done",
-    "prepublish": "npm run build",
+    "prepublish": "not-in-publish || npm run build",
     "coveralls": "nyc report --reporter lcovonly && cat ./coverage/lcov.info | coveralls"
   },
   "repository": {
@@ -74,6 +74,7 @@
     "eslint-module-utils": "file:./utils",
     "eslint-plugin-eslint-plugin": "^2.2.1",
     "eslint-plugin-import": "2.x",
+    "in-publish": "^2.0.0",
     "linklocal": "^2.8.2",
     "mocha": "^3.5.3",
     "nyc": "^11.9.0",

From 890500718360b96885823da6db4be8bc0388cc17 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 7 Feb 2020 10:41:19 -1000
Subject: [PATCH 112/767] [Tests] appveyor: on node 8-12, use npm 6.10.3
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Raphael von der Grün <raphinesse@gmail.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 appveyor.yml | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/appveyor.yml b/appveyor.yml
index e985479525..29e310a182 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -8,7 +8,7 @@ environment:
   # - nodejs_version: "4"
 
 matrix:
-  fast_finish: true
+  fast_finish: false
 
   # allow_failures:
   #   - nodejs_version: "4" # for eslint 5
@@ -27,6 +27,9 @@ install:
       if ($env:nodejs_version -eq "4") {
         npm install -g npm@3;
       }
+      if ($env:nodejs_version -in @("8", "10", "12")) {
+        npm install -g npm@6.10.3;
+      }
   - npm install
 
   # fix symlinks

From 47f912e74eccbb6009ea5778a7cdb33e918dd495 Mon Sep 17 00:00:00 2001
From: fisker <lionkay@gmail.com>
Date: Tue, 11 Feb 2020 17:21:16 +0800
Subject: [PATCH 113/767] [Fix] `order`: fix `isExternalModule` detection on
 windows

---
 CHANGELOG.md                 |  4 ++++
 src/core/importType.js       |  9 +++++----
 tests/src/core/importType.js | 15 ++++++++++++++-
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e6e9d025e..1966b174be 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+### Fixed
+- [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
 
 ## [2.20.1] - 2020-02-01
 ### Fixed
@@ -652,6 +654,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
 [#1625]: https://github.com/benmosher/eslint-plugin-import/pull/1625
 [#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
@@ -1105,3 +1108,4 @@ for info on changes for earlier releases.
 [@kentcdodds]: https://github.com/kentcdodds
 [@IvanGoncharov]: https://github.com/IvanGoncharov
 [@wschurman]: https://github.com/wschurman
+[@fisker]: https://github.com/fisker
diff --git a/src/core/importType.js b/src/core/importType.js
index df60575c01..49c6fb91d9 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -29,15 +29,16 @@ function isExternalPath(path, name, settings) {
 }
 
 function isSubpath(subpath, path) {
-  const normSubpath = subpath.replace(/[/]$/, '')
+  const normPath = path.replace(/\\/g, '/')
+  const normSubpath = subpath.replace(/\\/g, '/').replace(/\/$/, '')
   if (normSubpath.length === 0) {
     return false
   }
-  const left = path.indexOf(normSubpath)
+  const left = normPath.indexOf(normSubpath)
   const right = left + normSubpath.length
   return left !== -1 &&
-        (left === 0 || normSubpath[0] !== '/' && path[left - 1] === '/') &&
-        (right >= path.length || path[right] === '/')
+        (left === 0 || normSubpath[0] !== '/' && normPath[left - 1] === '/') &&
+        (right >= normPath.length || normPath[right] === '/')
 }
 
 const externalModuleRegExp = /^\w/
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 75be3101ed..b3bfb6bb62 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -1,7 +1,7 @@
 import { expect } from 'chai'
 import * as path from 'path'
 
-import importType from 'core/importType'
+import importType, {isExternalModule} from 'core/importType'
 
 import { testContext, testFilePath } from '../utils'
 
@@ -180,6 +180,12 @@ describe('importType(name)', function () {
   })
 
   it('returns "external" for a scoped module from a symlinked directory which partial path is contained in "external-module-folders" (webpack resolver)', function() {
+    const originalFoldersContext = testContext({
+      'import/resolver': 'webpack',
+      'import/external-module-folders': [],
+    })
+    expect(importType('@test-scope/some-module', originalFoldersContext)).to.equal('internal')
+
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['files/symlinked-module'],
@@ -224,4 +230,11 @@ describe('importType(name)', function () {
     })
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
   })
+
+  it('`isExternalModule` works with windows directory separator', function() {
+    expect(isExternalModule('foo', {}, 'E:\\path\\to\\node_modules\\foo')).to.equal(true)
+    expect(isExternalModule('foo', {
+      'import/external-module-folders': ['E:\\path\\to\\node_modules'],
+    }, 'E:\\path\\to\\node_modules\\foo')).to.equal(true)
+  })
 })

From 12971f5ced52ede943515fac23b81b2a8d38ba60 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Mon, 17 Feb 2020 12:46:19 +0800
Subject: [PATCH 114/767] [Fix] `order`: recognize ".." as a "parent" path

Fixes #1405.
---
 CHANGELOG.md             |  2 ++
 src/core/importType.js   |  2 +-
 tests/src/rules/order.js | 28 +++++++++++++++++++++++++++-
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1966b174be..3876057976 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 ### Fixed
 - [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
+- [`order`]: recognize ".." as a "parent" path ([#1658], thanks [@golopot])
 
 ## [2.20.1] - 2020-02-01
 ### Fixed
@@ -654,6 +655,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
 [#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
 [#1625]: https://github.com/benmosher/eslint-plugin-import/pull/1625
diff --git a/src/core/importType.js b/src/core/importType.js
index 49c6fb91d9..4d56b86d4b 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -68,7 +68,7 @@ function isInternalModule(name, settings, path) {
 }
 
 function isRelativeToParent(name) {
-  return /^\.\.[\\/]/.test(name)
+  return/^\.\.$|^\.\.[\\/]/.test(name)
 }
 
 const indexFiles = ['.', './', './index', './index.js']
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index d5a0dd98bc..c9fd4fa7a8 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -19,6 +19,7 @@ ruleTester.run('order', rule, {
         var relParent1 = require('../foo');
         var relParent2 = require('../foo/bar');
         var relParent3 = require('../');
+        var relParent4 = require('..');
         var sibling = require('./foo');
         var index = require('./');`,
       }),
@@ -196,7 +197,13 @@ ruleTester.run('order', rule, {
         import { Input } from '-/components/Input';
         import { Button } from '-/components/Button';
 
-        import { add } from './helper';`,
+        import p from '..';
+        import q from '../';
+
+        import { add } from './helper';
+
+        import i from '.';
+        import j from './';`,
       options: [
         {
           'newlines-between': 'always',
@@ -2002,6 +2009,25 @@ ruleTester.run('order', rule, {
         message: '`foo` import should occur before import of `Bar`',
       }],
     }),
+    // Alphabetize with parent paths
+    test({
+      code: `
+        import a from '../a';
+        import p from '..';
+      `,
+      output: `
+        import p from '..';
+        import a from '../a';
+      `,
+      options: [{
+        groups: ['external', 'index'],
+        alphabetize: {order: 'asc'},
+      }],
+      errors: [{
+        ruleID: 'order',
+        message: '`..` import should occur before import of `../a`',
+      }],
+    }),
     // Alphabetize with require
     test({
       code: `

From 41aaa184210a2d58115e99e57b2f7f0ce79d29b0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 18 Feb 2020 10:56:43 -0800
Subject: [PATCH 115/767] `resolvers/node`: [New] add `.node` extension

Fixes #802
---
 resolvers/node/CHANGELOG.md       |  5 ++++-
 resolvers/node/index.js           |  2 +-
 resolvers/node/test/dot-node.node |  0
 resolvers/node/test/native.node   |  0
 resolvers/node/test/paths.js      | 13 ++++++++++++-
 5 files changed, 17 insertions(+), 3 deletions(-)
 create mode 100644 resolvers/node/test/dot-node.node
 create mode 100644 resolvers/node/test/native.node

diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index f0d2358ba6..1418844082 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -4,10 +4,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## Unreleased
+### Added
+- add `.node` extension ([#1663])
 
 ## v0.3.2 - 2018-01-05
 ### Added
-- `.mjs` extension detected by default to support `experimental-modules` (#939)
+- `.mjs` extension detected by default to support `experimental-modules` ([#939])
 
 ### Deps
 - update `debug`, `resolve`
@@ -42,6 +44,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 [#438]: https://github.com/benmosher/eslint-plugin-import/pull/438
 
+[#1663]: https://github.com/benmosher/eslint-plugin-import/issues/1663
 [#939]: https://github.com/benmosher/eslint-plugin-import/issues/939
 [#531]: https://github.com/benmosher/eslint-plugin-import/issues/531
 [#437]: https://github.com/benmosher/eslint-plugin-import/issues/437
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index b5a1537bf9..bf2aab3820 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -28,7 +28,7 @@ function opts(file, config) {
   return Object.assign({
       // more closely matches Node (#333)
       // plus 'mjs' for native modules! (#939)
-      extensions: ['.mjs', '.js', '.json'],
+      extensions: ['.mjs', '.js', '.json', '.node'],
     },
     config,
     {
diff --git a/resolvers/node/test/dot-node.node b/resolvers/node/test/dot-node.node
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/resolvers/node/test/native.node b/resolvers/node/test/native.node
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/resolvers/node/test/paths.js b/resolvers/node/test/paths.js
index 2b4e7fd60f..d50366d13c 100644
--- a/resolvers/node/test/paths.js
+++ b/resolvers/node/test/paths.js
@@ -40,10 +40,21 @@ describe("default options", function () {
       .equal(path.resolve(__dirname, './native.mjs'))
   })
 
+  it("finds .node modules, with lowest precedence", function () {
+    expect(node.resolve('./native.node', './test/file.js'))
+      .to.have.property('path')
+      .equal(path.resolve(__dirname, './native.node'))
+  })
+
+  it("finds .node modules", function () {
+    expect(node.resolve('./dot-node', './test/file.js'))
+      .to.have.property('path')
+      .equal(path.resolve(__dirname, './dot-node.node'))
+  })
+
   it("still finds .js if explicit", function () {
     expect(node.resolve('./native.js', './test/file.js'))
       .to.have.property('path')
       .equal(path.resolve(__dirname, './native.js'))
   })
-
 })

From b6242b02548037223720657db4597f46b534dc87 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Fri, 21 Feb 2020 12:18:22 +0800
Subject: [PATCH 116/767] [fix] `no-duplicates`: fix fixer on cases with
 default import

---
 CHANGELOG.md                     | 2 ++
 src/rules/no-duplicates.js       | 9 +++++++--
 tests/src/rules/no-duplicates.js | 6 ++++++
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3876057976..e8fbdb5f75 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
 - [`order`]: recognize ".." as a "parent" path ([#1658], thanks [@golopot])
+- [`no-duplicates`]: fix fixer on cases with default import ([#1666], thanks [@golopot])
 
 ## [2.20.1] - 2020-02-01
 ### Fixed
@@ -655,6 +656,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
 [#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
 [#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 69e5a23a02..ce586cd674 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -136,8 +136,13 @@ function getFix(first, rest, sourceCode) {
         fixes.push(fixer.insertTextBefore(closeBrace, specifiersText))
       }
     } else if (!shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
-      // `import './foo'` → `import {...} from './foo'`
-      fixes.push(fixer.insertTextAfter(firstToken, ` {${specifiersText}} from`))
+      if (first.specifiers.length === 0) {
+        // `import './foo'` → `import {...} from './foo'`
+        fixes.push(fixer.insertTextAfter(firstToken, ` {${specifiersText}} from`))
+      } else {
+        // `import def from './foo'` → `import def, {...} from './foo'`
+        fixes.push(fixer.insertTextAfter(first.specifiers[0], `, {${specifiersText}}`))
+      }
     } else if (!shouldAddDefault && openBrace != null && closeBrace != null) {
       // `import {...} './foo'` → `import {..., ...} from './foo'`
       fixes.push(fixer.insertTextBefore(closeBrace, specifiersText))
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 468c7ab982..917d0e400e 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -168,6 +168,12 @@ ruleTester.run('no-duplicates', rule, {
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
 
+    test({
+      code: "import def from './foo'; import {x} from './foo'",
+      output: "import def, {x} from './foo'; ",
+      errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
+    }),
+
     test({
       code: "import {x} from './foo'; import def from './foo'",
       output: "import def, {x} from './foo'; ",

From adbced7cde1818f23677384868e17380b886683e Mon Sep 17 00:00:00 2001
From: Kyle Getz <kgetz@arista.com>
Date: Sat, 29 Feb 2020 16:49:48 -0800
Subject: [PATCH 117/767] utils: [New] Print more helpful info if parsing fails

If parsing fails, the only message printed to the console is vague and
mostly unhelpful. Print some information about the source of the error
to make debugging easy.
---
 utils/CHANGELOG.md | 5 +++++
 utils/parse.js     | 4 +++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 61671ba89c..0f32688b24 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Added
+[New] Print more helpful info if parsing fails ([#1671], thanks [@kaiyoma])
+
 ## v2.5.2 - 2020-01-12
 
 ### Fixed
@@ -70,6 +73,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#1671]: https://github.com/benmosher/eslint-plugin-import/pull/1671
 [#1606]: https://github.com/benmosher/eslint-plugin-import/pull/1606
 [#1602]: https://github.com/benmosher/eslint-plugin-import/pull/1602
 [#1591]: https://github.com/benmosher/eslint-plugin-import/pull/1591
@@ -94,3 +98,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@arcanis]: https://github.com/arcanis
 [@sompylasar]: https://github.com/sompylasar
 [@iamnapo]: https://github.com/iamnapo
+[@kaiyoma]: https://github.com/kaiyoma
diff --git a/utils/parse.js b/utils/parse.js
index fa2ff14259..b3a469221d 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -47,7 +47,9 @@ exports.default = function parse(path, content, context) {
     try {
       ast = parser.parseForESLint(content, parserOptions).ast
     } catch (e) {
-      //
+      console.warn()
+      console.warn('Error while parsing ' + parserOptions.filePath)
+      console.warn('Line ' + e.lineNumber + ', column ' + e.column + ': ' + e.message)
     }
     if (!ast || typeof ast !== 'object') {
       console.warn(

From efd6be15a71a39f82b610f0e24804214dc6630d2 Mon Sep 17 00:00:00 2001
From: Richard Xia <richardxia@richardxia.com>
Date: Sat, 1 Feb 2020 21:16:21 -0800
Subject: [PATCH 118/767] [Fix] `no-unused-modules`: handle `export { default }
 from` syntax

Fixes #1631
---
 CHANGELOG.md                            |  3 ++
 src/rules/no-unused-modules.js          | 53 ++++++++++++++++++++++++-
 tests/files/no-unused-modules/file-0.js |  1 +
 tests/files/no-unused-modules/file-s.js |  1 +
 tests/src/rules/no-unused-modules.js    |  9 ++++-
 5 files changed, 63 insertions(+), 4 deletions(-)
 create mode 100644 tests/files/no-unused-modules/file-s.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e8fbdb5f75..381a23ff1c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
 - [`order`]: recognize ".." as a "parent" path ([#1658], thanks [@golopot])
 - [`no-duplicates`]: fix fixer on cases with default import ([#1666], thanks [@golopot])
+- [`no-unused-modules`]: Handle `export { default } from` syntax ([#1631], thanks [@richardxia])
 
 ## [2.20.1] - 2020-02-01
 ### Fixed
@@ -660,6 +661,7 @@ for info on changes for earlier releases.
 [#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
 [#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
+[#1631]: https://github.com/benmosher/eslint-plugin-import/issues/1631
 [#1625]: https://github.com/benmosher/eslint-plugin-import/pull/1625
 [#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
 [#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
@@ -1113,3 +1115,4 @@ for info on changes for earlier releases.
 [@IvanGoncharov]: https://github.com/IvanGoncharov
 [@wschurman]: https://github.com/wschurman
 [@fisker]: https://github.com/fisker
+[@richardxia]: https://github.com/richardxia
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 44606dc857..9468dc87d0 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -66,8 +66,54 @@ const CLASS_DECLARATION = 'ClassDeclaration'
 const DEFAULT = 'default'
 const TYPE_ALIAS = 'TypeAlias'
 
+/**
+ * List of imports per file.
+ *
+ * Represented by a two-level Map to a Set of identifiers. The upper-level Map
+ * keys are the paths to the modules containing the imports, while the
+ * lower-level Map keys are the paths to the files which are being imported
+ * from. Lastly, the Set of identifiers contains either names being imported
+ * or a special AST node name listed above (e.g ImportDefaultSpecifier).
+ *
+ * For example, if we have a file named foo.js containing:
+ *
+ *   import { o2 } from './bar.js';
+ *
+ * Then we will have a structure that looks like:
+ *
+ *   Map { 'foo.js' => Map { 'bar.js' => Set { 'o2' } } }
+ *
+ * @type {Map<string, Map<string, Set<string>>>}
+ */
 const importList = new Map()
+
+/**
+ * List of exports per file.
+ *
+ * Represented by a two-level Map to an object of metadata. The upper-level Map
+ * keys are the paths to the modules containing the exports, while the
+ * lower-level Map keys are the specific identifiers or special AST node names
+ * being exported. The leaf-level metadata object at the moment only contains a
+ * `whereUsed` propoerty, which contains a Set of paths to modules that import
+ * the name.
+ *
+ * For example, if we have a file named bar.js containing the following exports:
+ *
+ *   const o2 = 'bar';
+ *   export { o2 };
+ *
+ * And a file named foo.js containing the following import:
+ *
+ *   import { o2 } from './bar.js';
+ *
+ * Then we will have a structure that looks like:
+ *
+ *   Map { 'bar.js' => Map { 'o2' => { whereUsed: Set { 'foo.js' } } } }
+ *
+ * @type {Map<string, Map<string, object>>}
+ */
 const exportList = new Map()
+
 const ignoredFiles = new Set()
 const filesOutsideSrc = new Set()
 
@@ -453,9 +499,12 @@ module.exports = {
         }
       }
 
-      const exportStatement = exports.get(exportedValue)
+      // exportsList will always map any imported value of 'default' to 'ImportDefaultSpecifier'
+      const exportsKey = exportedValue === DEFAULT ? IMPORT_DEFAULT_SPECIFIER : exportedValue
+
+      const exportStatement = exports.get(exportsKey)
 
-      const value = exportedValue === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportedValue
+      const value = exportsKey === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportsKey
 
       if (typeof exportStatement !== 'undefined'){
         if (exportStatement.whereUsed.size < 1) {
diff --git a/tests/files/no-unused-modules/file-0.js b/tests/files/no-unused-modules/file-0.js
index a5319b5fcc..6b5cc71bc1 100644
--- a/tests/files/no-unused-modules/file-0.js
+++ b/tests/files/no-unused-modules/file-0.js
@@ -11,3 +11,4 @@ import {q} from './file-q'
 export * from './file-n'
 export { default, o0, o3 } from './file-o'
 export { p } from './file-p'
+import s from './file-s'
diff --git a/tests/files/no-unused-modules/file-s.js b/tests/files/no-unused-modules/file-s.js
new file mode 100644
index 0000000000..86587470bf
--- /dev/null
+++ b/tests/files/no-unused-modules/file-s.js
@@ -0,0 +1 @@
+export { default } from './file-o'
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index cb3d4c103d..ac15fd9154 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -110,7 +110,8 @@ ruleTester.run('no-unused-modules', rule, {
            import * as l from './file-l'
            export * from './file-n'
            export { default, o0, o3 } from './file-o'
-           export { p } from './file-p'`,
+           export { p } from './file-p'
+           import s from './file-s'`,
            filename: testFilePath('./no-unused-modules/file-0.js'),
            errors: [
              error(`exported declaration 'default' not used within other modules`),
@@ -165,7 +166,11 @@ ruleTester.run('no-unused-modules', rule, {
 
 // // test for export from
 ruleTester.run('no-unused-modules', rule, {
-  valid: [],
+  valid: [
+    test({ options: unusedExportsOptions,
+           code: `export { default } from './file-o'`,
+           filename: testFilePath('./no-unused-modules/file-s.js')}),
+  ],
   invalid: [
     test({ options: unusedExportsOptions,
            code: `export { k } from '${testFilePath('./no-unused-modules/file-k.js')}'`,

From 1a3a12869651bec54d567af8dc0e7cb2a801d41f Mon Sep 17 00:00:00 2001
From: TheCrueltySage <miltenfiremage@gmail.com>
Date: Wed, 19 Feb 2020 17:39:15 +0700
Subject: [PATCH 119/767] [Fix] `first`: Add a way to disable `absolute-first`
 explicitly

---
 CHANGELOG.md             | 3 +++
 src/rules/first.js       | 2 +-
 tests/src/rules/first.js | 3 +++
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 381a23ff1c..e5e0fab9b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]: recognize ".." as a "parent" path ([#1658], thanks [@golopot])
 - [`no-duplicates`]: fix fixer on cases with default import ([#1666], thanks [@golopot])
 - [`no-unused-modules`]: Handle `export { default } from` syntax ([#1631], thanks [@richardxia])
+- [`first`]: Add a way to disable `absolute-first` explicitly ([#1664], thanks [@TheCrueltySage])
 
 ## [2.20.1] - 2020-02-01
 ### Fixed
@@ -658,6 +659,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
+[#1664]: https://github.com/benmosher/eslint-plugin-import/pull/1664
 [#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
 [#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
@@ -1116,3 +1118,4 @@ for info on changes for earlier releases.
 [@wschurman]: https://github.com/wschurman
 [@fisker]: https://github.com/fisker
 [@richardxia]: https://github.com/richardxia
+[@TheCrueltySage]: https://github.com/TheCrueltySage
diff --git a/src/rules/first.js b/src/rules/first.js
index 393cadb1fa..c1422cdb0b 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -10,7 +10,7 @@ module.exports = {
     schema: [
       {
         type: 'string',
-        enum: ['absolute-first'],
+        enum: ['absolute-first', 'disable-absolute-first'],
       },
     ],
   },
diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index 55367cf43c..8c5d72a34c 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -11,6 +11,9 @@ ruleTester.run('first', rule, {
                   export { x, y }" })
   , test({ code: "import { x } from 'foo'; import { y } from './bar'" })
   , test({ code: "import { x } from './foo'; import { y } from 'bar'" })
+  , test({ code: "import { x } from './foo'; import { y } from 'bar'"
+         , options: ['disable-absolute-first'],
+         })
   , test({ code: "'use directive';\
                   import { x } from 'foo';" })
   ,

From efb5f07d716e4577600fd234da495d1e686738de Mon Sep 17 00:00:00 2001
From: Alexandre Djerbetian <alexandre.djerbetian@360learning.com>
Date: Sat, 14 Mar 2020 20:12:27 +0100
Subject: [PATCH 120/767] [Tests] use babel instead of NODE_PATH

---
 .babelrc             | 10 +++++++++-
 package.json         |  9 +++++----
 test/mocha.opts      |  3 +++
 tests/src/package.js |  9 ++++++++-
 4 files changed, 25 insertions(+), 6 deletions(-)
 create mode 100644 test/mocha.opts

diff --git a/.babelrc b/.babelrc
index c2f08fdc2c..2cbf5c811c 100644
--- a/.babelrc
+++ b/.babelrc
@@ -3,7 +3,15 @@
   "sourceMaps": "inline",
   "env": {
     "test": {
-      "plugins": [ "istanbul" ]
+      "plugins": [
+        "istanbul",
+        [ "module-resolver", { "root": [ "./src/" ] } ]
+      ]
+    },
+    "testCompiled": {
+      "plugins": [
+        [ "module-resolver", { "root": [ "./lib/" ] } ]
+      ]
     }
   }
 }
diff --git a/package.json b/package.json
index 28e45eeb56..d820b829c3 100644
--- a/package.json
+++ b/package.json
@@ -22,13 +22,13 @@
     "build": "babel --quiet --out-dir lib src",
     "postbuild": "npm run copy-metafiles",
     "copy-metafiles": "for DIR in memo-parser resolvers/node resolvers/webpack utils; do cp LICENSE .npmrc \"${DIR}/\"; done",
-    "watch": "npm run mocha -- --watch tests/src",
+    "watch": "npm run tests-only -- -- --watch",
     "pretest": "linklocal",
     "posttest": "eslint .",
-    "mocha": "cross-env BABEL_ENV=test NODE_PATH=./src nyc -s mocha -R dot --recursive -t 5s",
-    "tests-only": "npm run mocha tests/src",
+    "mocha": "nyc -s mocha",
+    "tests-only": "cross-env BABEL_ENV=test npm run mocha tests/src",
     "test": "npm run tests-only",
-    "test-compiled": "npm run prepublish && NODE_PATH=./lib mocha --compilers js:babel-register --recursive tests/src",
+    "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
     "test-all": "npm test && for resolver in ./resolvers/*; do cd $resolver && npm test && cd ../..; done",
     "prepublish": "not-in-publish || npm run build",
     "coveralls": "nyc report --reporter lcovonly && cat ./coverage/lcov.info | coveralls"
@@ -60,6 +60,7 @@
     "babel-core": "^6.26.3",
     "babel-eslint": "^8.2.6",
     "babel-plugin-istanbul": "^4.1.6",
+    "babel-plugin-module-resolver": "^2.7.1",
     "babel-preset-es2015-argon": "latest",
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
diff --git a/test/mocha.opts b/test/mocha.opts
new file mode 100644
index 0000000000..0be6eb2fd6
--- /dev/null
+++ b/test/mocha.opts
@@ -0,0 +1,3 @@
+--reporter=dot
+--recursive
+-t 5s
diff --git a/tests/src/package.js b/tests/src/package.js
index 9f66c6607f..700d4121b4 100644
--- a/tests/src/package.js
+++ b/tests/src/package.js
@@ -51,10 +51,17 @@ describe('package', function () {
       let preamble = 'import/'
 
       for (let rule in module.configs[configFile].rules) {
-        expect(() => require('rules/'+rule.slice(preamble.length)))
+        expect(() => require(getRulePath(rule.slice(preamble.length))))
           .not.to.throw(Error)
       }
     }
+
+    function getRulePath(ruleName) {
+      // 'require' does not work with dynamic paths because of the compilation step by babel
+      // (which resolves paths according to the root folder configuration)
+      // the usage of require.resolve on a static path gets around this
+      return path.resolve(require.resolve('rules/no-unresolved'), '..', ruleName)
+    }
   })
 
   it('marks deprecated rules in their metadata', function () {

From 9c5899e8af3c1a44e1087a83e409e54560f3bd67 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 28 Mar 2020 14:56:52 -0700
Subject: [PATCH 121/767] utils: v2.6.0

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 0f32688b24..f337d3850a 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v2.6.0 - 2020-03-28
+
 ### Added
 [New] Print more helpful info if parsing fails ([#1671], thanks [@kaiyoma])
 
diff --git a/utils/package.json b/utils/package.json
index b8d4033e66..6e8ebddfb9 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.5.2",
+  "version": "2.6.0",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From a618f88ffeb345ce6785eae02971b687339d8f23 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 28 Mar 2020 16:11:50 -0700
Subject: [PATCH 122/767] [Tests] pin esquery, due to breaking change in a
 minor version

See https://github.com/estools/esquery/issues/95
---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index d820b829c3..333ff468d9 100644
--- a/package.json
+++ b/package.json
@@ -75,6 +75,7 @@
     "eslint-module-utils": "file:./utils",
     "eslint-plugin-eslint-plugin": "^2.2.1",
     "eslint-plugin-import": "2.x",
+    "esquery": "~1.1.0",
     "in-publish": "^2.0.0",
     "linklocal": "^2.8.2",
     "mocha": "^3.5.3",

From 71ca88f0a1e7e1270f1c1f9633d3ae8f136f58e1 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 28 Mar 2020 15:00:47 -0700
Subject: [PATCH 123/767] Bump to v2.20.2

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5e0fab9b4..4b76324d4b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+
+## [2.20.2] - 2020-03-28
 ### Fixed
 - [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
 - [`order`]: recognize ".." as a "parent" path ([#1658], thanks [@golopot])
@@ -919,7 +921,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.1...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.2...HEAD
+[2.20.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.1...v2.20.2
 [2.20.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.0...v2.20.1
 [2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.1...v2.20.0
 [2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.0...v2.19.1
diff --git a/package.json b/package.json
index 333ff468d9..aa637e2024 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.20.1",
+  "version": "2.20.2",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 2b50d16d1491cbeff3ee9566c369468bbe886765 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Thu, 2 Apr 2020 00:46:02 +0800
Subject: [PATCH 124/767] [Tests] Add eslint@7 prereleases to CI

---
 .travis.yml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index a6824a6c5c..929bca0852 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,7 @@ node_js:
 os: linux
 
 env:
+  - ESLINT_VERSION=^7.0.0-0
   - ESLINT_VERSION=6
   - ESLINT_VERSION=5
   - ESLINT_VERSION=4
@@ -65,8 +66,14 @@ matrix:
     env: ESLINT_VERSION=5
   - node_js: '4'
     env: ESLINT_VERSION=6
+  - node_js: '4'
+    env: ESLINT_VERSION=^7.0.0-0
   - node_js: '6'
     env: ESLINT_VERSION=6
+  - node_js: '6'
+    env: ESLINT_VERSION=^7.0.0-0
+  - node_js: '8'
+    env: ESLINT_VERSION=^7.0.0-0
 
   fast_finish: true
   allow_failures:

From 3adb3f9877b6c56188f03b0a7823e6acd19f15fc Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Thu, 2 Apr 2020 00:22:19 +0800
Subject: [PATCH 125/767] [Tests] remove useless property "ruleId" in test
 cases

---
 tests/src/rules/exports-last.js               |  1 -
 tests/src/rules/no-absolute-path.js           |  1 -
 tests/src/rules/no-cycle.js                   |  2 +-
 tests/src/rules/no-default-export.js          |  8 +--
 tests/src/rules/no-dynamic-require.js         |  1 -
 tests/src/rules/no-extraneous-dependencies.js | 24 --------
 tests/src/rules/no-named-export.js            | 40 ++++++-------
 tests/src/rules/no-nodejs-modules.js          |  1 -
 tests/src/rules/no-self-import.js             |  1 -
 tests/src/rules/no-unassigned-import.js       |  1 -
 tests/src/rules/no-unused-modules.js          |  2 +-
 tests/src/rules/order.js                      | 57 -------------------
 tests/src/rules/prefer-default-export.js      | 12 ++--
 13 files changed, 32 insertions(+), 119 deletions(-)

diff --git a/tests/src/rules/exports-last.js b/tests/src/rules/exports-last.js
index 770e123d31..cc853ba76c 100644
--- a/tests/src/rules/exports-last.js
+++ b/tests/src/rules/exports-last.js
@@ -6,7 +6,6 @@ import rule from 'rules/exports-last'
 const ruleTester = new RuleTester()
 
 const error = type => ({
-  ruleId: 'exports-last',
   message: 'Export statements should appear at the end of the file',
   type,
 })
diff --git a/tests/src/rules/no-absolute-path.js b/tests/src/rules/no-absolute-path.js
index 8689997b45..2a95829b00 100644
--- a/tests/src/rules/no-absolute-path.js
+++ b/tests/src/rules/no-absolute-path.js
@@ -6,7 +6,6 @@ const ruleTester = new RuleTester()
     , rule = require('rules/no-absolute-path')
 
 const error = {
-  ruleId: 'no-absolute-path',
   message: 'Do not import modules using an absolute path',
 }
 
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index df1e6d1433..5d6cfc6618 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -5,7 +5,7 @@ import { RuleTester } from 'eslint'
 const ruleTester = new RuleTester()
     , rule = require('rules/no-cycle')
 
-const error = message => ({ ruleId: 'no-cycle', message })
+const error = message => ({ message })
 
 const test = def => _test(Object.assign(def, {
   filename: testFilePath('./cycles/depth-zero.js'),
diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index dd71c167ea..d11b7d3b11 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -89,7 +89,7 @@ ruleTester.run('no-default-export', rule, {
     test({
       code: 'export default function bar() {};',
       errors: [{
-        ruleId: 'ExportDefaultDeclaration',
+        type: 'ExportDefaultDeclaration',
         message: 'Prefer named exports.',
       }],
     }),
@@ -98,14 +98,14 @@ ruleTester.run('no-default-export', rule, {
         export const foo = 'foo';
         export default bar;`,
       errors: [{
-        ruleId: 'ExportDefaultDeclaration',
+        type: 'ExportDefaultDeclaration',
         message: 'Prefer named exports.',
       }],
     }),
     test({
       code: 'let foo; export { foo as default }',
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Do not alias `foo` as `default`. Just export `foo` itself ' +
           'instead.',
       }],
@@ -114,7 +114,7 @@ ruleTester.run('no-default-export', rule, {
       code: 'export default from "foo.js"',
       parser: require.resolve('babel-eslint'),
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Prefer named exports.',
       }],
     }),
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index 8793d0dd8e..5846032004 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -6,7 +6,6 @@ const ruleTester = new RuleTester()
     , rule = require('rules/no-dynamic-require')
 
 const error = {
-  ruleId: 'no-dynamic-require',
   message: 'Calls to require() should use string literals',
 }
 
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index e70a601746..a9540e51ee 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -126,7 +126,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       filename: path.join(packageDirMonoRepoRoot, 'foo.js'),
       options: [{packageDir: packageDirMonoRepoRoot }],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
@@ -135,7 +134,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       filename: path.join(packageDirMonoRepoWithNested, 'foo.js'),
       options: [{packageDir: packageDirMonoRepoRoot}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
@@ -143,28 +141,24 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import "not-a-dependency"',
       options: [{packageDir: packageDirMonoRepoRoot}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
     test({
       code: 'import "not-a-dependency"',
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
     test({
       code: 'var donthaveit = require("@org/not-a-dependency")',
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'@org/not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S @org/not-a-dependency\' to add it',
       }],
     }),
     test({
       code: 'var donthaveit = require("@org/not-a-dependency/foo")',
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'@org/not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S @org/not-a-dependency\' to add it',
       }],
     }),
@@ -172,7 +166,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import "eslint"',
       options: [{devDependencies: false, peerDependencies: false}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'eslint\' should be listed in the project\'s dependencies, not devDependencies.',
       }],
     }),
@@ -180,14 +173,12 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import "lodash.isarray"',
       options: [{optionalDependencies: false}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'lodash.isarray\' should be listed in the project\'s dependencies, not optionalDependencies.',
       }],
     }),
     test({
       code: 'var foo = require("not-a-dependency")',
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
@@ -195,7 +186,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'var glob = require("glob")',
       options: [{devDependencies: false}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'glob\' should be listed in the project\'s dependencies, not devDependencies.',
       }],
     }),
@@ -204,7 +194,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       options: [{devDependencies: ['*.test.js']}],
       filename: 'foo.tes.js',
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'chai\' should be listed in the project\'s dependencies, not devDependencies.',
       }],
     }),
@@ -213,7 +202,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       options: [{devDependencies: ['*.test.js']}],
       filename: path.join(process.cwd(), 'foo.tes.js'),
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'chai\' should be listed in the project\'s dependencies, not devDependencies.',
       }],
     }),
@@ -222,7 +210,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       options: [{devDependencies: ['*.test.js', '*.spec.js']}],
       filename: 'foo.tes.js',
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'chai\' should be listed in the project\'s dependencies, not devDependencies.',
       }],
     }),
@@ -231,7 +218,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       options: [{devDependencies: ['*.test.js', '*.spec.js']}],
       filename: path.join(process.cwd(), 'foo.tes.js'),
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'chai\' should be listed in the project\'s dependencies, not devDependencies.',
       }],
     }),
@@ -239,7 +225,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'var eslint = require("lodash.isarray")',
       options: [{optionalDependencies: false}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'lodash.isarray\' should be listed in the project\'s dependencies, not optionalDependencies.',
       }],
     }),
@@ -247,7 +232,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import "not-a-dependency"',
       options: [{packageDir: path.join(__dirname, '../../../')}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
@@ -255,7 +239,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import "bar"',
       options: [{packageDir: path.join(__dirname, './doesn-exist/')}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: 'The package.json file could not be found.',
       }],
     }),
@@ -263,7 +246,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import foo from "foo"',
       options: [{packageDir: packageDirWithSyntaxError}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: 'The package.json file could not be parsed: ' + packageFileWithSyntaxErrorMessage,
       }],
     }),
@@ -272,7 +254,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       filename: path.join(packageDirMonoRepoWithNested, 'foo.js'),
       options: [{packageDir: packageDirMonoRepoWithNested}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: "'left-pad' should be listed in the project's dependencies. Run 'npm i -S left-pad' to add it",
       }],
     }),
@@ -280,7 +261,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import react from "react";',
       filename: path.join(packageDirMonoRepoRoot, 'foo.js'),
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: "'react' should be listed in the project's dependencies. Run 'npm i -S react' to add it",
       }],
     }),
@@ -289,7 +269,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       filename: path.join(packageDirMonoRepoWithNested, 'foo.js'),
       options: [{packageDir: packageDirMonoRepoRoot}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: "'react' should be listed in the project's dependencies. Run 'npm i -S react' to add it",
       }],
     }),
@@ -298,7 +277,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       filename: path.join(packageDirWithEmpty, 'index.js'),
       options: [{packageDir: packageDirWithEmpty}],
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: "'react' should be listed in the project's dependencies. Run 'npm i -S react' to add it",
       }],
     }),
@@ -319,14 +297,12 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'export { foo } from "not-a-dependency";',
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
     test({
       code: 'export * from "not-a-dependency";',
       errors: [{
-        ruleId: 'no-extraneous-dependencies',
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
diff --git a/tests/src/rules/no-named-export.js b/tests/src/rules/no-named-export.js
index c4ef9c9c7f..bde92b9e41 100644
--- a/tests/src/rules/no-named-export.js
+++ b/tests/src/rules/no-named-export.js
@@ -35,10 +35,10 @@ ruleTester.run('no-named-export', rule, {
         export const bar = 'bar';
       `,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }, {
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
@@ -47,7 +47,7 @@ ruleTester.run('no-named-export', rule, {
         export const foo = 'foo';
         export default bar;`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
@@ -57,17 +57,17 @@ ruleTester.run('no-named-export', rule, {
         export function bar() {};
       `,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }, {
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
     test({
       code: `export const foo = 'foo';`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
@@ -77,35 +77,35 @@ ruleTester.run('no-named-export', rule, {
         export { foo };
       `,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
     test({
       code: `let foo, bar; export { foo, bar }`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
     test({
       code: `export const { foo, bar } = item;`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
     test({
       code: `export const { foo, bar: baz } = item;`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
     test({
       code: `export const { foo: { bar, baz } } = item;`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
@@ -116,31 +116,31 @@ ruleTester.run('no-named-export', rule, {
         export { item };
       `,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }, {
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
     test({
       code: `export * from './foo';`,
       errors: [{
-        ruleId: 'ExportAllDeclaration',
+        type: 'ExportAllDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
     test({
       code: `export const { foo } = { foo: "bar" };`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
     test({
       code: `export const { foo: { bar } } = { foo: { bar: "baz" } };`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
@@ -148,7 +148,7 @@ ruleTester.run('no-named-export', rule, {
       code: 'export { a, b } from "foo.js"',
       parser: require.resolve('babel-eslint'),
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
@@ -156,7 +156,7 @@ ruleTester.run('no-named-export', rule, {
       code: `export type UserId = number;`,
       parser: require.resolve('babel-eslint'),
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
@@ -164,7 +164,7 @@ ruleTester.run('no-named-export', rule, {
       code: 'export foo from "foo.js"',
       parser: require.resolve('babel-eslint'),
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
@@ -172,7 +172,7 @@ ruleTester.run('no-named-export', rule, {
       code: `export Memory, { MemoryValue } from './Memory'`,
       parser: require.resolve('babel-eslint'),
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
       }],
     }),
diff --git a/tests/src/rules/no-nodejs-modules.js b/tests/src/rules/no-nodejs-modules.js
index b5e55fafc2..4be050c63f 100644
--- a/tests/src/rules/no-nodejs-modules.js
+++ b/tests/src/rules/no-nodejs-modules.js
@@ -6,7 +6,6 @@ const ruleTester = new RuleTester()
     , rule = require('rules/no-nodejs-modules')
 
 const error = message => ({
-  ruleId: 'no-nodejs-modules',
   message,
 })
 
diff --git a/tests/src/rules/no-self-import.js b/tests/src/rules/no-self-import.js
index f8549b49ed..281d67107f 100644
--- a/tests/src/rules/no-self-import.js
+++ b/tests/src/rules/no-self-import.js
@@ -6,7 +6,6 @@ const ruleTester = new RuleTester()
     , rule = require('rules/no-self-import')
 
 const error = {
-  ruleId: 'no-self-import',
   message: 'Module imports itself.',
 }
 
diff --git a/tests/src/rules/no-unassigned-import.js b/tests/src/rules/no-unassigned-import.js
index 414bfca90f..d4fca8f457 100644
--- a/tests/src/rules/no-unassigned-import.js
+++ b/tests/src/rules/no-unassigned-import.js
@@ -7,7 +7,6 @@ const ruleTester = new RuleTester()
     , rule = require('rules/no-unassigned-import')
 
 const error = {
-  ruleId: 'no-unassigned-import',
   message: 'Imported module should be assigned',
 }
 
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index ac15fd9154..d1a7f62fd3 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -10,7 +10,7 @@ const ruleTester = new RuleTester()
     , jsxRuleTester = new RuleTester(jsxConfig)
     , rule = require('rules/no-unused-modules')
 
-const error = message => ({ ruleId: 'no-unused-modules', message })
+const error = message => ({ message })
 
 const missingExportsOptions = [{
   missingExports: true,
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index c9fd4fa7a8..83e459cea9 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -681,7 +681,6 @@ ruleTester.run('order', rule, {
         var async = require('async');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -696,7 +695,6 @@ ruleTester.run('order', rule, {
         var async = require('async');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -711,7 +709,6 @@ ruleTester.run('order', rule, {
         var async = require('async');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -726,7 +723,6 @@ ruleTester.run('order', rule, {
         /* comment1 */  var async = require('async'); /* comment2 */
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -741,7 +737,6 @@ ruleTester.run('order', rule, {
         /* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -756,7 +751,6 @@ ruleTester.run('order', rule, {
         `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n`
       ,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -776,7 +770,6 @@ ruleTester.run('order', rule, {
           comment3 */
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -791,7 +784,6 @@ ruleTester.run('order', rule, {
         var {b} = require('async');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -808,7 +800,6 @@ ruleTester.run('order', rule, {
         var async = require('async');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -821,7 +812,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
         var async = require('async');` + '\n',
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -836,7 +826,6 @@ ruleTester.run('order', rule, {
         import async from 'async';
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -851,7 +840,6 @@ ruleTester.run('order', rule, {
         var async = require('async');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     }),
@@ -866,7 +854,6 @@ ruleTester.run('order', rule, {
         var parent = require('../parent');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`async` import should occur before import of `../parent`',
       }],
     }),
@@ -881,7 +868,6 @@ ruleTester.run('order', rule, {
         var sibling = require('./sibling');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`../parent` import should occur before import of `./sibling`',
       }],
     }),
@@ -896,7 +882,6 @@ ruleTester.run('order', rule, {
         var index = require('./');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`./sibling` import should occur before import of `./`',
       }],
     }),
@@ -908,10 +893,8 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`async` import should occur before import of `./sibling`',
       }, {
-        ruleId: 'order',
         message: '`fs` import should occur before import of `./sibling`',
       }],
     }),
@@ -934,7 +917,6 @@ ruleTester.run('order', rule, {
         var index = require('./');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`./` import should occur after import of `bar`',
       }],
     }),
@@ -950,7 +932,6 @@ ruleTester.run('order', rule, {
       `,
       options: [{groups: ['index', 'sibling', 'parent', 'external', 'builtin']}],
       errors: [{
-        ruleId: 'order',
         message: '`./` import should occur before import of `fs`',
       }],
     }),
@@ -961,7 +942,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `./foo`',
       }],
     })),
@@ -972,7 +952,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `./foo`',
       }],
     })),
@@ -985,7 +964,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `./foo`',
       }],
     })),
@@ -998,7 +976,6 @@ ruleTester.run('order', rule, {
           .bar;
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `./foo`',
       }],
     })),
@@ -1021,7 +998,6 @@ ruleTester.run('order', rule, {
         ['sibling', 'parent', 'external'],
       ]}],
       errors: [{
-        ruleId: 'order',
         message: '`path` import should occur before import of `./foo`',
       }],
     }),
@@ -1041,7 +1017,6 @@ ruleTester.run('order', rule, {
         // missing 'builtin'
       ]}],
       errors: [{
-        ruleId: 'order',
         message: '`async` import should occur before import of `path`',
       }],
     }),
@@ -1057,7 +1032,6 @@ ruleTester.run('order', rule, {
         ['sibling', 'parent', 'UNKNOWN', 'internal'],
       ]}],
       errors: [{
-        ruleId: 'order',
         message: 'Incorrect configuration of the rule: Unknown type `"UNKNOWN"`',
       }],
     }),
@@ -1072,7 +1046,6 @@ ruleTester.run('order', rule, {
         ['sibling', 'parent', ['builtin'], 'internal'],
       ]}],
       errors: [{
-        ruleId: 'order',
         message: 'Incorrect configuration of the rule: Unknown type `["builtin"]`',
       }],
     }),
@@ -1087,7 +1060,6 @@ ruleTester.run('order', rule, {
         ['sibling', 'parent', 2, 'internal'],
       ]}],
       errors: [{
-        ruleId: 'order',
         message: 'Incorrect configuration of the rule: Unknown type `2`',
       }],
     }),
@@ -1102,7 +1074,6 @@ ruleTester.run('order', rule, {
         ['sibling', 'parent', 'parent', 'internal'],
       ]}],
       errors: [{
-        ruleId: 'order',
         message: 'Incorrect configuration of the rule: `parent` is duplicated',
       }],
     }),
@@ -1127,7 +1098,6 @@ ruleTester.run('order', rule, {
         var index = require('./');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`./foo` import should occur before import of `fs`',
       }],
     }),
@@ -1143,7 +1113,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur after import of `../foo/bar`',
       }],
     }),
@@ -1510,7 +1479,6 @@ ruleTester.run('order', rule, {
         fn_call();
       `,
       errors: [{
-        ruleId: 'order',
         message: '`./local` import should occur after import of `global2`',
       }],
     }),
@@ -1533,7 +1501,6 @@ ruleTester.run('order', rule, {
         fn_call();
       `,
       errors: [{
-        ruleId: 'order',
         message: '`./local` import should occur after import of `global2`',
       }],
     }),
@@ -1584,7 +1551,6 @@ ruleTester.run('order', rule, {
         fn_call();
       `,
       errors: [{
-        ruleId: 'order',
         message: '`./local` import should occur after import of `global3`',
       }],
     })),
@@ -1639,7 +1605,6 @@ ruleTester.run('order', rule, {
         ],
       }],
       errors: [{
-        ruleId: 'order',
         message: '`~/components/Input` import should occur before import of `./helper`',
       }],
     }),
@@ -1665,7 +1630,6 @@ ruleTester.run('order', rule, {
         ],
       }],
       errors: [{
-        ruleId: 'order',
         message: '`./helper` import should occur after import of `async`',
       }],
     }),
@@ -1689,7 +1653,6 @@ ruleTester.run('order', rule, {
         ],
       }],
       errors: [{
-        ruleId: 'order',
         message: '`~/components/Input` import should occur before import of `lodash`',
       }],
     }),
@@ -1723,7 +1686,6 @@ ruleTester.run('order', rule, {
       }],
       errors: [
         {
-          ruleId: 'order',
           message: '`-/components/Export` import should occur before import of `$/components/Import`',
         },
       ],
@@ -1759,7 +1721,6 @@ ruleTester.run('order', rule, {
       }],
       errors: [
         {
-          ruleId: 'order',
           message: '`~/components/Output` import should occur before import of `#/components/Input`',
         },
       ],
@@ -1773,7 +1734,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1800,7 +1760,6 @@ ruleTester.run('order', rule, {
         http.createServer(express());
       `,
       errors: [{
-        ruleId: 'order',
         message: '`./config` import should occur after import of `express`',
       }],
     }),
@@ -1812,7 +1771,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1823,7 +1781,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs')(a);
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1834,7 +1791,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1846,7 +1802,6 @@ ruleTester.run('order', rule, {
         var fs = require('fs');
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1858,7 +1813,6 @@ ruleTester.run('order', rule, {
         import fs from 'fs';
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1870,7 +1824,6 @@ ruleTester.run('order', rule, {
         import fs from 'fs';
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1882,7 +1835,6 @@ ruleTester.run('order', rule, {
         import fs from 'fs';
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1894,7 +1846,6 @@ ruleTester.run('order', rule, {
         import fs from 'fs';
       `,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1909,7 +1860,6 @@ ruleTester.run('order', rule, {
       `,
       parser,
       errors: [{
-        ruleId: 'order',
         message: '`fs` import should occur before import of `async`',
       }],
     })),
@@ -1934,7 +1884,6 @@ ruleTester.run('order', rule, {
         alphabetize: {order: 'asc'},
       }],
       errors: [{
-        ruleID: 'order',
         message: '`Bar` import should occur before import of `bar`',
       }],
     }),
@@ -1959,7 +1908,6 @@ ruleTester.run('order', rule, {
         alphabetize: {order: 'desc'},
       }],
       errors: [{
-        ruleID: 'order',
         message: '`bar` import should occur before import of `Bar`',
       }],
     }),
@@ -1982,7 +1930,6 @@ ruleTester.run('order', rule, {
         alphabetize: {order: 'asc', caseInsensitive: true},
       }],
       errors: [{
-        ruleID: 'order',
         message: '`Bar` import should occur before import of `foo`',
       }],
     }),
@@ -2005,7 +1952,6 @@ ruleTester.run('order', rule, {
         alphabetize: {order: 'desc', caseInsensitive: true},
       }],
       errors: [{
-        ruleID: 'order',
         message: '`foo` import should occur before import of `Bar`',
       }],
     }),
@@ -2024,7 +1970,6 @@ ruleTester.run('order', rule, {
         alphabetize: {order: 'asc'},
       }],
       errors: [{
-        ruleID: 'order',
         message: '`..` import should occur before import of `../a`',
       }],
     }),
@@ -2037,10 +1982,8 @@ ruleTester.run('order', rule, {
         import { hello } from './hello';
       `,
       errors: [{
-        ruleId: 'order',
         message: '`./int` import should occur before import of `./cello`',
       }, {
-        ruleId: 'order',
         message: '`./hello` import should occur before import of `./cello`',
       }],
     }),
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 19aef41e0b..9e38cea926 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -94,7 +94,7 @@ ruleTester.run('prefer-default-export', rule, {
       code: `
         export function bar() {};`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Prefer default export.',
       }],
     }),
@@ -102,7 +102,7 @@ ruleTester.run('prefer-default-export', rule, {
       code: `
         export const foo = 'foo';`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Prefer default export.',
       }],
     }),
@@ -111,7 +111,7 @@ ruleTester.run('prefer-default-export', rule, {
         const foo = 'foo';
         export { foo };`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportSpecifier',
         message: 'Prefer default export.',
       }],
     }),
@@ -119,7 +119,7 @@ ruleTester.run('prefer-default-export', rule, {
       code: `
         export const { foo } = { foo: "bar" };`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Prefer default export.',
       }],
     }),
@@ -127,7 +127,7 @@ ruleTester.run('prefer-default-export', rule, {
       code: `
         export const { foo: { bar } } = { foo: { bar: "baz" } };`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Prefer default export.',
       }],
     }),
@@ -135,7 +135,7 @@ ruleTester.run('prefer-default-export', rule, {
       code: `
         export const [a] = ["foo"]`,
       errors: [{
-        ruleId: 'ExportNamedDeclaration',
+        type: 'ExportNamedDeclaration',
         message: 'Prefer default export.',
       }],
     }),

From a86ba0603ea25395988943575718ba2d4133c4e4 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Thu, 2 Apr 2020 11:30:42 +0800
Subject: [PATCH 126/767] [Tests] add missing outputs in test cases

---
 tests/src/rules/no-useless-path-segments.js | 35 +++++++++++
 tests/src/rules/order.js                    | 67 +++++++++++++--------
 2 files changed, 77 insertions(+), 25 deletions(-)

diff --git a/tests/src/rules/no-useless-path-segments.js b/tests/src/rules/no-useless-path-segments.js
index 366e753541..2a864d0b6c 100644
--- a/tests/src/rules/no-useless-path-segments.js
+++ b/tests/src/rules/no-useless-path-segments.js
@@ -40,41 +40,49 @@ function runResolverTests(resolver) {
       // CommonJS modules
       test({
         code: 'require("./../files/malformed.js")',
+        output: 'require("../files/malformed.js")',
         options: [{ commonjs: true }],
         errors: [ 'Useless path segments for "./../files/malformed.js", should be "../files/malformed.js"'],
       }),
       test({
         code: 'require("./../files/malformed")',
+        output: 'require("../files/malformed")',
         options: [{ commonjs: true }],
         errors: [ 'Useless path segments for "./../files/malformed", should be "../files/malformed"'],
       }),
       test({
         code: 'require("../files/malformed.js")',
+        output: 'require("./malformed.js")',
         options: [{ commonjs: true }],
         errors: [ 'Useless path segments for "../files/malformed.js", should be "./malformed.js"'],
       }),
       test({
         code: 'require("../files/malformed")',
+        output: 'require("./malformed")',
         options: [{ commonjs: true }],
         errors: [ 'Useless path segments for "../files/malformed", should be "./malformed"'],
       }),
       test({
         code: 'require("./test-module/")',
+        output: 'require("./test-module")',
         options: [{ commonjs: true }],
         errors: [ 'Useless path segments for "./test-module/", should be "./test-module"'],
       }),
       test({
         code: 'require("./")',
+        output: 'require(".")',
         options: [{ commonjs: true }],
         errors: [ 'Useless path segments for "./", should be "."'],
       }),
       test({
         code: 'require("../")',
+        output: 'require("..")',
         options: [{ commonjs: true }],
         errors: [ 'Useless path segments for "../", should be ".."'],
       }),
       test({
         code: 'require("./deep//a")',
+        output: 'require("./deep/a")',
         options: [{ commonjs: true }],
         errors: [ 'Useless path segments for "./deep//a", should be "./deep/a"'],
       }),
@@ -82,41 +90,49 @@ function runResolverTests(resolver) {
       // CommonJS modules + noUselessIndex
       test({
         code: 'require("./bar/index.js")',
+        output: 'require("./bar/")',
         options: [{ commonjs: true, noUselessIndex: true }],
         errors: ['Useless path segments for "./bar/index.js", should be "./bar/"'], // ./bar.js exists
       }),
       test({
         code: 'require("./bar/index")',
+        output: 'require("./bar/")',
         options: [{ commonjs: true, noUselessIndex: true }],
         errors: ['Useless path segments for "./bar/index", should be "./bar/"'], // ./bar.js exists
       }),
       test({
         code: 'require("./importPath/")',
+        output: 'require("./importPath")',
         options: [{ commonjs: true, noUselessIndex: true }],
         errors: ['Useless path segments for "./importPath/", should be "./importPath"'], // ./importPath.js does not exist
       }),
       test({
         code: 'require("./importPath/index.js")',
+        output: 'require("./importPath")',
         options: [{ commonjs: true, noUselessIndex: true }],
         errors: ['Useless path segments for "./importPath/index.js", should be "./importPath"'], // ./importPath.js does not exist
       }),
       test({
         code: 'require("./importType/index")',
+        output: 'require("./importType")',
         options: [{ commonjs: true, noUselessIndex: true }],
         errors: ['Useless path segments for "./importType/index", should be "./importType"'], // ./importPath.js does not exist
       }),
       test({
         code: 'require("./index")',
+        output: 'require(".")',
         options: [{ commonjs: true, noUselessIndex: true }],
         errors: ['Useless path segments for "./index", should be "."'],
       }),
       test({
         code: 'require("../index")',
+        output: 'require("..")',
         options: [{ commonjs: true, noUselessIndex: true }],
         errors: ['Useless path segments for "../index", should be ".."'],
       }),
       test({
         code: 'require("../index.js")',
+        output: 'require("..")',
         options: [{ commonjs: true, noUselessIndex: true }],
         errors: ['Useless path segments for "../index.js", should be ".."'],
       }),
@@ -124,90 +140,109 @@ function runResolverTests(resolver) {
       // ES modules
       test({
         code: 'import "./../files/malformed.js"',
+        output: 'import "../files/malformed.js"',
         errors: [ 'Useless path segments for "./../files/malformed.js", should be "../files/malformed.js"'],
       }),
       test({
         code: 'import "./../files/malformed"',
+        output: 'import "../files/malformed"',
         errors: [ 'Useless path segments for "./../files/malformed", should be "../files/malformed"'],
       }),
       test({
         code: 'import "../files/malformed.js"',
+        output: 'import "./malformed.js"',
         errors: [ 'Useless path segments for "../files/malformed.js", should be "./malformed.js"'],
       }),
       test({
         code: 'import "../files/malformed"',
+        output: 'import "./malformed"',
         errors: [ 'Useless path segments for "../files/malformed", should be "./malformed"'],
       }),
       test({
         code: 'import "./test-module/"',
+        output: 'import "./test-module"',
         errors: [ 'Useless path segments for "./test-module/", should be "./test-module"'],
       }),
       test({
         code: 'import "./"',
+        output: 'import "."',
         errors: [ 'Useless path segments for "./", should be "."'],
       }),
       test({
         code: 'import "../"',
+        output: 'import ".."',
         errors: [ 'Useless path segments for "../", should be ".."'],
       }),
       test({
         code: 'import "./deep//a"',
+        output: 'import "./deep/a"',
         errors: [ 'Useless path segments for "./deep//a", should be "./deep/a"'],
       }),
 
       // ES modules + noUselessIndex
       test({
         code: 'import "./bar/index.js"',
+        output: 'import "./bar/"',
         options: [{ noUselessIndex: true }],
         errors: ['Useless path segments for "./bar/index.js", should be "./bar/"'], // ./bar.js exists
       }),
       test({
         code: 'import "./bar/index"',
+        output: 'import "./bar/"',
         options: [{ noUselessIndex: true }],
         errors: ['Useless path segments for "./bar/index", should be "./bar/"'], // ./bar.js exists
       }),
       test({
         code: 'import "./importPath/"',
+        output: 'import "./importPath"',
         options: [{ noUselessIndex: true }],
         errors: ['Useless path segments for "./importPath/", should be "./importPath"'], // ./importPath.js does not exist
       }),
       test({
         code: 'import "./importPath/index.js"',
+        output: 'import "./importPath"',
         options: [{ noUselessIndex: true }],
         errors: ['Useless path segments for "./importPath/index.js", should be "./importPath"'], // ./importPath.js does not exist
       }),
       test({
         code: 'import "./importPath/index"',
+        output: 'import "./importPath"',
         options: [{ noUselessIndex: true }],
         errors: ['Useless path segments for "./importPath/index", should be "./importPath"'], // ./importPath.js does not exist
       }),
       test({
         code: 'import "./index"',
+        output: 'import "."',
         options: [{ noUselessIndex: true }],
         errors: ['Useless path segments for "./index", should be "."'],
       }),
       test({
         code: 'import "../index"',
+        output: 'import ".."',
         options: [{ noUselessIndex: true }],
         errors: ['Useless path segments for "../index", should be ".."'],
       }),
       test({
         code: 'import "../index.js"',
+        output: 'import ".."',
         options: [{ noUselessIndex: true }],
         errors: ['Useless path segments for "../index.js", should be ".."'],
       }),
       test({
         code: 'import("./")',
+        output: 'import(".")',
         errors: [ 'Useless path segments for "./", should be "."'],
         parser: require.resolve('babel-eslint'),
       }),
       test({
         code: 'import("../")',
+        output: 'import("..")',
         errors: [ 'Useless path segments for "../", should be ".."'],
         parser: require.resolve('babel-eslint'),
       }),
       test({
         code: 'import("./deep//a")',
+        output: 'import("./deep/a")',
         errors: [ 'Useless path segments for "./deep//a", should be "./deep/a"'],
         parser: require.resolve('babel-eslint'),
       }),
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 83e459cea9..67deb7b914 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,6 +1,8 @@
 import { test, getTSParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
+import eslintPkg from 'eslint/package.json'
+import semver from 'semver'
 
 const ruleTester = new RuleTester()
     , rule = require('rules/order')
@@ -886,18 +888,25 @@ ruleTester.run('order', rule, {
       }],
     }),
     // Multiple errors
-    test({
-      code: `
-        var sibling = require('./sibling');
-        var async = require('async');
-        var fs = require('fs');
-      `,
-      errors: [{
-        message: '`async` import should occur before import of `./sibling`',
-      }, {
-        message: '`fs` import should occur before import of `./sibling`',
-      }],
-    }),
+    ...semver.satisfies(eslintPkg.version, '< 3.0.0') ? [] : [
+      test({
+        code: `
+          var sibling = require('./sibling');
+          var async = require('async');
+          var fs = require('fs');
+        `,
+          output: `
+          var async = require('async');
+          var sibling = require('./sibling');
+          var fs = require('fs');
+        `,
+        errors: [{
+          message: '`async` import should occur before import of `./sibling`',
+        }, {
+          message: '`fs` import should occur before import of `./sibling`',
+        }],
+      }),
+    ],
     // Uses 'after' wording if it creates less errors
     test({
       code: `
@@ -1974,18 +1983,26 @@ ruleTester.run('order', rule, {
       }],
     }),
     // Alphabetize with require
-    test({
-      code: `
-        const { cello } = require('./cello');
-        import { int } from './int';
-        const blah = require('./blah');
-        import { hello } from './hello';
-      `,
-      errors: [{
-        message: '`./int` import should occur before import of `./cello`',
-      }, {
-        message: '`./hello` import should occur before import of `./cello`',
-      }],
-    }),
+    ...semver.satisfies(eslintPkg.version, '< 3.0.0') ? [] : [
+      test({
+        code: `
+          const { cello } = require('./cello');
+          import { int } from './int';
+          const blah = require('./blah');
+          import { hello } from './hello';
+        `,
+        output: `
+          import { int } from './int';
+          const { cello } = require('./cello');
+          const blah = require('./blah');
+          import { hello } from './hello';
+        `, 
+        errors: [{
+          message: '`./int` import should occur before import of `./cello`',
+        }, {
+          message: '`./hello` import should occur before import of `./cello`',
+        }],
+      }),
+    ],
   ].filter((t) => !!t),
 })

From 5c67f17aa87e836d0007c8cc064f447903155e03 Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Thu, 2 Apr 2020 00:41:52 +0800
Subject: [PATCH 127/767] [Refactor] avoid using deprecated eslint api
 sourceCode.getComments

---
 src/rules/dynamic-import-chunkname.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 44fb5611cc..40b99239ab 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -42,7 +42,9 @@ module.exports = {
 
         const sourceCode = context.getSourceCode()
         const arg = node.arguments[0]
-        const leadingComments = sourceCode.getComments(arg).leading
+        const leadingComments = sourceCode.getCommentsBefore
+          ? sourceCode.getCommentsBefore(arg) // This method is available in ESLint >= 4.
+          : sourceCode.getComments(arg).leading // This method is deprecated in ESLint 7.
 
         if (!leadingComments || leadingComments.length === 0) {
           context.report({

From 6a110dd16a7fd775f08601054bf14ffd503eea7b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 4 Apr 2020 14:09:55 -0700
Subject: [PATCH 128/767] [New] officially support eslint 7

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index aa637e2024..d6c4c95a02 100644
--- a/package.json
+++ b/package.json
@@ -67,7 +67,7 @@
     "chai": "^4.2.0",
     "coveralls": "^3.0.6",
     "cross-env": "^4.0.0",
-    "eslint": "2.x - 6.x",
+    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.0.0-0",
     "eslint-import-resolver-node": "file:./resolvers/node",
     "eslint-import-resolver-typescript": "^1.0.2",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
@@ -88,7 +88,7 @@
     "typescript-eslint-parser": "^22.0.0"
   },
   "peerDependencies": {
-    "eslint": "2.x - 6.x"
+    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.0.0-0"
   },
   "dependencies": {
     "array-includes": "^3.0.3",

From baf1a8c697d14ffa229e24455e84cc7192287d64 Mon Sep 17 00:00:00 2001
From: Ernesto Stifano <ernesto.stifano@codistica.com>
Date: Sun, 29 Mar 2020 16:44:53 +0200
Subject: [PATCH 129/767] [Fix] `group-exports`: Flow type export awareness

Fixes #1702.
---
 CHANGELOG.md                     |  6 ++++
 docs/rules/group-exports.md      | 18 ++++++++++
 package.json                     |  1 +
 src/rules/group-exports.js       | 57 +++++++++++++++++++++--------
 tests/src/rules/group-exports.js | 62 +++++++++++++++++++++++++++++++-
 5 files changed, 129 insertions(+), 15 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b76324d4b..44c62ee562 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
+
 ## [2.20.2] - 2020-03-28
 ### Fixed
 - [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
@@ -660,6 +663,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
 [#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
 [#1664]: https://github.com/benmosher/eslint-plugin-import/pull/1664
 [#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
@@ -988,6 +992,7 @@ for info on changes for earlier releases.
 [0.12.1]: https://github.com/benmosher/eslint-plugin-import/compare/v0.12.0...v0.12.1
 [0.12.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.11.0...v0.12.0
 [0.11.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.10.1...v0.11.0
+
 [@mathieudutour]: https://github.com/mathieudutour
 [@gausie]: https://github.com/gausie
 [@singles]: https://github.com/singles
@@ -1122,3 +1127,4 @@ for info on changes for earlier releases.
 [@fisker]: https://github.com/fisker
 [@richardxia]: https://github.com/richardxia
 [@TheCrueltySage]: https://github.com/TheCrueltySage
+[@ernestostifano]: https://github.com/ernestostifano
diff --git a/docs/rules/group-exports.md b/docs/rules/group-exports.md
index f61ff5306b..e6b9887b24 100644
--- a/docs/rules/group-exports.md
+++ b/docs/rules/group-exports.md
@@ -60,6 +60,15 @@ test.another = true
 module.exports = test
 ```
 
+```flow js
+const first = true;
+type firstType = boolean
+
+// A single named export declaration (type exports handled separately) -> ok
+export {first}
+export type {firstType}
+```
+
 
 ### Invalid
 
@@ -94,6 +103,15 @@ module.exports.first = true
 module.exports.second = true
 ```
 
+```flow js
+type firstType = boolean
+type secondType = any
+
+// Multiple named type export statements -> not ok!
+export type {firstType}
+export type {secondType}
+```
+
 ## When Not To Use It
 
 If you do not mind having your exports spread across the file, you can safely turn this rule off.
diff --git a/package.json b/package.json
index d6c4c95a02..90e4ac8c34 100644
--- a/package.json
+++ b/package.json
@@ -62,6 +62,7 @@
     "babel-plugin-istanbul": "^4.1.6",
     "babel-plugin-module-resolver": "^2.7.1",
     "babel-preset-es2015-argon": "latest",
+    "babel-preset-flow": "^6.23.0",
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
     "chai": "^4.2.0",
diff --git a/src/rules/group-exports.js b/src/rules/group-exports.js
index cd7fc992dd..8abeb3d231 100644
--- a/src/rules/group-exports.js
+++ b/src/rules/group-exports.js
@@ -46,19 +46,28 @@ function accessorChain(node) {
 
 function create(context) {
   const nodes = {
-    modules: new Set(),
-    commonjs: new Set(),
-    sources: {},
+    modules: {
+      set: new Set(),
+      sources: {},
+    },
+    types: {
+      set: new Set(),
+      sources: {},
+    },
+    commonjs: {
+      set: new Set(),
+    },
   }
 
   return {
     ExportNamedDeclaration(node) {
+      let target = node.exportKind === 'type' ? nodes.types : nodes.modules
       if (!node.source) {
-        nodes.modules.add(node)
-      } else if (Array.isArray(nodes.sources[node.source.value])) {
-        nodes.sources[node.source.value].push(node)
+        target.set.add(node)
+      } else if (Array.isArray(target.sources[node.source.value])) {
+        target.sources[node.source.value].push(node)
       } else {
-        nodes.sources[node.source.value] = [node]
+        target.sources[node.source.value] = [node]
       }
     },
 
@@ -73,21 +82,21 @@ function create(context) {
       // Deeper assignments are ignored since they just modify what's already being exported
       // (ie. module.exports.exported.prop = true is ignored)
       if (chain[0] === 'module' && chain[1] === 'exports' && chain.length <= 3) {
-        nodes.commonjs.add(node)
+        nodes.commonjs.set.add(node)
         return
       }
 
       // Assignments to exports (exports.* = *)
       if (chain[0] === 'exports' && chain.length === 2) {
-        nodes.commonjs.add(node)
+        nodes.commonjs.set.add(node)
         return
       }
     },
 
     'Program:exit': function onExit() {
       // Report multiple `export` declarations (ES2015 modules)
-      if (nodes.modules.size > 1) {
-        nodes.modules.forEach(node => {
+      if (nodes.modules.set.size > 1) {
+        nodes.modules.set.forEach(node => {
           context.report({
             node,
             message: errors[node.type],
@@ -96,7 +105,27 @@ function create(context) {
       }
 
       // Report multiple `aggregated exports` from the same module (ES2015 modules)
-      flat(values(nodes.sources)
+      flat(values(nodes.modules.sources)
+        .filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1))
+        .forEach((node) => {
+          context.report({
+            node,
+            message: errors[node.type],
+          })
+        })
+
+      // Report multiple `export type` declarations (FLOW ES2015 modules)
+      if (nodes.types.set.size > 1) {
+        nodes.types.set.forEach(node => {
+          context.report({
+            node,
+            message: errors[node.type],
+          })
+        })
+      }
+
+      // Report multiple `aggregated type exports` from the same module (FLOW ES2015 modules)
+      flat(values(nodes.types.sources)
         .filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1))
         .forEach((node) => {
           context.report({
@@ -106,8 +135,8 @@ function create(context) {
         })
 
       // Report multiple `module.exports` assignments (CommonJS)
-      if (nodes.commonjs.size > 1) {
-        nodes.commonjs.forEach(node => {
+      if (nodes.commonjs.set.size > 1) {
+        nodes.commonjs.set.forEach(node => {
           context.report({
             node,
             message: errors[node.type],
diff --git a/tests/src/rules/group-exports.js b/tests/src/rules/group-exports.js
index 9a0c2c1ba7..0766a325e6 100644
--- a/tests/src/rules/group-exports.js
+++ b/tests/src/rules/group-exports.js
@@ -1,6 +1,8 @@
 import { test } from '../utils'
 import { RuleTester } from 'eslint'
 import rule from 'rules/group-exports'
+import {resolve} from 'path'
+import {default as babelPresetFlow} from 'babel-preset-flow'
 
 /* eslint-disable max-len */
 const errors = {
@@ -8,7 +10,16 @@ const errors = {
   commonjs: 'Multiple CommonJS exports; consolidate all exports into a single assignment to `module.exports`',
 }
 /* eslint-enable max-len */
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester({
+  parser: resolve(__dirname, '../../../node_modules/babel-eslint'),
+  parserOptions: {
+    babelOptions: {
+      configFile: false,
+      babelrc: false,
+      presets: [babelPresetFlow],
+    },
+  },
+})
 
 ruleTester.run('group-exports', rule, {
   valid: [
@@ -103,6 +114,27 @@ ruleTester.run('group-exports', rule, {
       unrelated = 'assignment'
       module.exports.test = true
     ` }),
+    test({ code: `
+      type firstType = {
+        propType: string
+      };
+      const first = {};
+      export type { firstType };
+      export { first };
+    ` }),
+    test({ code: `
+      type firstType = {
+        propType: string
+      };
+      type secondType = {
+        propType: string
+      };
+      export type { firstType, secondType };
+    ` }),
+    test({ code: `
+      export type { type1A, type1B } from './module-1'
+      export { method1 } from './module-1'
+    ` }),
   ],
   invalid: [
     test({
@@ -231,5 +263,33 @@ ruleTester.run('group-exports', rule, {
         errors.commonjs,
       ],
     }),
+    test({
+      code: `
+        type firstType = {
+          propType: string
+        };
+        type secondType = {
+          propType: string
+        };
+        const first = {};
+        export type { firstType };
+        export type { secondType };
+        export { first };
+      `,
+      errors: [
+        errors.named,
+        errors.named,
+      ],
+    }),
+    test({
+      code: `
+        export type { type1 } from './module-1'
+        export type { type2 } from './module-1'
+      `,
+      errors: [
+        errors.named,
+        errors.named,
+      ],
+    }),
   ],
 })

From fe6cea911f6780a59fbc4761e79da853da25f1d2 Mon Sep 17 00:00:00 2001
From: Emily Marigold Klassen <forivall@gmail.com>
Date: Fri, 3 Apr 2020 20:54:41 -0700
Subject: [PATCH 130/767] [Fix] `order`: Recognize pathGroup config for first
 group

Co-authored-by: Emily Marigold Klassen <forivall@gmail.com>
Co-authored-by: Vitaly Gordon <rocket.mind@gmail.com>
---
 CHANGELOG.md             |  5 +++++
 src/rules/order.js       |  2 +-
 tests/src/rules/order.js | 17 +++++++++++++++++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44c62ee562..a08d7aabcb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
+- [`order`]: Recognize pathGroup config for first group ([#1719], [#1724], thanks [@forivall], [@xpl])
 
 ## [2.20.2] - 2020-03-28
 ### Fixed
@@ -663,6 +664,8 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1724]: https://github.com/benmosher/eslint-plugin-import/issues/1724
+[#1719]: https://github.com/benmosher/eslint-plugin-import/issues/1719
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
 [#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
 [#1664]: https://github.com/benmosher/eslint-plugin-import/pull/1664
@@ -1128,3 +1131,5 @@ for info on changes for earlier releases.
 [@richardxia]: https://github.com/richardxia
 [@TheCrueltySage]: https://github.com/TheCrueltySage
 [@ernestostifano]: https://github.com/ernestostifano
+[@forivall]: https://github.com/forivall
+[@xpl]: https://github.com/xpl
diff --git a/src/rules/order.js b/src/rules/order.js
index 948c5f4272..f17b6ad0cd 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -318,7 +318,7 @@ function computeRank(context, ranks, name, type, excludedImportTypes) {
   if (!excludedImportTypes.has(impType)) {
     rank = computePathRank(ranks.groups, ranks.pathGroups, name, ranks.maxPosition)
   }
-  if (!rank) {
+  if (typeof rank === 'undefined') {
     rank = ranks.groups[impType]
   }
   if (type !== 'import') {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 67deb7b914..aee2b1124d 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -307,6 +307,23 @@ ruleTester.run('order', rule, {
         ],
       }],
     }),
+    // Using pathGroups (a test case for https://github.com/benmosher/eslint-plugin-import/pull/1724)
+    test({
+      code: `
+        import fs from 'fs';
+        import external from 'external';
+        import externalTooPlease from './make-me-external';
+
+        import sibling from './sibling';`,
+      options: [{
+        'newlines-between': 'always',
+        pathGroupsExcludedImportTypes: [],
+        pathGroups: [
+          { pattern: './make-me-external', group: 'external' },
+        ],
+        groups: [['builtin', 'external'], 'internal', 'parent', 'sibling', 'index'],
+      }],
+    }),
     // Monorepo setup, using Webpack resolver, workspace folder name in external-module-folders
     test({
       code: `

From 4f1101e584558d9c686144b71222acaaf4f70b72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Astori?= <jeremie@astori.fr>
Date: Mon, 13 Apr 2020 11:43:26 -0400
Subject: [PATCH 131/767] [patch] TypeScript config: Disable `import/named`

---
 CHANGELOG.md         | 5 +++++
 config/typescript.js | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a08d7aabcb..be86fcd50a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
 - [`order`]: Recognize pathGroup config for first group ([#1719], [#1724], thanks [@forivall], [@xpl])
 
+### Changed
+- TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
+
 ## [2.20.2] - 2020-03-28
 ### Fixed
 - [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
@@ -664,6 +667,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1726]: https://github.com/benmosher/eslint-plugin-import/issues/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/issues/1724
 [#1719]: https://github.com/benmosher/eslint-plugin-import/issues/1719
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
@@ -1133,3 +1137,4 @@ for info on changes for earlier releases.
 [@ernestostifano]: https://github.com/ernestostifano
 [@forivall]: https://github.com/forivall
 [@xpl]: https://github.com/xpl
+[@astorije]: https://github.com/astorije
diff --git a/config/typescript.js b/config/typescript.js
index 262e3c7999..705faaf372 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -19,4 +19,10 @@ module.exports = {
     },
   },
 
+  rules: {
+    // analysis/correctness
+
+    // TypeScript compilation already ensures that named imports exist in the referenced module
+    'import/named': 'off',
+  },
 }

From 3b4487c9b9b5a2398a0c0361d6526e709b0559a7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 13 Apr 2020 13:58:16 -0700
Subject: [PATCH 132/767] [Tests] unpin esquery

See https://github.com/estools/esquery/issues/95
---
 package.json | 1 -
 1 file changed, 1 deletion(-)

diff --git a/package.json b/package.json
index 90e4ac8c34..33209b3149 100644
--- a/package.json
+++ b/package.json
@@ -76,7 +76,6 @@
     "eslint-module-utils": "file:./utils",
     "eslint-plugin-eslint-plugin": "^2.2.1",
     "eslint-plugin-import": "2.x",
-    "esquery": "~1.1.0",
     "in-publish": "^2.0.0",
     "linklocal": "^2.8.2",
     "mocha": "^3.5.3",

From 40d1e6785412892515c0a1800aae8a32494bde9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= <fredrik.hoglund@gmail.com>
Date: Mon, 13 Apr 2020 23:20:59 +0200
Subject: [PATCH 133/767] [Fix] `no-unused-modules`: Count re-export as usage
 when used in combination with import

---
 CHANGELOG.md                                     |  3 +++
 src/rules/no-unused-modules.js                   |  8 +++++++-
 tests/files/no-unused-modules/import-export-1.js |  2 ++
 tests/files/no-unused-modules/import-export-2.js |  2 ++
 tests/src/rules/no-unused-modules.js             | 11 +++++++++++
 5 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 tests/files/no-unused-modules/import-export-1.js
 create mode 100644 tests/files/no-unused-modules/import-export-2.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index be86fcd50a..5525a6f14e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
 - [`order`]: Recognize pathGroup config for first group ([#1719], [#1724], thanks [@forivall], [@xpl])
+- [`no-unused-modules`]: Fix re-export not counting as usage when used in combination with import ([#1722], thanks [@Ephem])
 
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
@@ -669,6 +670,7 @@ for info on changes for earlier releases.
 
 [#1726]: https://github.com/benmosher/eslint-plugin-import/issues/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/issues/1724
+[#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
 [#1719]: https://github.com/benmosher/eslint-plugin-import/issues/1719
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
 [#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
@@ -1138,3 +1140,4 @@ for info on changes for earlier releases.
 [@forivall]: https://github.com/forivall
 [@xpl]: https://github.com/xpl
 [@astorije]: https://github.com/astorije
+[@Ephem]: https://github.com/Ephem
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 9468dc87d0..60416d21cd 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -196,7 +196,13 @@ const prepareImportsAndExports = (srcFiles, context) => {
         if (isNodeModule(key)) {
           return
         }
-        imports.set(key, value.importedSpecifiers)
+        let localImport = imports.get(key)
+        if (typeof localImport !== 'undefined') {
+          localImport = new Set([...localImport, ...value.importedSpecifiers])
+        } else {
+          localImport = value.importedSpecifiers
+        }
+        imports.set(key, localImport)
       })
       importList.set(file, imports)
 
diff --git a/tests/files/no-unused-modules/import-export-1.js b/tests/files/no-unused-modules/import-export-1.js
new file mode 100644
index 0000000000..218c3cff7c
--- /dev/null
+++ b/tests/files/no-unused-modules/import-export-1.js
@@ -0,0 +1,2 @@
+export const a = 5;
+export const b = 'b';
diff --git a/tests/files/no-unused-modules/import-export-2.js b/tests/files/no-unused-modules/import-export-2.js
new file mode 100644
index 0000000000..9cfb2747b5
--- /dev/null
+++ b/tests/files/no-unused-modules/import-export-2.js
@@ -0,0 +1,2 @@
+import { a } from './import-export-1';
+export { b } from './import-export-1';
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index d1a7f62fd3..702406316e 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -427,6 +427,17 @@ ruleTester.run('no-unused-modules', rule, {
   ],
 })
 
+// Test that import and export in the same file both counts as usage
+ruleTester.run('no-unused-modules', rule, {
+  valid: [
+    test({ options: unusedExportsOptions,
+          code: `export const a = 5;export const b = 't1'`,
+          filename: testFilePath('./no-unused-modules/import-export-1.js'),
+        }),
+  ],
+  invalid: [],
+})
+
 describe('test behaviour for new file', () => {
   before(() => {
     fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', {encoding: 'utf8'})

From caf45a6e7f3ab0e1edf179abf8531e1a14e77c6d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 19 Apr 2020 00:01:35 -0700
Subject: [PATCH 134/767] [Docs] `no-named-as-default-member`: fix a broken URL

Fixes #1731.
---
 docs/rules/no-named-as-default-member.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/rules/no-named-as-default-member.md b/docs/rules/no-named-as-default-member.md
index da6ae3f1d4..92a7f242c5 100644
--- a/docs/rules/no-named-as-default-member.md
+++ b/docs/rules/no-named-as-default-member.md
@@ -14,7 +14,7 @@ fixed in Babel 6. Before upgrading an existing codebase to Babel 6, it can be
 useful to run this lint rule.
 
 
-[blog]: https://kentcdodds.com/blog/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution
+[blog]: https://web.archive.org/web/20170108102530/https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0
 
 
 ## Rule Details

From 951615228d90c3188dc551147f422dc3165dbadd Mon Sep 17 00:00:00 2001
From: Kevin Mui <kmui2@wisc.edu>
Date: Tue, 3 Mar 2020 22:58:03 -0600
Subject: [PATCH 135/767] [Fix] `no-duplicates`: Handle TS import type

Fixes #1667.
---
 CHANGELOG.md                     |  3 +++
 package.json                     |  4 ++--
 tests/src/rules/no-duplicates.js | 31 ++++++++++++++++++++++++++++++-
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5525a6f14e..ea4eebef6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
 - [`order`]: Recognize pathGroup config for first group ([#1719], [#1724], thanks [@forivall], [@xpl])
 - [`no-unused-modules`]: Fix re-export not counting as usage when used in combination with import ([#1722], thanks [@Ephem])
+- [`no-duplicates`]: Handle TS import type ([#1676], thanks [@kmui2])
 
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
@@ -673,6 +674,7 @@ for info on changes for earlier releases.
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
 [#1719]: https://github.com/benmosher/eslint-plugin-import/issues/1719
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
+[#1676]: https://github.com/benmosher/eslint-plugin-import/pull/1676
 [#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
 [#1664]: https://github.com/benmosher/eslint-plugin-import/pull/1664
 [#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
@@ -1141,3 +1143,4 @@ for info on changes for earlier releases.
 [@xpl]: https://github.com/xpl
 [@astorije]: https://github.com/astorije
 [@Ephem]: https://github.com/Ephem
+[@kmui2]: https://github.com/kmui2
diff --git a/package.json b/package.json
index 33209b3149..acbf3dbbf2 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
   "devDependencies": {
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
-    "@typescript-eslint/parser": "1.10.3-alpha.13",
+    "@typescript-eslint/parser": "^2.23.0",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
     "babel-eslint": "^8.2.6",
@@ -84,7 +84,7 @@
     "rimraf": "^2.7.1",
     "semver": "^6.3.0",
     "sinon": "^2.4.1",
-    "typescript": "~3.2.2",
+    "typescript": "~3.8.3",
     "typescript-eslint-parser": "^22.0.0"
   },
   "peerDependencies": {
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 917d0e400e..0137221b03 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -1,5 +1,5 @@
 import * as path from 'path'
-import { test as testUtil } from '../utils'
+import { test as testUtil, getNonDefaultParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
 
@@ -399,3 +399,32 @@ ruleTester.run('no-duplicates', rule, {
     }),
   ],
 })
+
+context('TypeScript', function() {
+  getNonDefaultParsers()
+  .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+  .forEach((parser) => {
+    const parserConfig = {
+      parser: parser,
+      settings: {
+        'import/parsers': { [parser]: ['.ts'] },
+        'import/resolver': { 'eslint-import-resolver-typescript': true },
+      },
+    }
+
+    ruleTester.run('no-duplicates', rule, {
+      valid: [
+        // #1667: ignore duplicate if is a typescript type import
+        test(
+          {
+            code: "import type { x } from './foo'; import y from './foo'",
+            parser,
+          },
+          parserConfig,
+        ),
+      ],
+      invalid: [],
+    })
+  })
+})
+

From 381267a88f9a71feac1454ea2bf50efdd69be09e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joa=CC=83o=20Vieira?= <joaoguerravieira@gmail.com>
Date: Wed, 30 Oct 2019 17:50:25 +0000
Subject: [PATCH 136/767] [New] `import/default`: support default export in
 TSExportAssignment

Fixes #1527
---
 CHANGELOG.md                                  |  4 ++
 src/ExportMap.js                              | 42 ++++++++++----
 tests/files/typescript-default.ts             |  1 +
 ...pescript-export-assign-default-reexport.ts |  2 +
 .../typescript-export-assign-default.d.ts     |  3 +
 .../files/typescript-export-assign-mixed.d.ts | 11 ++++
 ...cript-export-assign-namespace-merged.d.ts} |  0
 ...> typescript-export-assign-namespace.d.ts} |  0
 tests/src/rules/default.js                    | 55 ++++++++++++++++++-
 tests/src/rules/named.js                      |  7 ++-
 10 files changed, 112 insertions(+), 13 deletions(-)
 create mode 100644 tests/files/typescript-default.ts
 create mode 100644 tests/files/typescript-export-assign-default-reexport.ts
 create mode 100644 tests/files/typescript-export-assign-default.d.ts
 create mode 100644 tests/files/typescript-export-assign-mixed.d.ts
 rename tests/files/{typescript-export-assign-merged.d.ts => typescript-export-assign-namespace-merged.d.ts} (100%)
 rename tests/files/{typescript-export-assign.d.ts => typescript-export-assign-namespace.d.ts} (100%)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea4eebef6e..f88d03d693 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Added
+- [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])
+
 ### Fixed
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
 - [`order`]: Recognize pathGroup config for first group ([#1719], [#1724], thanks [@forivall], [@xpl])
@@ -697,6 +700,7 @@ for info on changes for earlier releases.
 [#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1542]: https://github.com/benmosher/eslint-plugin-import/pull/1542
+[#1528]: https://github.com/benmosher/eslint-plugin-import/pull/1528
 [#1526]: https://github.com/benmosher/eslint-plugin-import/pull/1526
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
 [#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 525f64a48a..5a36b220b8 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -530,30 +530,50 @@ ExportMap.parse = function (path, content, context) {
 
     // This doesn't declare anything, but changes what's being exported.
     if (n.type === 'TSExportAssignment') {
-      const moduleDecls = ast.body.filter((bodyNode) =>
-        bodyNode.type === 'TSModuleDeclaration' && bodyNode.id.name === n.expression.name
+      const exportedName = n.expression.name
+      const declTypes = [
+        'VariableDeclaration',
+        'ClassDeclaration',
+        'TSDeclareFunction',
+        'TSEnumDeclaration',
+        'TSTypeAliasDeclaration',
+        'TSInterfaceDeclaration',
+        'TSAbstractClassDeclaration',
+        'TSModuleDeclaration',
+      ]
+      const exportedDecls = ast.body.filter(({ type, id, declarations }) => 
+        declTypes.includes(type) && 
+        (id && id.name === exportedName || declarations.find(d => d.id.name === exportedName))
       )
-      moduleDecls.forEach((moduleDecl) => {
-        if (moduleDecl && moduleDecl.body && moduleDecl.body.body) {
-          moduleDecl.body.body.forEach((moduleBlockNode) => {
+      if (exportedDecls.length === 0) {
+        // Export is not referencing any local declaration, must be re-exporting
+        m.namespace.set('default', captureDoc(source, docStyleParsers, n))
+        return
+      }
+      exportedDecls.forEach((decl) => {
+        if (decl.type === 'TSModuleDeclaration' && decl && decl.body && decl.body.body) {
+          decl.body.body.forEach((moduleBlockNode) => {
             // Export-assignment exports all members in the namespace, explicitly exported or not.
-            const exportedDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
+            const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
               moduleBlockNode.declaration :
               moduleBlockNode
 
-            if (exportedDecl.type === 'VariableDeclaration') {
-              exportedDecl.declarations.forEach((decl) =>
-                recursivePatternCapture(decl.id,(id) => m.namespace.set(
+            if (namespaceDecl.type === 'VariableDeclaration') {
+              namespaceDecl.declarations.forEach((d) =>
+                recursivePatternCapture(d.id, (id) => m.namespace.set(
                   id.name,
-                  captureDoc(source, docStyleParsers, decl, exportedDecl, moduleBlockNode))
+                  captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode))
                 )
               )
             } else {
               m.namespace.set(
-                exportedDecl.id.name,
+                namespaceDecl.id.name,
                 captureDoc(source, docStyleParsers, moduleBlockNode))
             }
           })
+        } else {
+          // Export as default
+          m.namespace.set('default', captureDoc(source, docStyleParsers, decl))
         }
       })
     }
diff --git a/tests/files/typescript-default.ts b/tests/files/typescript-default.ts
new file mode 100644
index 0000000000..6d9a8f42c0
--- /dev/null
+++ b/tests/files/typescript-default.ts
@@ -0,0 +1 @@
+export default function foobar() {};
diff --git a/tests/files/typescript-export-assign-default-reexport.ts b/tests/files/typescript-export-assign-default-reexport.ts
new file mode 100644
index 0000000000..2fd502539c
--- /dev/null
+++ b/tests/files/typescript-export-assign-default-reexport.ts
@@ -0,0 +1,2 @@
+import { getFoo } from './typescript';
+export = getFoo;
diff --git a/tests/files/typescript-export-assign-default.d.ts b/tests/files/typescript-export-assign-default.d.ts
new file mode 100644
index 0000000000..f871ed9261
--- /dev/null
+++ b/tests/files/typescript-export-assign-default.d.ts
@@ -0,0 +1,3 @@
+export = foobar;
+
+declare const foobar: number;
diff --git a/tests/files/typescript-export-assign-mixed.d.ts b/tests/files/typescript-export-assign-mixed.d.ts
new file mode 100644
index 0000000000..8bf4c34b8c
--- /dev/null
+++ b/tests/files/typescript-export-assign-mixed.d.ts
@@ -0,0 +1,11 @@
+export = foobar;
+
+declare function foobar(): void;
+declare namespace foobar {
+  type MyType = string
+  enum MyEnum {
+    Foo,
+    Bar,
+    Baz
+  }
+}
diff --git a/tests/files/typescript-export-assign-merged.d.ts b/tests/files/typescript-export-assign-namespace-merged.d.ts
similarity index 100%
rename from tests/files/typescript-export-assign-merged.d.ts
rename to tests/files/typescript-export-assign-namespace-merged.d.ts
diff --git a/tests/files/typescript-export-assign.d.ts b/tests/files/typescript-export-assign-namespace.d.ts
similarity index 100%
rename from tests/files/typescript-export-assign.d.ts
rename to tests/files/typescript-export-assign-namespace.d.ts
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index 4544285afb..79d03e6c55 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES } from '../utils'
+import { test, SYNTAX_CASES, getTSParsers } from '../utils'
 import { RuleTester } from 'eslint'
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve'
@@ -152,3 +152,56 @@ if (!CASE_SENSITIVE_FS) {
     ],
   })
 }
+
+context('TypeScript', function () {
+  getTSParsers().forEach((parser) => {
+      ruleTester.run(`default`, rule, {
+        valid: [
+          test({
+            code: `import foobar from "./typescript-default"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+          }),
+          test({
+            code: `import foobar from "./typescript-export-assign-default"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+          }),
+          test({
+            code: `import foobar from "./typescript-export-assign-mixed"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+          }),
+          test({
+            code: `import foobar from "./typescript-export-assign-default-reexport"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+          }),
+        ],
+
+        invalid: [
+          test({
+            code: `import foobar from "./typescript"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+            errors: ['No default export found in imported module "./typescript".'],
+          }),
+        ],
+      })
+    })
+})
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 303df1e145..eba7bec1ad 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -285,7 +285,12 @@ ruleTester.run('named (export *)', rule, {
 
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
-    ['typescript', 'typescript-declare', 'typescript-export-assign', 'typescript-export-assign-merged'].forEach((source) => {
+    [
+      'typescript', 
+      'typescript-declare', 
+      'typescript-export-assign-namespace', 
+      'typescript-export-assign-namespace-merged',
+    ].forEach((source) => {
       ruleTester.run(`named`, rule, {
         valid: [
           test({

From 67a31b1316ee702d9bc5534a380d1f944a645c7b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 23 Apr 2020 11:02:31 -0700
Subject: [PATCH 137/767] [Tests] `no-unused-modules`: add export +
 destructuring case

Closes #1683.
---
 tests/src/rules/no-unused-modules.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 702406316e..d409e41ed7 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -52,6 +52,10 @@ ruleTester.run('no-unused-modules', rule, {
            code: 'const a = 1; export default a'}),
     test({ options: missingExportsOptions,
            code: 'export class Foo {}'}),
+    test({ options: missingExportsOptions,
+           code: 'export const [foobar] = [];'}),
+    test({ options: missingExportsOptions,
+           code: 'export const [foobar] = foobarFactory();'}),
   ],
   invalid: [
     test({

From 055389d425caae7219659fb97b6d0b992d2f1aaa Mon Sep 17 00:00:00 2001
From: Nikolay Stoynov <arvigeus@gmail.com>
Date: Sat, 11 Jan 2020 12:39:41 +0200
Subject: [PATCH 138/767] [readme] Remove duplicate no-unused-modules from docs

Remove no-unused-modules from Static analysis because it is already mentioned in Helpful warnings
---
 CHANGELOG.md | 3 +++
 README.md    | 2 --
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f88d03d693..2648c8954a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
+- [readme] Remove duplicate no-unused-modules from docs ([#1690], thanks [@arvigeus])
 
 ## [2.20.2] - 2020-03-28
 ### Fixed
@@ -677,6 +678,7 @@ for info on changes for earlier releases.
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
 [#1719]: https://github.com/benmosher/eslint-plugin-import/issues/1719
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
+[#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
 [#1676]: https://github.com/benmosher/eslint-plugin-import/pull/1676
 [#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
 [#1664]: https://github.com/benmosher/eslint-plugin-import/pull/1664
@@ -1148,3 +1150,4 @@ for info on changes for earlier releases.
 [@astorije]: https://github.com/astorije
 [@Ephem]: https://github.com/Ephem
 [@kmui2]: https://github.com/kmui2
+[@arvigeus]: https://github.com/arvigeus
diff --git a/README.md b/README.md
index cc9d1d789b..e08e72ffa2 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,6 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 * Forbid a module from importing a module with a dependency path back to itself ([`no-cycle`])
 * Prevent unnecessary path segments in import and require statements ([`no-useless-path-segments`])
 * Forbid importing modules from parent directories ([`no-relative-parent-imports`])
-* Forbid modules without any export, and exports not imported by any modules. ([`no-unused-modules`])
 
 [`no-unresolved`]: ./docs/rules/no-unresolved.md
 [`named`]: ./docs/rules/named.md
@@ -42,7 +41,6 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 [`no-cycle`]: ./docs/rules/no-cycle.md
 [`no-useless-path-segments`]: ./docs/rules/no-useless-path-segments.md
 [`no-relative-parent-imports`]: ./docs/rules/no-relative-parent-imports.md
-[`no-unused-modules`]: ./docs/rules/no-unused-modules.md
 
 ### Helpful warnings
 

From 73211e80ea9a263a8ac0a544a2a1f150da19687f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Veyret?= <stephane@neptura.org>
Date: Wed, 11 Mar 2020 17:37:42 +0100
Subject: [PATCH 139/767] [New] `no-cycle`: add `ignoreExternal` option

Fixes #1647
---
 CHANGELOG.md                             |  2 ++
 docs/rules/no-cycle.md                   | 23 +++++++++++++++++
 src/rules/no-cycle.js                    | 12 +++++++++
 tests/files/cycles/external-depth-two.js |  2 ++
 tests/files/cycles/external/depth-one.js |  2 ++
 tests/src/rules/no-cycle.js              | 32 ++++++++++++++++++++++++
 6 files changed, 73 insertions(+)
 create mode 100644 tests/files/cycles/external-depth-two.js
 create mode 100644 tests/files/cycles/external/depth-one.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2648c8954a..3bbc7245f9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Added
 - [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])
+- [`no-cycle`]: add `ignoreExternal` option ([#1681], thanks [@sveyret])
 
 ### Fixed
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
@@ -679,6 +680,7 @@ for info on changes for earlier releases.
 [#1719]: https://github.com/benmosher/eslint-plugin-import/issues/1719
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
 [#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
+[#1681]: https://github.com/benmosher/eslint-plugin-import/pull/1681
 [#1676]: https://github.com/benmosher/eslint-plugin-import/pull/1676
 [#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
 [#1664]: https://github.com/benmosher/eslint-plugin-import/pull/1664
diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md
index 8819d6704f..6329bb272e 100644
--- a/docs/rules/no-cycle.md
+++ b/docs/rules/no-cycle.md
@@ -55,6 +55,26 @@ import { b } from './dep-b.js' // not reported as the cycle is at depth 2
 This is not necessarily recommended, but available as a cost/benefit tradeoff mechanism
 for reducing total project lint time, if needed.
 
+#### `ignoreExternal`
+
+An `ignoreExternal` option is available to prevent the cycle detection to expand to external modules:
+
+```js
+/*eslint import/no-cycle: [2, { ignoreExternal: true }]*/
+
+// dep-a.js
+import 'module-b/dep-b.js'
+
+export function a() { /* ... */ }
+```
+
+```js
+// node_modules/module-b/dep-b.js
+import { a } from './dep-a.js' // not reported as this module is external
+```
+
+Its value is `false` by default, but can be set to `true` for reducing total project lint time, if needed.
+
 ## When Not To Use It
 
 This rule is comparatively computationally expensive. If you are pressed for lint
@@ -65,5 +85,8 @@ this rule enabled.
 
 - [Original inspiring issue](https://github.com/benmosher/eslint-plugin-import/issues/941)
 - Rule to detect that module imports itself: [`no-self-import`]
+- [`import/external-module-folders`] setting
 
 [`no-self-import`]: ./no-self-import.md
+
+[`import/external-module-folders`]: ../../README.md#importexternal-module-folders
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 62da3643b4..8f39246b5c 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -4,6 +4,7 @@
  */
 
 import Exports from '../ExportMap'
+import { isExternalModule } from '../core/importType'
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor'
 import docsUrl from '../docsUrl'
 
@@ -18,6 +19,11 @@ module.exports = {
         type: 'integer',
         minimum: 1,
       },
+      ignoreExternal: {
+        description: 'ignore external modules',
+        type: 'boolean',
+        default: false,
+      },
     })],
   },
 
@@ -27,8 +33,13 @@ module.exports = {
 
     const options = context.options[0] || {}
     const maxDepth = options.maxDepth || Infinity
+    const ignoreModule = (name) => options.ignoreExternal ? isExternalModule(name) : false
 
     function checkSourceValue(sourceNode, importer) {
+      if (ignoreModule(sourceNode.value)) {
+        return // ignore external modules
+      }
+
       const imported = Exports.get(sourceNode.value, context)
 
       if (importer.importKind === 'type') {
@@ -54,6 +65,7 @@ module.exports = {
         for (let [path, { getter, source }] of m.imports) {
           if (path === myPath) return true
           if (traversed.has(path)) continue
+          if (ignoreModule(source.value)) continue
           if (route.length + 1 < maxDepth) {
             untraversed.push({
               mget: getter,
diff --git a/tests/files/cycles/external-depth-two.js b/tests/files/cycles/external-depth-two.js
new file mode 100644
index 0000000000..fbb6bfcbb2
--- /dev/null
+++ b/tests/files/cycles/external-depth-two.js
@@ -0,0 +1,2 @@
+import { foo } from "cycles/external/depth-one"
+export { foo }
diff --git a/tests/files/cycles/external/depth-one.js b/tests/files/cycles/external/depth-one.js
new file mode 100644
index 0000000000..9caa762505
--- /dev/null
+++ b/tests/files/cycles/external/depth-one.js
@@ -0,0 +1,2 @@
+import foo from "../depth-zero"
+export { foo }
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 5d6cfc6618..b0f4153e8d 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -40,6 +40,22 @@ ruleTester.run('no-cycle', rule, {
       code: 'import { foo, bar } from "./depth-two"',
       options: [{ maxDepth: 1 }],
     }),
+    test({
+      code: 'import { foo } from "cycles/external/depth-one"',
+      options: [{ ignoreExternal: true }],
+      settings: {
+        'import/resolver': 'webpack',
+        'import/external-module-folders': ['external'],
+      },
+    }),
+    test({
+      code: 'import { foo } from "./external-depth-two"',
+      options: [{ ignoreExternal: true }],
+      settings: {
+        'import/resolver': 'webpack',
+        'import/external-module-folders': ['external'],
+      },
+    }),
     test({
       code: 'import("./depth-two").then(function({ foo }){})',
       options: [{ maxDepth: 1 }],
@@ -63,6 +79,22 @@ ruleTester.run('no-cycle', rule, {
       code: 'import { foo } from "./depth-one"',
       errors: [error(`Dependency cycle detected.`)],
     }),
+    test({
+      code: 'import { foo } from "cycles/external/depth-one"',
+      errors: [error(`Dependency cycle detected.`)],
+      settings: {
+        'import/resolver': 'webpack',
+        'import/external-module-folders': ['external'],
+      },
+    }),
+    test({
+      code: 'import { foo } from "./external-depth-two"',
+      errors: [error(`Dependency cycle via cycles/external/depth-one:1`)],
+      settings: {
+        'import/resolver': 'webpack',
+        'import/external-module-folders': ['external'],
+      },
+    }),
     test({
       code: 'import { foo } from "./depth-one"',
       options: [{ maxDepth: 1 }],

From cf8b3d9c46f0c09d74e87e978a45a26e3e0ff3a1 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 23 Apr 2020 12:37:19 -0700
Subject: [PATCH 140/767] [Docs] `no-named-as-default-member`: use
 non-archive.org link

Per https://github.com/benmosher/eslint-plugin-import/issues/1731#issuecomment-616155999
---
 docs/rules/no-named-as-default-member.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/rules/no-named-as-default-member.md b/docs/rules/no-named-as-default-member.md
index 92a7f242c5..da6ae3f1d4 100644
--- a/docs/rules/no-named-as-default-member.md
+++ b/docs/rules/no-named-as-default-member.md
@@ -14,7 +14,7 @@ fixed in Babel 6. Before upgrading an existing codebase to Babel 6, it can be
 useful to run this lint rule.
 
 
-[blog]: https://web.archive.org/web/20170108102530/https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0
+[blog]: https://kentcdodds.com/blog/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution
 
 
 ## Rule Details

From 95c12fca0a8d07a2b72d42a5a8a0530b3a51e768 Mon Sep 17 00:00:00 2001
From: Miguel Oller <maoa22@gmail.com>
Date: Sun, 29 Mar 2020 01:36:42 -0400
Subject: [PATCH 141/767] [resolvers/webpack] [fix] provide config fallback

Fixes #1448
---
 resolvers/webpack/CHANGELOG.md | 8 +++++++-
 resolvers/webpack/index.js     | 6 ++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 78e01348e4..e06203823d 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Fixed
+- [fix] provide config fallback ([#1705], thanks [@migueloller])
+
 ## 0.12.0 - 2019-12-07
 
 ### Added
@@ -13,7 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## 0.11.1 - 2019-04-13
 
 ### Fixed
-- [fix] match coreLibs after resolveSync in webpack-resolver ([#1297])
+- [fix] match coreLibs after resolveSync in webpack-resolver ([#1297], thanks [@echenley])
 
 ## 0.11.0 - 2018-01-22
 
@@ -122,6 +125,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - `interpret` configs (such as `.babel.js`).
   Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
+[#1705]: https://github.com/benmosher/eslint-plugin-import/pull/1705
 [#1503]: https://github.com/benmosher/eslint-plugin-import/pull/1503
 [#1297]: https://github.com/benmosher/eslint-plugin-import/pull/1297
 [#1261]: https://github.com/benmosher/eslint-plugin-import/pull/1261
@@ -172,4 +176,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@mattkrick]: https://github.com/mattkrick
 [@idudinov]: https://github.com/idudinov
 [@keann]: https://github.com/keann
+[@echenley]: https://github.com/echenley
 [@Aghassi]: https://github.com/Aghassi
+[@migueloller]: https://github.com/migueloller
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index dd3fc7a38a..20c594847b 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -119,6 +119,12 @@ exports.resolve = function (source, file, settings) {
     }
   }
 
+  if (webpackConfig == null) {
+    webpackConfig = {}
+
+    console.warn('No webpack configuration with a "resolve" field found. Using empty object instead')
+  }
+
   log('Using config: ', webpackConfig)
 
   // externals

From a8888b02572a49d41bf208624f914d6593b4adc7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 24 Apr 2020 00:07:23 -0700
Subject: [PATCH 142/767] [meta] `appveyor`: only run tests, not linter

---
 appveyor.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/appveyor.yml b/appveyor.yml
index 29e310a182..70366a055e 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -48,7 +48,7 @@ test_script:
   - npm --version
 
   # core tests
-  - npm test
+  - npm run tests-only
 
   # resolver tests
   - cd .\resolvers\webpack && npm test && cd ..\..

From b307c7c14bed8b20807cc629911093c5ec47f0ed Mon Sep 17 00:00:00 2001
From: Averin Anton <aaverin@marathonbet.ru>
Date: Tue, 17 Jul 2018 19:18:55 +0300
Subject: [PATCH 143/767] [Fix] `newline-after-import`: recognize decorators

Fixes #1004.
---
 CHANGELOG.md                            |  3 +++
 src/rules/newline-after-import.js       | 12 +++++++++-
 tests/src/rules/newline-after-import.js | 32 +++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3bbc7245f9..de430cf595 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]: Recognize pathGroup config for first group ([#1719], [#1724], thanks [@forivall], [@xpl])
 - [`no-unused-modules`]: Fix re-export not counting as usage when used in combination with import ([#1722], thanks [@Ephem])
 - [`no-duplicates`]: Handle TS import type ([#1676], thanks [@kmui2])
+- [``newline-after-import`: recognize decorators ([#1139], thanks [@atos1990])
 
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
@@ -770,6 +771,7 @@ for info on changes for earlier releases.
 [#1157]: https://github.com/benmosher/eslint-plugin-import/pull/1157
 [#1151]: https://github.com/benmosher/eslint-plugin-import/pull/1151
 [#1142]: https://github.com/benmosher/eslint-plugin-import/pull/1142
+[#1139]: https://github.com/benmosher/eslint-plugin-import/pull/1139
 [#1137]: https://github.com/benmosher/eslint-plugin-import/pull/1137
 [#1135]: https://github.com/benmosher/eslint-plugin-import/pull/1135
 [#1128]: https://github.com/benmosher/eslint-plugin-import/pull/1128
@@ -1153,3 +1155,4 @@ for info on changes for earlier releases.
 [@Ephem]: https://github.com/Ephem
 [@kmui2]: https://github.com/kmui2
 [@arvigeus]: https://github.com/arvigeus
+[@atos1990]: https://github.com/atos1990
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 690826eb42..7807dfcdab 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -43,6 +43,10 @@ function isClassWithDecorator(node) {
   return node.type === 'ClassDeclaration' && node.decorators && node.decorators.length
 }
 
+function isExportDefaultClass(node) {
+  return node.type === 'ExportDefaultDeclaration' && node.declaration.type === 'ClassDeclaration'
+}
+
 module.exports = {
   meta: {
     type: 'layout',
@@ -68,7 +72,13 @@ module.exports = {
     const requireCalls = []
 
     function checkForNewLine(node, nextNode, type) {
-      if (isClassWithDecorator(nextNode)) {
+      if (isExportDefaultClass(nextNode)) {
+        let classNode = nextNode.declaration
+
+        if (isClassWithDecorator(classNode)) {
+          nextNode = classNode.decorators[0]
+        }
+      } else if (isClassWithDecorator(nextNode)) {
         nextNode = nextNode.decorators[0]
       }
 
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 220b217d77..bb94b56dad 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -165,6 +165,16 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       parser: require.resolve('babel-eslint'),
     },
+    {
+      code : `// issue 1004\nimport foo from 'foo';\n\n@SomeDecorator(foo)\nexport default class Test {}`,
+      parserOptions: { sourceType: 'module' },
+      parser: require.resolve('babel-eslint'),
+    },
+    {
+      code : `// issue 1004\nconst foo = require('foo');\n\n@SomeDecorator(foo)\nexport default class Test {}`,
+      parserOptions: { sourceType: 'module' },
+      parser: require.resolve('babel-eslint'),
+    },
   ],
 
   invalid: [
@@ -340,5 +350,27 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       parser: require.resolve('babel-eslint'),
     },
+    {
+      code: `// issue 10042\nimport foo from 'foo';\n@SomeDecorator(foo)\nexport default class Test {}`,
+      output: `// issue 10042\nimport foo from 'foo';\n\n@SomeDecorator(foo)\nexport default class Test {}`,
+      errors: [ {
+        line: 2,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE,
+      } ],
+      parserOptions: { sourceType: 'module' },
+      parser: require.resolve('babel-eslint'),
+    },
+    {
+      code: `// issue 1004\nconst foo = require('foo');\n@SomeDecorator(foo)\nexport default class Test {}`,
+      output: `// issue 1004\nconst foo = require('foo');\n\n@SomeDecorator(foo)\nexport default class Test {}`,
+      errors: [ {
+        line: 2,
+        column: 1,
+        message: REQUIRE_ERROR_MESSAGE,
+      } ],
+      parserOptions: { sourceType: 'module' },
+      parser: require.resolve('babel-eslint'),
+    },
   ],
 })

From 92caa3594e0f8d7bf143dedba0c7c2b47b541f34 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 24 Apr 2020 00:14:38 -0700
Subject: [PATCH 144/767] [Tests] on `node` `v14`

---
 .travis.yml  | 8 +++++++-
 appveyor.yml | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 929bca0852..e34ae479a5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
 language: node_js
 node_js:
+  - '14'
   - '13'
   - '12'
   - '10'
@@ -23,7 +24,7 @@ matrix:
   - env: LINT=true
     node_js: lts/*
   - env: PACKAGE=resolvers/node
-    node_js: 13
+    node_js: 14
   - env: PACKAGE=resolvers/node
     node_js: 12
   - env: PACKAGE=resolvers/node
@@ -34,6 +35,8 @@ matrix:
     node_js: 6
   - env: PACKAGE=resolvers/node
     node_js: 4
+  - env: PACKAGE=resolvers/webpack
+    node_js: 14
   - env: PACKAGE=resolvers/webpack
     node_js: 12
   - env: PACKAGE=resolvers/webpack
@@ -45,6 +48,9 @@ matrix:
   - env: PACKAGE=resolvers/webpack
     node_js: 4
 
+  - os: osx
+    env: ESLINT_VERSION=5
+    node_js: 14
   - os: osx
     env: ESLINT_VERSION=5
     node_js: 12
diff --git a/appveyor.yml b/appveyor.yml
index 70366a055e..4505d78d76 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,6 +1,7 @@
 # Test against this version of Node.js
 environment:
   matrix:
+  - nodejs_version: "14"
   - nodejs_version: "12"
   - nodejs_version: "10"
   - nodejs_version: "8"

From 3f46ccfe203fa5aad5767699df339a9b2f0294e3 Mon Sep 17 00:00:00 2001
From: Filipp Riabchun <filipp.riabchun@jetbrains.com>
Date: Tue, 19 May 2020 20:21:07 +0200
Subject: [PATCH 145/767] Revert "[flow] `no-unused-modules`: add flow type
 support"

This reverts commit 05085bbd
---
 CHANGELOG.md                            |  5 +++-
 src/rules/no-unused-modules.js          |  7 ++----
 tests/files/no-unused-modules/flow-0.js |  1 -
 tests/files/no-unused-modules/flow-1.js |  2 --
 tests/files/no-unused-modules/flow-2.js |  2 --
 tests/src/rules/no-unused-modules.js    | 32 -------------------------
 6 files changed, 6 insertions(+), 43 deletions(-)
 delete mode 100644 tests/files/no-unused-modules/flow-0.js
 delete mode 100644 tests/files/no-unused-modules/flow-1.js
 delete mode 100644 tests/files/no-unused-modules/flow-2.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index de430cf595..c6e9ec9751 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,7 +15,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]: Recognize pathGroup config for first group ([#1719], [#1724], thanks [@forivall], [@xpl])
 - [`no-unused-modules`]: Fix re-export not counting as usage when used in combination with import ([#1722], thanks [@Ephem])
 - [`no-duplicates`]: Handle TS import type ([#1676], thanks [@kmui2])
-- [``newline-after-import`: recognize decorators ([#1139], thanks [@atos1990])
+- [`newline-after-import`]: recognize decorators ([#1139], thanks [@atos1990])
+- [`no-unused-modules`]: Revert "[flow] `no-unused-modules`: add flow type support" ([#1770], thanks [@Hypnosphi])
 
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
@@ -675,6 +676,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1770]: https://github.com/benmosher/eslint-plugin-import/issues/1770
 [#1726]: https://github.com/benmosher/eslint-plugin-import/issues/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/issues/1724
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
@@ -1156,3 +1158,4 @@ for info on changes for earlier releases.
 [@kmui2]: https://github.com/kmui2
 [@arvigeus]: https://github.com/arvigeus
 [@atos1990]: https://github.com/atos1990
+[@Hypnosphi]: https://github.com/Hypnosphi
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 60416d21cd..9d2d91a1b7 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -64,7 +64,6 @@ const VARIABLE_DECLARATION = 'VariableDeclaration'
 const FUNCTION_DECLARATION = 'FunctionDeclaration'
 const CLASS_DECLARATION = 'ClassDeclaration'
 const DEFAULT = 'default'
-const TYPE_ALIAS = 'TypeAlias'
 
 /**
  * List of imports per file.
@@ -563,8 +562,7 @@ module.exports = {
           if (declaration) {
             if (
               declaration.type === FUNCTION_DECLARATION ||
-              declaration.type === CLASS_DECLARATION ||
-              declaration.type === TYPE_ALIAS
+              declaration.type === CLASS_DECLARATION
             ) {
               newExportIdentifiers.add(declaration.id.name)
             }
@@ -889,8 +887,7 @@ module.exports = {
         if (node.declaration) {
           if (
             node.declaration.type === FUNCTION_DECLARATION ||
-            node.declaration.type === CLASS_DECLARATION ||
-            node.declaration.type === TYPE_ALIAS
+            node.declaration.type === CLASS_DECLARATION
           ) {
             checkUsage(node, node.declaration.id.name)
           }
diff --git a/tests/files/no-unused-modules/flow-0.js b/tests/files/no-unused-modules/flow-0.js
deleted file mode 100644
index 46bda68794..0000000000
--- a/tests/files/no-unused-modules/flow-0.js
+++ /dev/null
@@ -1 +0,0 @@
-import { type FooType } from './flow-2';
diff --git a/tests/files/no-unused-modules/flow-1.js b/tests/files/no-unused-modules/flow-1.js
deleted file mode 100644
index bb7266d3ce..0000000000
--- a/tests/files/no-unused-modules/flow-1.js
+++ /dev/null
@@ -1,2 +0,0 @@
-// @flow strict
-export type Bar = number;
diff --git a/tests/files/no-unused-modules/flow-2.js b/tests/files/no-unused-modules/flow-2.js
deleted file mode 100644
index 0cbb836a6d..0000000000
--- a/tests/files/no-unused-modules/flow-2.js
+++ /dev/null
@@ -1,2 +0,0 @@
-// @flow strict
-export type FooType = string;
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index d409e41ed7..a066dd33f2 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -680,38 +680,6 @@ describe('do not report unused export for files mentioned in package.json', () =
   })
 })
 
-describe('correctly report flow types', () => {
-  ruleTester.run('no-unused-modules', rule, {
-    valid: [
-      test({
-        options: unusedExportsOptions,
-        code: 'import { type FooType } from "./flow-2";',
-        parser: require.resolve('babel-eslint'),
-        filename: testFilePath('./no-unused-modules/flow-0.js'),
-      }),
-      test({
-        options: unusedExportsOptions,
-        code: `// @flow strict
-               export type FooType = string;`,
-        parser: require.resolve('babel-eslint'),
-        filename: testFilePath('./no-unused-modules/flow-2.js'),
-      }),
-    ],
-    invalid: [
-      test({
-        options: unusedExportsOptions,
-        code: `// @flow strict
-               export type Bar = string;`,
-        parser: require.resolve('babel-eslint'),
-        filename: testFilePath('./no-unused-modules/flow-1.js'),
-        errors: [
-          error(`exported declaration 'Bar' not used within other modules`),
-        ],
-      }),
-    ],
-  })
-})
-
 describe('Avoid errors if re-export all from umd compiled library', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [

From 2e72af5a99211d3994dba3465fe2567c9335c150 Mon Sep 17 00:00:00 2001
From: Nick Partridge <nick.ryan.partridge@gmail.com>
Date: Fri, 29 May 2020 15:41:05 -0500
Subject: [PATCH 146/767] [Docs] `order`: fix bad inline config

`alphabetize` option does not permit boolean
---
 CHANGELOG.md        | 11 +++++++----
 docs/rules/order.md |  4 ++--
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c6e9ec9751..a97d84aa21 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
 - [readme] Remove duplicate no-unused-modules from docs ([#1690], thanks [@arvigeus])
+- [Docs] `order`: fix bad inline config ([#1788], thanks [@nickofthyme])
 
 ## [2.20.2] - 2020-03-28
 ### Fixed
@@ -676,11 +677,12 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
-[#1770]: https://github.com/benmosher/eslint-plugin-import/issues/1770
-[#1726]: https://github.com/benmosher/eslint-plugin-import/issues/1726
-[#1724]: https://github.com/benmosher/eslint-plugin-import/issues/1724
+[#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
+[#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
+[#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
+[#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
-[#1719]: https://github.com/benmosher/eslint-plugin-import/issues/1719
+[#1719]: https://github.com/benmosher/eslint-plugin-import/pull/1719
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
 [#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
 [#1681]: https://github.com/benmosher/eslint-plugin-import/pull/1681
@@ -1159,3 +1161,4 @@ for info on changes for earlier releases.
 [@arvigeus]: https://github.com/arvigeus
 [@atos1990]: https://github.com/atos1990
 [@Hypnosphi]: https://github.com/Hypnosphi
+[@nickofthyme]: https://github.com/nickofthyme
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 667b63374f..3aa41bbf50 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -229,7 +229,7 @@ alphabetize: {
 This will fail the rule check:
 
 ```js
-/* eslint import/order: ["error", {"alphabetize": true}] */
+/* eslint import/order: ["error", {"alphabetize": {"order": "asc", "caseInsensitive": true}}] */
 import React, { PureComponent } from 'react';
 import aTypes from 'prop-types';
 import { compose, apply } from 'xcompose';
@@ -240,7 +240,7 @@ import blist from 'BList';
 While this will pass:
 
 ```js
-/* eslint import/order: ["error", {"alphabetize": true}] */
+/* eslint import/order: ["error", {"alphabetize": {"order": "asc", "caseInsensitive": true}}] */
 import blist from 'BList';
 import * as classnames from 'classnames';
 import aTypes from 'prop-types';

From 62b554bc5f5024695b40d8701fbd8267fb4eb73f Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Fri, 29 May 2020 21:26:28 +0200
Subject: [PATCH 147/767] [New] `order`: Add support for TypeScript's "import
 equals"-expressions

---
 CHANGELOG.md             |  3 +++
 package.json             |  4 +--
 src/rules/order.js       | 55 +++++++++++++++++++++++--------------
 tests/src/rules/order.js | 58 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 98 insertions(+), 22 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a97d84aa21..e4d37cdd53 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Added
 - [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])
 - [`no-cycle`]: add `ignoreExternal` option ([#1681], thanks [@sveyret])
+- [`order`]: Add support for TypeScript's "import equals"-expressions ([#1785], thanks [@manuth])
 
 ### Fixed
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
@@ -678,6 +679,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
+[#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
 [#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
@@ -1162,3 +1164,4 @@ for info on changes for earlier releases.
 [@atos1990]: https://github.com/atos1990
 [@Hypnosphi]: https://github.com/Hypnosphi
 [@nickofthyme]: https://github.com/nickofthyme
+[@manuth]: https://github.com/manuth
diff --git a/package.json b/package.json
index acbf3dbbf2..90596b292f 100644
--- a/package.json
+++ b/package.json
@@ -25,8 +25,8 @@
     "watch": "npm run tests-only -- -- --watch",
     "pretest": "linklocal",
     "posttest": "eslint .",
-    "mocha": "nyc -s mocha",
-    "tests-only": "cross-env BABEL_ENV=test npm run mocha tests/src",
+    "mocha": "cross-env BABEL_ENV=test nyc -s mocha",
+    "tests-only": "npm run mocha tests/src",
     "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
     "test-all": "npm test && for resolver in ./resolvers/*; do cd $resolver && npm test && cd ../..; done",
diff --git a/src/rules/order.js b/src/rules/order.js
index f17b6ad0cd..9edac3af91 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -157,8 +157,12 @@ function isPlainImportModule(node) {
   return node.type === 'ImportDeclaration' && node.specifiers != null && node.specifiers.length > 0
 }
 
+function isPlainImportEquals(node) {
+  return node.type === 'TSImportEqualsDeclaration' && node.moduleReference.expression
+}
+
 function canCrossNodeWhileReorder(node) {
-  return isPlainRequireModule(node) || isPlainImportModule(node)
+  return isPlainRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node)
 }
 
 function canReorderItems(firstNode, secondNode) {
@@ -243,28 +247,22 @@ function makeOutOfOrderReport(context, imported) {
   reportOutOfOrder(context, imported, outOfOrder, 'before')
 }
 
-function importsSorterAsc(importA, importB) {
-  if (importA < importB) {
-    return -1
-  }
-
-  if (importA > importB) {
-    return 1
-  }
+function getSorter(ascending) {
+  let multiplier = (ascending ? 1 : -1)
 
-  return 0
-}
+  return function importsSorter(importA, importB) {
+    let result
 
-function importsSorterDesc(importA, importB) {
-  if (importA < importB) {
-    return 1
-  }
+    if ((importA < importB) || importB === null) {
+      result = -1
+    } else if ((importA > importB) || importA === null) {
+      result = 1
+    } else {
+      result = 0
+    }
 
-  if (importA > importB) {
-    return -1
+    return result * multiplier
   }
-
-  return 0
 }
 
 function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
@@ -278,7 +276,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
 
   const groupRanks = Object.keys(groupedByRanks)
 
-  const sorterFn = alphabetizeOptions.order === 'asc' ? importsSorterAsc : importsSorterDesc
+  const sorterFn = getSorter(alphabetizeOptions.order === 'asc')
   const comparator = alphabetizeOptions.caseInsensitive ? (a, b) => sorterFn(String(a).toLowerCase(), String(b).toLowerCase()) : (a, b) => sorterFn(a, b)
   // sort imports locally within their group
   groupRanks.forEach(function(groupRank) {
@@ -609,6 +607,23 @@ module.exports = {
           )
         }
       },
+      TSImportEqualsDeclaration: function handleImports(node) {
+        let name
+        if (node.moduleReference.type === 'TSExternalModuleReference') {
+          name = node.moduleReference.expression.value
+        } else {
+          name = null
+        }
+        registerNode(
+          context,
+          node,
+          name,
+          'import',
+          ranks,
+          imported,
+          pathGroupsExcludedImportTypes
+        )
+      },
       CallExpression: function handleRequires(node) {
         if (level !== 0 || !isStaticRequire(node) || !isInVariableDeclarator(node.parent)) {
           return
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index aee2b1124d..529582e84a 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -167,6 +167,22 @@ ruleTester.run('order', rule, {
         var index = require('./');
       `,
     }),
+    // Export equals expressions should be on top alongside with ordinary import-statements.
+    ...getTSParsers().map(parser => (
+      test({
+        code: `
+          import async, {foo1} from 'async';
+          import relParent2, {foo2} from '../foo/bar';
+          import sibling, {foo3} from './foo';
+          var fs = require('fs');
+          var util = require("util");
+          var relParent1 = require('../foo');
+          var relParent3 = require('../');
+          var index = require('./');
+        `,
+        parser,
+      })
+    )),
     // Adding unknown import types (e.g. using a resolver alias via babel) to the groups.
     test({
       code: `
@@ -1142,6 +1158,24 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur after import of `../foo/bar`',
       }],
     }),
+    ...getTSParsers().map(parser => (
+      test({
+        code: `
+          var fs = require('fs');
+          import async, {foo1} from 'async';
+          import bar = require("../foo/bar");
+        `,
+        output: `
+          import async, {foo1} from 'async';
+          import bar = require("../foo/bar");
+          var fs = require('fs');
+        `,
+        parser,
+        errors: [{
+          message: '`fs` import should occur after import of `../foo/bar`',
+        }],
+      })
+    )),
     // Default order using import with custom import alias
     test({
       code: `
@@ -1913,6 +1947,30 @@ ruleTester.run('order', rule, {
         message: '`Bar` import should occur before import of `bar`',
       }],
     }),
+    ...getTSParsers().map(parser => (
+        test({
+          code: `
+            import sync = require('sync');
+            import async, {foo1} from 'async';
+
+            import index from './';
+          `,
+          output: `
+            import async, {foo1} from 'async';
+            import sync = require('sync');
+
+            import index from './';
+          `,
+          options: [{
+            groups: ['external', 'index'],
+            alphabetize: {order: 'asc'},
+          }],
+          parser,
+          errors: [{
+            message: '`async` import should occur before import of `sync`',
+          }],
+        })
+      )),
     // Option alphabetize: {order: 'desc'}
     test({
       code: `

From 8118170d6fc6d626829ccbedba4be10bd3b97c55 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Fri, 29 May 2020 22:06:04 +0200
Subject: [PATCH 148/767] [Tests] Add fix for Windows Subsystem for Linux

 - Update appveyor-config to include wsl
---
 CHANGELOG.md     |   2 +
 appveyor.yml     | 140 ++++++++++++++++++++++++++++++++++-------------
 utils/resolve.js |   2 +-
 3 files changed, 104 insertions(+), 40 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4d37cdd53..baae8d2e28 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
 - [readme] Remove duplicate no-unused-modules from docs ([#1690], thanks [@arvigeus])
 - [Docs] `order`: fix bad inline config ([#1788], thanks [@nickofthyme])
+- [Tests] Add fix for Windows Subsystem for Linux ([#1786], thanks [@manuth])
 
 ## [2.20.2] - 2020-03-28
 ### Fixed
@@ -679,6 +680,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
+[#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
 [#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
 [#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
diff --git a/appveyor.yml b/appveyor.yml
index 4505d78d76..3981e91b47 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,3 +1,7 @@
+configuration:
+  - Native
+  - WSL
+
 # Test against this version of Node.js
 environment:
   matrix:
@@ -8,8 +12,12 @@ environment:
   # - nodejs_version: "6"
   # - nodejs_version: "4"
 
+image: Visual Studio 2019
 matrix:
   fast_finish: false
+  exclude:
+    - configuration: WSL
+      nodejs_version: "8"
 
   # allow_failures:
   #   - nodejs_version: "4" # for eslint 5
@@ -18,45 +26,99 @@ matrix:
 #   - x86
 #   - x64
 
-# Install scripts. (runs after repo cloning)
-install:
-  # Get the latest stable version of Node.js or io.js
-  - ps: Install-Product node $env:nodejs_version
-
-  # install modules
-  - ps: >-
-      if ($env:nodejs_version -eq "4") {
-        npm install -g npm@3;
-      }
-      if ($env:nodejs_version -in @("8", "10", "12")) {
-        npm install -g npm@6.10.3;
-      }
-  - npm install
-
-  # fix symlinks
-  - cmd: git config core.symlinks true
-  - cmd: git reset --hard
-
-  # todo: learn how to do this for all .\resolvers\* on Windows
-  - cd .\resolvers\webpack && npm install && cd ..\..
-  - cd .\resolvers\node && npm install && cd ..\..
-
-# Post-install test scripts.
-test_script:
-
-  # Output useful info for debugging.
-  - node --version
-  - npm --version
-
-  # core tests
-  - npm run tests-only
-
-  # resolver tests
-  - cd .\resolvers\webpack && npm test && cd ..\..
-  - cd .\resolvers\node && npm test && cd ..\..
-
-on_success:
-  - npm run coveralls
+for:
+-
+  matrix:
+    only:
+      - configuration: Native
+  # Install scripts. (runs after repo cloning)
+  install:
+    # Get the latest stable version of Node.js or io.js
+    - ps: Install-Product node $env:nodejs_version
+
+    # install modules
+    - ps: >-
+        if ($env:nodejs_version -eq "4") {
+          npm install -g npm@3;
+        }
+        if ($env:nodejs_version -in @("8", "10", "12")) {
+          npm install -g npm@6.10.3;
+        }
+    - npm install
+
+    # fix symlinks
+    - git config core.symlinks true
+    - git reset --hard
+
+    # todo: learn how to do this for all .\resolvers\* on Windows
+    - cd .\resolvers\webpack && npm install && cd ..\..
+    - cd .\resolvers\node && npm install && cd ..\..
+
+  # Post-install test scripts.
+  test_script:
+
+    # Output useful info for debugging.
+    - node --version
+    - npm --version
+
+    # core tests
+    - npm run pretest
+    - npm run tests-only
+
+    # resolver tests
+    - cd .\resolvers\webpack && npm test && cd ..\..
+    - cd .\resolvers\node && npm test && cd ..\..
+
+  on_success:
+    - npm run coveralls
+-
+  matrix:
+    only:
+      - configuration: WSL
+  # Install scripts. (runs after repo cloning)
+  install:
+    # Get the latest stable version of Node.js or io.js
+    - ps: $env:WSLENV += ":nodejs_version"
+    - ps: wsl curl -sL 'https://deb.nodesource.com/setup_${nodejs_version}.x' `| sudo APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 -E bash -
+    - wsl sudo DEBIAN_FRONTEND=noninteractive apt install -y nodejs
+
+    # install modules
+    - ps: >-
+        if ($env:nodejs_version -eq "4") {
+          wsl sudo npm install -g npm@3;
+        }
+        if ($env:nodejs_version -in @("8", "10", "12")) {
+          wsl sudo npm install -g npm@6.10.3;
+        }
+    - wsl npm install
+
+    # fix symlinks
+    - git config core.symlinks true
+    - git reset --hard
+    # reset new-line characters
+    - wsl git reset --hard
+
+    # todo: learn how to do this for all .\resolvers\* on Windows
+    - cd .\resolvers\webpack && wsl npm install && cd ..\..
+    - cd .\resolvers\node && wsl npm install && cd ..\..
+
+  # Post-install test scripts.
+  test_script:
+
+    # Output useful info for debugging.
+    - wsl node --version
+    - wsl npm --version
+
+    # core tests
+    - wsl npm run pretest
+    - wsl npm run tests-only
+
+    # resolver tests
+    - cd .\resolvers\webpack && wsl npm test && cd ..\..
+    - cd .\resolvers\node && wsl npm test && cd ..\..
+
+  on_success:
+    - wsl npm run coveralls
 
 # Don't actually build.
 build: off
diff --git a/utils/resolve.js b/utils/resolve.js
index 3138194a94..fc8f85de9a 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -10,7 +10,7 @@ const path = require('path')
 const hashObject = require('./hash').hashObject
     , ModuleCache = require('./ModuleCache').default
 
-const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname, 'reSOLVE.js'))
+const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname.toUpperCase(), 'reSOLVE.js'))
 exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS
 
 const ERROR_NAME = 'EslintPluginImportResolveError'

From 5cc31478a12c138b382e8efa97275db945b80562 Mon Sep 17 00:00:00 2001
From: Julien Blatecky <julien.blatecky@creatiwity.net>
Date: Wed, 13 May 2020 16:59:09 +0200
Subject: [PATCH 149/767] [Fix] TypeScript: Add nested namespace handling

---
 CHANGELOG.md                               |  3 ++
 src/ExportMap.js                           | 43 ++++++++++++----------
 tests/files/typescript-declare-nested.d.ts | 15 ++++++++
 tests/src/rules/namespace.js               | 15 +++++++-
 4 files changed, 56 insertions(+), 20 deletions(-)
 create mode 100644 tests/files/typescript-declare-nested.d.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index baae8d2e28..b9cfe0d71c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-duplicates`]: Handle TS import type ([#1676], thanks [@kmui2])
 - [`newline-after-import`]: recognize decorators ([#1139], thanks [@atos1990])
 - [`no-unused-modules`]: Revert "[flow] `no-unused-modules`: add flow type support" ([#1770], thanks [@Hypnosphi])
+- TypeScript: Add nested namespace handling ([#1763], thanks [@julien1619])
 
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
@@ -683,6 +684,7 @@ for info on changes for earlier releases.
 [#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
 [#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
 [#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
+[#1763]: https://github.com/benmosher/eslint-plugin-import/pull/1763
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
@@ -1167,3 +1169,4 @@ for info on changes for earlier releases.
 [@Hypnosphi]: https://github.com/Hypnosphi
 [@nickofthyme]: https://github.com/nickofthyme
 [@manuth]: https://github.com/manuth
+[@julien1619]: https://github.com/julien1619
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 5a36b220b8..b53d252a33 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -551,26 +551,31 @@ ExportMap.parse = function (path, content, context) {
         return
       }
       exportedDecls.forEach((decl) => {
-        if (decl.type === 'TSModuleDeclaration' && decl && decl.body && decl.body.body) {
-          decl.body.body.forEach((moduleBlockNode) => {
-            // Export-assignment exports all members in the namespace, explicitly exported or not.
-            const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
-              moduleBlockNode.declaration :
-              moduleBlockNode
-
-            if (namespaceDecl.type === 'VariableDeclaration') {
-              namespaceDecl.declarations.forEach((d) =>
-                recursivePatternCapture(d.id, (id) => m.namespace.set(
-                  id.name,
-                  captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode))
+        if (decl.type === 'TSModuleDeclaration') {
+          if (decl.body && decl.body.type === 'TSModuleDeclaration') {
+            m.namespace.set(decl.body.id.name, captureDoc(source, docStyleParsers, decl.body))
+          } else if (decl.body && decl.body.body) {
+            decl.body.body.forEach((moduleBlockNode) => {
+              // Export-assignment exports all members in the namespace,
+              // explicitly exported or not.
+              const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
+                moduleBlockNode.declaration :
+                moduleBlockNode
+
+              if (namespaceDecl.type === 'VariableDeclaration') {
+                namespaceDecl.declarations.forEach((d) =>
+                  recursivePatternCapture(d.id, (id) => m.namespace.set(
+                    id.name,
+                    captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode)
+                  ))
                 )
-              )
-            } else {
-              m.namespace.set(
-                namespaceDecl.id.name,
-                captureDoc(source, docStyleParsers, moduleBlockNode))
-            }
-          })
+              } else {
+                m.namespace.set(
+                  namespaceDecl.id.name,
+                  captureDoc(source, docStyleParsers, moduleBlockNode))
+              }
+            })
+          }
         } else {
           // Export as default
           m.namespace.set('default', captureDoc(source, docStyleParsers, decl))
diff --git a/tests/files/typescript-declare-nested.d.ts b/tests/files/typescript-declare-nested.d.ts
new file mode 100644
index 0000000000..dc6b0049a3
--- /dev/null
+++ b/tests/files/typescript-declare-nested.d.ts
@@ -0,0 +1,15 @@
+declare namespace foo {
+  interface SomeInterface {
+    a: string;
+  }
+}
+
+declare namespace foo.bar {
+  interface SomeOtherInterface {
+    b: string;
+  }
+
+  function MyFunction();
+}
+
+export = foo;
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index cfc6305d5a..cac18c62a5 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES } from '../utils'
+import { test, SYNTAX_CASES, getTSParsers } from '../utils'
 import { RuleTester } from 'eslint'
 
 var ruleTester = new RuleTester({ env: { es6: true }})
@@ -120,6 +120,19 @@ const valid = [
     },
   }),
 
+  // Typescript
+  ...getTSParsers().map((parser) => test({
+    code: `
+      import * as foo from "./typescript-declare-nested"
+      foo.bar.MyFunction()
+    `,
+    parser: parser,
+    settings: {
+      'import/parsers': { [parser]: ['.ts'] },
+      'import/resolver': { 'eslint-import-resolver-typescript': true },
+    },
+  })),
+
   ...SYNTAX_CASES,
 ]
 

From 6159ce9fb25c64526f89befa082d704e64796e68 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 30 May 2020 20:00:10 -0700
Subject: [PATCH 150/767] [Tests] `no-extraneous-dependencies`: avoid hardcoded
 test cases for deps

In particular, this removes test cases that only pass accidentally due
to node_modules' structure, which should help fix tests on Windows.
---
 package.json                                  |  1 +
 tests/src/rules/no-extraneous-dependencies.js | 28 +++++++++++--------
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/package.json b/package.json
index 90596b292f..b9faf9e515 100644
--- a/package.json
+++ b/package.json
@@ -56,6 +56,7 @@
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "^2.23.0",
+    "array.prototype.flatmap": "^1.2.3",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
     "babel-eslint": "^8.2.6",
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index a9540e51ee..97279d8538 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -3,8 +3,10 @@ import * as path from 'path'
 import * as fs from 'fs'
 
 import { RuleTester } from 'eslint'
+import flatMap from 'array.prototype.flatmap'
+
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-extraneous-dependencies')
+const rule = require('rules/no-extraneous-dependencies')
 
 const packageDirWithSyntaxError = path.join(__dirname, '../../files/with-syntax-error')
 const packageFileWithSyntaxErrorMessage = (() => {
@@ -22,21 +24,25 @@ const packageDirBundleDeps = path.join(__dirname, '../../files/bundled-dependenc
 const packageDirBundledDepsAsObject = path.join(__dirname, '../../files/bundled-dependencies/as-object')
 const packageDirBundledDepsRaceCondition = path.join(__dirname, '../../files/bundled-dependencies/race-condition')
 
+const {
+  dependencies: deps,
+  devDependencies: devDeps,
+} = require('../../files/package.json')
+
 ruleTester.run('no-extraneous-dependencies', rule, {
   valid: [
-    test({ code: 'import "lodash.cond"'}),
-    test({ code: 'import "pkg-up"'}),
-    test({ code: 'import foo, { bar } from "lodash.cond"'}),
-    test({ code: 'import foo, { bar } from "pkg-up"'}),
+    ...flatMap(Object.keys(deps).concat(Object.keys(devDeps)), (pkg) => [
+      test({ code: `import "${pkg}"` }),
+      test({ code: `import foo, { bar } from "${pkg}"` }),
+      test({ code: `require("${pkg}")` }),
+      test({ code: `var foo = require("${pkg}")` }),
+      test({ code: `export { foo } from "${pkg}"` }),
+      test({ code: `export * from "${pkg}"` }),
+    ]),
     test({ code: 'import "eslint"'}),
     test({ code: 'import "eslint/lib/api"'}),
-    test({ code: 'require("lodash.cond")'}),
-    test({ code: 'require("pkg-up")'}),
-    test({ code: 'var foo = require("lodash.cond")'}),
-    test({ code: 'var foo = require("pkg-up")'}),
     test({ code: 'import "fs"'}),
     test({ code: 'import "./foo"'}),
-    test({ code: 'import "lodash.isarray"'}),
     test({ code: 'import "@org/package"'}),
 
     test({ code: 'import "electron"', settings: { 'import/core-modules': ['electron'] } }),
@@ -113,8 +119,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import foo from "@generated/foo"',
       options: [{packageDir: packageDirBundledDepsRaceCondition}],
     }),
-    test({ code: 'export { foo } from "lodash.cond"' }),
-    test({ code: 'export * from "lodash.cond"' }),
     test({ code: 'export function getToken() {}' }),
     test({ code: 'export class Component extends React.Component {}' }),
     test({ code: 'export function Component() {}' }),

From eb2b7eac06147d9c88f39b780a048896eb6b7d2c Mon Sep 17 00:00:00 2001
From: Kevin Mui <kmui2@wisc.edu>
Date: Sun, 26 Apr 2020 20:49:38 -0500
Subject: [PATCH 151/767] [Tests] `order`: Add TS import type tests

Co-authored-by: Kevin Mui <kmui2@wisc.edu>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 CHANGELOG.md             |   2 +
 tests/src/rules/order.js | 144 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9cfe0d71c..c5634132ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -49,6 +49,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
 - [meta] fix "files" field to include/exclude the proper files ([#1635], thanks [@ljharb])
+- [Tests] `order`: Add TS import type tests ([#1736], thanks [@kmui2])
 
 ## [2.20.0] - 2020-01-10
 ### Added
@@ -685,6 +686,7 @@ for info on changes for earlier releases.
 [#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
 [#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
 [#1763]: https://github.com/benmosher/eslint-plugin-import/pull/1763
+[#1736]: https://github.com/benmosher/eslint-plugin-import/pull/1736
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 529582e84a..f6e2dddbaa 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,4 +1,4 @@
-import { test, getTSParsers } from '../utils'
+import { test, getTSParsers, getNonDefaultParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
 import eslintPkg from 'eslint/package.json'
@@ -2071,7 +2071,7 @@ ruleTester.run('order', rule, {
           const { cello } = require('./cello');
           const blah = require('./blah');
           import { hello } from './hello';
-        `, 
+        `,
         errors: [{
           message: '`./int` import should occur before import of `./cello`',
         }, {
@@ -2081,3 +2081,143 @@ ruleTester.run('order', rule, {
     ],
   ].filter((t) => !!t),
 })
+
+
+context('TypeScript', function () {
+  getNonDefaultParsers()
+    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .forEach((parser) => {
+      const parserConfig = {
+        parser: parser,
+        settings: {
+          'import/parsers': { [parser]: ['.ts'] },
+          'import/resolver': { 'eslint-import-resolver-typescript': true },
+        },
+      }
+
+      ruleTester.run('order', rule, {
+        valid: [
+          // #1667: typescript type import support
+
+          // Option alphabetize: {order: 'asc'}
+          test(
+            {
+              code: `
+                import c from 'Bar';
+                import type { C } from 'Bar';
+                import b from 'bar';
+                import a from 'foo';
+                import type { A } from 'foo';
+
+                import index from './';
+              `,
+              parser,
+              options: [
+                {
+                  groups: ['external', 'index'],
+                  alphabetize: { order: 'asc' },
+                },
+              ],
+            },
+            parserConfig,
+          ),
+          // Option alphabetize: {order: 'desc'}
+          test(
+            {
+              code: `
+                import a from 'foo';
+                import type { A } from 'foo';
+                import b from 'bar';
+                import c from 'Bar';
+                import type { C } from 'Bar';
+
+                import index from './';
+              `,
+              parser,
+              options: [
+                {
+                  groups: ['external', 'index'],
+                  alphabetize: { order: 'desc' },
+                },
+              ],
+            },
+            parserConfig,
+          ),
+        ],
+        invalid: [
+          // Option alphabetize: {order: 'asc'}
+          test(
+            {
+              code: `
+              import b from 'bar';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import index from './';
+            `,
+              output: `
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import b from 'bar';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import index from './';
+            `,
+              parser,
+              options: [
+                {
+                  groups: ['external', 'index'],
+                  alphabetize: { order: 'asc' },
+                },
+              ],
+              errors: [
+                {
+                  message: process.env.ESLINT_VERSION === '2' ? '`bar` import should occur after import of `Bar`' : /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,
+                },
+              ],
+            },
+            parserConfig,
+          ),
+          // Option alphabetize: {order: 'desc'}
+          test(
+            {
+              code: `
+              import a from 'foo';
+              import type { A } from 'foo';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import b from 'bar';
+
+              import index from './';
+            `,
+              output: `
+              import a from 'foo';
+              import type { A } from 'foo';
+              import b from 'bar';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+
+              import index from './';
+            `,
+              parser,
+              options: [
+                {
+                  groups: ['external', 'index'],
+                  alphabetize: { order: 'desc' },
+                },
+              ],
+              errors: [
+                {
+                  message: process.env.ESLINT_VERSION === '2' ? '`bar` import should occur before import of `Bar`' : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
+                },
+              ],
+            },
+            parserConfig,
+          ),
+        ],
+      })
+    })
+})

From 40ee069f107effe6a8a62f94607e91fad1da4eb6 Mon Sep 17 00:00:00 2001
From: Julien Blatecky <julien.blatecky@creatiwity.net>
Date: Wed, 13 May 2020 18:40:07 +0200
Subject: [PATCH 152/767] [Fix] `namespace`/`ExportMap`: Fix interface
 declarations for TypeScript

See also #1528.
---
 CHANGELOG.md                                  |  2 ++
 src/ExportMap.js                              |  5 ++++-
 tests/files/typescript-declare-interface.d.ts | 11 +++++++++++
 tests/src/rules/namespace.js                  |  9 +++++++++
 4 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 tests/files/typescript-declare-interface.d.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5634132ee..9d9c2d01b7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`newline-after-import`]: recognize decorators ([#1139], thanks [@atos1990])
 - [`no-unused-modules`]: Revert "[flow] `no-unused-modules`: add flow type support" ([#1770], thanks [@Hypnosphi])
 - TypeScript: Add nested namespace handling ([#1763], thanks [@julien1619])
+- [`namespace`]/`ExportMap`: Fix interface declarations for TypeScript ([#1764], thanks [@julien1619])
 
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
@@ -685,6 +686,7 @@ for info on changes for earlier releases.
 [#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
 [#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
 [#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
+[#1764]: https://github.com/benmosher/eslint-plugin-import/pull/1764
 [#1763]: https://github.com/benmosher/eslint-plugin-import/pull/1763
 [#1736]: https://github.com/benmosher/eslint-plugin-import/pull/1736
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
diff --git a/src/ExportMap.js b/src/ExportMap.js
index b53d252a33..56f9f58b57 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -543,7 +543,10 @@ ExportMap.parse = function (path, content, context) {
       ]
       const exportedDecls = ast.body.filter(({ type, id, declarations }) => 
         declTypes.includes(type) && 
-        (id && id.name === exportedName || declarations.find(d => d.id.name === exportedName))
+        (
+          (id && id.name === exportedName) ||
+          (declarations && declarations.find(d => d.id.name === exportedName))
+        )
       )
       if (exportedDecls.length === 0) {
         // Export is not referencing any local declaration, must be re-exporting
diff --git a/tests/files/typescript-declare-interface.d.ts b/tests/files/typescript-declare-interface.d.ts
new file mode 100644
index 0000000000..b572b62e90
--- /dev/null
+++ b/tests/files/typescript-declare-interface.d.ts
@@ -0,0 +1,11 @@
+declare interface foo {
+  a: string;
+}
+
+declare namespace SomeNamespace {
+  type foobar = foo & {
+    b: string;
+  }
+}
+
+export = SomeNamespace
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index cac18c62a5..ba8c9145d3 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -133,6 +133,15 @@ const valid = [
     },
   })),
 
+  ...getTSParsers().map((parser) => test({
+    code: `import { foobar } from "./typescript-declare-interface"`,
+    parser: parser,
+    settings: {
+      'import/parsers': { [parser]: ['.ts'] },
+      'import/resolver': { 'eslint-import-resolver-typescript': true },
+    },
+  })),
+
   ...SYNTAX_CASES,
 ]
 

From a1c969fe4801dd9db50f00c0825c420947de0862 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=83=D1=80=20=D0=A3=D0=B4=D0=B0=D0=BB?=
 =?UTF-8?q?=D0=BE=D0=B2?= <artur.udalov@gmail.com>
Date: Sat, 2 May 2020 21:14:07 +0300
Subject: [PATCH 153/767] [Fix] `no-unused-modules`: avoid order-dependence

Fixes #1743
---
 CHANGELOG.md                                  |  3 +++
 src/rules/no-unused-modules.js                |  9 +++----
 .../renameDefault-2/ComponentA.js             |  1 +
 .../renameDefault-2/ComponentB.js             |  1 +
 .../renameDefault-2/components.js             |  2 ++
 .../renameDefault-2/usage.js                  |  1 +
 .../renameDefault/Component.js                |  1 +
 .../renameDefault/components.js               |  1 +
 .../no-unused-modules/renameDefault/usage.js  |  1 +
 tests/src/rules/no-unused-modules.js          | 25 +++++++++++++++++++
 10 files changed, 40 insertions(+), 5 deletions(-)
 create mode 100644 tests/files/no-unused-modules/renameDefault-2/ComponentA.js
 create mode 100644 tests/files/no-unused-modules/renameDefault-2/ComponentB.js
 create mode 100644 tests/files/no-unused-modules/renameDefault-2/components.js
 create mode 100644 tests/files/no-unused-modules/renameDefault-2/usage.js
 create mode 100644 tests/files/no-unused-modules/renameDefault/Component.js
 create mode 100644 tests/files/no-unused-modules/renameDefault/components.js
 create mode 100644 tests/files/no-unused-modules/renameDefault/usage.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d9c2d01b7..495bc30357 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: Revert "[flow] `no-unused-modules`: add flow type support" ([#1770], thanks [@Hypnosphi])
 - TypeScript: Add nested namespace handling ([#1763], thanks [@julien1619])
 - [`namespace`]/`ExportMap`: Fix interface declarations for TypeScript ([#1764], thanks [@julien1619])
+- [`no-unused-modules`]: avoid order-dependence ([#1744], thanks [@darkartur])
 
 ### Changed
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
@@ -688,6 +689,7 @@ for info on changes for earlier releases.
 [#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
 [#1764]: https://github.com/benmosher/eslint-plugin-import/pull/1764
 [#1763]: https://github.com/benmosher/eslint-plugin-import/pull/1763
+[#1744]: https://github.com/benmosher/eslint-plugin-import/pull/1744
 [#1736]: https://github.com/benmosher/eslint-plugin-import/pull/1736
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
@@ -1174,3 +1176,4 @@ for info on changes for earlier releases.
 [@nickofthyme]: https://github.com/nickofthyme
 [@manuth]: https://github.com/manuth
 [@julien1619]: https://github.com/julien1619
+[@darkartur]: https://github.com/darkartur
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 9d2d91a1b7..25139b681f 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -654,13 +654,12 @@ module.exports = {
           if (astNode.source) {
             resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context)
             astNode.specifiers.forEach(specifier => {
-              let name
-              if (specifier.exported.name === DEFAULT) {
-                name = IMPORT_DEFAULT_SPECIFIER
+              const name = specifier.local.name
+              if (specifier.local.name === DEFAULT) {
+                newDefaultImports.add(resolvedPath)
               } else {
-                name = specifier.local.name
+                newImports.set(name, resolvedPath)
               }
-              newImports.set(name, resolvedPath)
             })
           }
         }
diff --git a/tests/files/no-unused-modules/renameDefault-2/ComponentA.js b/tests/files/no-unused-modules/renameDefault-2/ComponentA.js
new file mode 100644
index 0000000000..b4517920fc
--- /dev/null
+++ b/tests/files/no-unused-modules/renameDefault-2/ComponentA.js
@@ -0,0 +1 @@
+export default function ComponentA() {}
diff --git a/tests/files/no-unused-modules/renameDefault-2/ComponentB.js b/tests/files/no-unused-modules/renameDefault-2/ComponentB.js
new file mode 100644
index 0000000000..72e0f2ee7a
--- /dev/null
+++ b/tests/files/no-unused-modules/renameDefault-2/ComponentB.js
@@ -0,0 +1 @@
+export default function ComponentB() {}
diff --git a/tests/files/no-unused-modules/renameDefault-2/components.js b/tests/files/no-unused-modules/renameDefault-2/components.js
new file mode 100644
index 0000000000..5a72952a3e
--- /dev/null
+++ b/tests/files/no-unused-modules/renameDefault-2/components.js
@@ -0,0 +1,2 @@
+export { default as ComponentA } from "./ComponentA";
+export { default as ComponentB } from "./ComponentB";
diff --git a/tests/files/no-unused-modules/renameDefault-2/usage.js b/tests/files/no-unused-modules/renameDefault-2/usage.js
new file mode 100644
index 0000000000..7298baa559
--- /dev/null
+++ b/tests/files/no-unused-modules/renameDefault-2/usage.js
@@ -0,0 +1 @@
+import { ComponentA, ComponentB } from './components'
diff --git a/tests/files/no-unused-modules/renameDefault/Component.js b/tests/files/no-unused-modules/renameDefault/Component.js
new file mode 100644
index 0000000000..c6be8faf00
--- /dev/null
+++ b/tests/files/no-unused-modules/renameDefault/Component.js
@@ -0,0 +1 @@
+export default function Component() {}
diff --git a/tests/files/no-unused-modules/renameDefault/components.js b/tests/files/no-unused-modules/renameDefault/components.js
new file mode 100644
index 0000000000..4a877cb1f8
--- /dev/null
+++ b/tests/files/no-unused-modules/renameDefault/components.js
@@ -0,0 +1 @@
+export { default as Component } from './Component'
diff --git a/tests/files/no-unused-modules/renameDefault/usage.js b/tests/files/no-unused-modules/renameDefault/usage.js
new file mode 100644
index 0000000000..6ee988988b
--- /dev/null
+++ b/tests/files/no-unused-modules/renameDefault/usage.js
@@ -0,0 +1 @@
+import { Component } from './components'
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index a066dd33f2..ef2d3e66c2 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -442,6 +442,31 @@ ruleTester.run('no-unused-modules', rule, {
   invalid: [],
 })
 
+describe('renameDefault', () => {
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({ options: unusedExportsOptions,
+        code: 'export { default as Component } from "./Component"',
+        filename: testFilePath('./no-unused-modules/renameDefault/components.js')}),
+      test({ options: unusedExportsOptions,
+        code: 'export default function Component() {}',
+        filename: testFilePath('./no-unused-modules/renameDefault/Component.js')}),
+    ],
+    invalid: [],
+  })
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({ options: unusedExportsOptions,
+        code: 'export { default as ComponentA } from "./ComponentA";export { default as ComponentB } from "./ComponentB";',
+        filename: testFilePath('./no-unused-modules/renameDefault-2/components.js')}),
+      test({ options: unusedExportsOptions,
+        code: 'export default function ComponentA() {};',
+        filename: testFilePath('./no-unused-modules/renameDefault-2/ComponentA.js')}),
+    ],
+    invalid: [],
+  })
+})
+
 describe('test behaviour for new file', () => {
   before(() => {
     fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', {encoding: 'utf8'})

From 0e5bed97c6b0cba5f7540980235a7b6ffdb1e89f Mon Sep 17 00:00:00 2001
From: Michael Olukoya <michael.olukoya@askattest.com>
Date: Wed, 6 May 2020 17:17:16 +0100
Subject: [PATCH 154/767] [Docs] `no-webpack-loader-syntax`: Updates webpack
 URLs

---
 CHANGELOG.md                           | 3 +++
 docs/rules/no-webpack-loader-syntax.md | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 495bc30357..c76df6a186 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,6 +35,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-duplicates`]: fix fixer on cases with default import ([#1666], thanks [@golopot])
 - [`no-unused-modules`]: Handle `export { default } from` syntax ([#1631], thanks [@richardxia])
 - [`first`]: Add a way to disable `absolute-first` explicitly ([#1664], thanks [@TheCrueltySage])
+- [Docs] `no-webpack-loader-syntax`: Updates webpack URLs ([#1751], thanks [@MikeyBeLike])
 
 ## [2.20.1] - 2020-02-01
 ### Fixed
@@ -689,6 +690,7 @@ for info on changes for earlier releases.
 [#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
 [#1764]: https://github.com/benmosher/eslint-plugin-import/pull/1764
 [#1763]: https://github.com/benmosher/eslint-plugin-import/pull/1763
+[#1751]: https://github.com/benmosher/eslint-plugin-import/pull/1751
 [#1744]: https://github.com/benmosher/eslint-plugin-import/pull/1744
 [#1736]: https://github.com/benmosher/eslint-plugin-import/pull/1736
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
@@ -1177,3 +1179,4 @@ for info on changes for earlier releases.
 [@manuth]: https://github.com/manuth
 [@julien1619]: https://github.com/julien1619
 [@darkartur]: https://github.com/darkartur
+[@MikeyBeLike]: https://github.com/MikeyBeLike
diff --git a/docs/rules/no-webpack-loader-syntax.md b/docs/rules/no-webpack-loader-syntax.md
index 37b39a4325..271c76ca82 100644
--- a/docs/rules/no-webpack-loader-syntax.md
+++ b/docs/rules/no-webpack-loader-syntax.md
@@ -2,12 +2,12 @@
 
 Forbid Webpack loader syntax in imports.
 
-[Webpack](http://webpack.github.io) allows specifying the [loaders](http://webpack.github.io/docs/loaders.html) to use in the import source string using a special syntax like this:
+[Webpack](https://webpack.js.org) allows specifying the [loaders](https://webpack.js.org/concepts/loaders/) to use in the import source string using a special syntax like this:
 ```js
 var moduleWithOneLoader = require("my-loader!./my-awesome-module");
 ```
 
-This syntax is non-standard, so it couples the code to Webpack. The recommended way to specify Webpack loader configuration is in a [Webpack configuration file](http://webpack.github.io/docs/loaders.html#loaders-by-config).
+This syntax is non-standard, so it couples the code to Webpack. The recommended way to specify Webpack loader configuration is in a [Webpack configuration file](https://webpack.js.org/concepts/loaders/#configuration).
 
 ## Rule Details
 

From 515957a25827fd291fe47bb3cc062c3c6ab932b4 Mon Sep 17 00:00:00 2001
From: Benjamin Arbogast <benjamin.arbogast@gmail.com>
Date: Thu, 21 May 2020 18:20:32 +0200
Subject: [PATCH 155/767] [Docs] `no-unused-rules`: Fix docs for unused exports

First change: Change `import * from  'file-c'` to `import * as fileC from  'file-c'`. The former isn't valid javascript, right?

Second change: Remove example 'file-d', I couldn't see a difference from 'file-c'

Third change: Rename 'file-e' to 'file-d'.
---
 CHANGELOG.md                    |  3 +++
 docs/rules/no-unused-modules.md | 14 ++++----------
 2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c76df6a186..e00da9d494 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [readme] Remove duplicate no-unused-modules from docs ([#1690], thanks [@arvigeus])
 - [Docs] `order`: fix bad inline config ([#1788], thanks [@nickofthyme])
 - [Tests] Add fix for Windows Subsystem for Linux ([#1786], thanks [@manuth])
+- [Docs] `no-unused-rules`: Fix docs for unused exports ([#1776], thanks [@barbogast])
 
 ## [2.20.2] - 2020-03-28
 ### Fixed
@@ -687,6 +688,7 @@ for info on changes for earlier releases.
 [#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
 [#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
 [#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
+[#1776]: https://github.com/benmosher/eslint-plugin-import/pull/1776
 [#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
 [#1764]: https://github.com/benmosher/eslint-plugin-import/pull/1764
 [#1763]: https://github.com/benmosher/eslint-plugin-import/pull/1763
@@ -1180,3 +1182,4 @@ for info on changes for earlier releases.
 [@julien1619]: https://github.com/julien1619
 [@darkartur]: https://github.com/darkartur
 [@MikeyBeLike]: https://github.com/MikeyBeLike
+[@barbogast]: https://github.com/barbogast
diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index 4302bc8458..8c234202f8 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -58,28 +58,22 @@ given file-f:
 ```js
 import { e } from 'file-a'
 import { f } from 'file-b'
-import * from  'file-c'
-export * from 'file-d'
-export { default, i0 } from 'file-e' // both will be reported
+import * as fileC from  'file-c'
+export { default, i0 } from 'file-d' // both will be reported
 
 export const j = 99 // will be reported 
 ```
-and file-e:
+and file-d:
 ```js
 export const i0 = 9 // will not be reported
 export const i1 = 9 // will be reported
 export default () => {} // will not be reported
 ```
-and file-d:
+and file-c:
 ```js
 export const h = 8 // will not be reported
 export default () => {} // will be reported, as export * only considers named exports and ignores default exports
 ```
-and file-c:
-```js
-export const g = 7 // will not be reported
-export default () => {} // will not be reported
-```
 and file-b:
 ```js
 import two, { b, c, doAnything } from 'file-a'

From 98292ed262c65116790d9ae5c841b62ba3a02f83 Mon Sep 17 00:00:00 2001
From: Adam Borowski <fl.borovsky@gmail.com>
Date: Sun, 26 Apr 2020 21:44:27 +0200
Subject: [PATCH 156/767] [Refactor] `no-extraneous-dependencies`: use
 moduleVisitor

---
 CHANGELOG.md                            |  3 +++
 src/rules/no-extraneous-dependencies.js | 28 ++++---------------------
 2 files changed, 7 insertions(+), 24 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e00da9d494..dd6471a8d6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: avoid order-dependence ([#1744], thanks [@darkartur])
 
 ### Changed
+- [Refactor] `no-extraneous-dependencies`: use moduleVisitor ([#1735], thanks [@adamborowski])
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
 - [readme] Remove duplicate no-unused-modules from docs ([#1690], thanks [@arvigeus])
 - [Docs] `order`: fix bad inline config ([#1788], thanks [@nickofthyme])
@@ -695,6 +696,7 @@ for info on changes for earlier releases.
 [#1751]: https://github.com/benmosher/eslint-plugin-import/pull/1751
 [#1744]: https://github.com/benmosher/eslint-plugin-import/pull/1744
 [#1736]: https://github.com/benmosher/eslint-plugin-import/pull/1736
+[#1735]: https://github.com/benmosher/eslint-plugin-import/pull/1735
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
@@ -1183,3 +1185,4 @@ for info on changes for earlier releases.
 [@darkartur]: https://github.com/darkartur
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@barbogast]: https://github.com/barbogast
+[@adamborowski]: https://github.com/adamborowski
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 7746f489ec..03c45526c0 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -3,8 +3,8 @@ import fs from 'fs'
 import readPkgUp from 'read-pkg-up'
 import minimatch from 'minimatch'
 import resolve from 'eslint-module-utils/resolve'
+import moduleVisitor from 'eslint-module-utils/moduleVisitor'
 import importType from '../core/importType'
-import isStaticRequire from '../core/staticRequire'
 import docsUrl from '../docsUrl'
 
 function hasKeys(obj = {}) {
@@ -200,28 +200,8 @@ module.exports = {
       allowBundledDeps: testConfig(options.bundledDependencies, filename) !== false,
     }
 
-    // todo: use module visitor from module-utils core
-    return {
-      ImportDeclaration: function (node) {
-        if (node.source) {
-          reportIfMissing(context, deps, depsOptions, node, node.source.value)
-        }
-      },
-      ExportNamedDeclaration: function (node) {
-        if (node.source) {
-          reportIfMissing(context, deps, depsOptions, node, node.source.value)
-        }
-      },
-      ExportAllDeclaration: function (node) {
-        if (node.source) {
-          reportIfMissing(context, deps, depsOptions, node, node.source.value)
-        }
-      },
-      CallExpression: function handleRequires(node) {
-        if (isStaticRequire(node)) {
-          reportIfMissing(context, deps, depsOptions, node, node.arguments[0].value)
-        }
-      },
-    }
+    return moduleVisitor(node => {
+      reportIfMissing(context, deps, depsOptions, node, node.value)
+    }, {commonjs: true})
   },
 }

From 1737429e3b3c91974498fcb49a3e167b9e49b53b Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sat, 30 May 2020 01:48:43 +0200
Subject: [PATCH 157/767] [meta] Make `copy-metafiles` platform-independent

Co-authored-by: Manuel Thalmann <m@nuth.ch>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 .travis.yml                    |  1 +
 package.json                   |  7 +++++--
 scripts/copyMetafiles.js       | 22 ++++++++++++++++++++++
 scripts/resolverDirectories.js |  3 +++
 scripts/testAll.js             | 20 ++++++++++++++++++++
 5 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 scripts/copyMetafiles.js
 create mode 100644 scripts/resolverDirectories.js
 create mode 100644 scripts/testAll.js

diff --git a/.travis.yml b/.travis.yml
index e34ae479a5..fda8f0a5a6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -89,6 +89,7 @@ matrix:
 
 before_install:
   - 'nvm install-latest-npm'
+  - 'npm install'
   - 'npm run copy-metafiles'
   - 'if [ -n "${PACKAGE-}" ]; then cd "${PACKAGE}"; fi'
 install:
diff --git a/package.json b/package.json
index b9faf9e515..a2a680a247 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,7 @@
     "prebuild": "rimraf lib",
     "build": "babel --quiet --out-dir lib src",
     "postbuild": "npm run copy-metafiles",
-    "copy-metafiles": "for DIR in memo-parser resolvers/node resolvers/webpack utils; do cp LICENSE .npmrc \"${DIR}/\"; done",
+    "copy-metafiles": "node --require babel-register ./scripts/copyMetafiles",
     "watch": "npm run tests-only -- -- --watch",
     "pretest": "linklocal",
     "posttest": "eslint .",
@@ -29,7 +29,7 @@
     "tests-only": "npm run mocha tests/src",
     "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
-    "test-all": "npm test && for resolver in ./resolvers/*; do cd $resolver && npm test && cd ../..; done",
+    "test-all": "node --require babel-register ./scripts/testAll",
     "prepublish": "not-in-publish || npm run build",
     "coveralls": "nyc report --reporter lcovonly && cat ./coverage/lcov.info | coveralls"
   },
@@ -77,9 +77,12 @@
     "eslint-module-utils": "file:./utils",
     "eslint-plugin-eslint-plugin": "^2.2.1",
     "eslint-plugin-import": "2.x",
+    "fs-copy-file-sync": "^1.1.1",
+    "glob": "^7.1.6",
     "in-publish": "^2.0.0",
     "linklocal": "^2.8.2",
     "mocha": "^3.5.3",
+    "npm-which": "^3.0.1",
     "nyc": "^11.9.0",
     "redux": "^3.7.2",
     "rimraf": "^2.7.1",
diff --git a/scripts/copyMetafiles.js b/scripts/copyMetafiles.js
new file mode 100644
index 0000000000..441e421e8d
--- /dev/null
+++ b/scripts/copyMetafiles.js
@@ -0,0 +1,22 @@
+import path from 'path'
+import copyFileSync from 'fs-copy-file-sync'
+import resolverDirectories from './resolverDirectories'
+
+let files = [
+    'LICENSE',
+    '.npmrc',
+]
+
+let directories = [
+    'memo-parser',
+    ...resolverDirectories,
+    'utils',
+]
+
+for (let directory of directories) {
+    for (let file of files) {
+        let destination = path.join(directory, file)
+        copyFileSync(file, destination)
+        console.log(`${file} -> ${destination}`)
+    }
+}
diff --git a/scripts/resolverDirectories.js b/scripts/resolverDirectories.js
new file mode 100644
index 0000000000..eea0620d36
--- /dev/null
+++ b/scripts/resolverDirectories.js
@@ -0,0 +1,3 @@
+import glob from 'glob'
+
+export default glob.sync('./resolvers/*/')
diff --git a/scripts/testAll.js b/scripts/testAll.js
new file mode 100644
index 0000000000..358ef3e89e
--- /dev/null
+++ b/scripts/testAll.js
@@ -0,0 +1,20 @@
+import { spawnSync } from 'child_process'
+import npmWhich from 'npm-which'
+import resolverDirectories from './resolverDirectories'
+
+let npmPath = npmWhich(__dirname).sync('npm')
+let spawnOptions = {
+    stdio: 'inherit',
+}
+
+spawnSync(
+    npmPath,
+    ['test'],
+    Object.assign({ cwd: __dirname }, spawnOptions))
+
+for (let resolverDir of resolverDirectories) {
+    spawnSync(
+        npmPath,
+        ['test'],
+        Object.assign({ cwd: resolverDir }, spawnOptions))
+}

From 1760b8954b6549df360ff75e3a2079919ee1c113 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sun, 31 May 2020 14:29:45 +0200
Subject: [PATCH 158/767] [Tests] Add `lodash.isarray` to deps as temporary fix

---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index a2a680a247..4191d11d26 100644
--- a/package.json
+++ b/package.json
@@ -81,6 +81,7 @@
     "glob": "^7.1.6",
     "in-publish": "^2.0.0",
     "linklocal": "^2.8.2",
+    "lodash.isarray": "^4.0.0",
     "mocha": "^3.5.3",
     "npm-which": "^3.0.1",
     "nyc": "^11.9.0",

From 6dd28ea6221a6c0aa5a810ba7bf37f128b2a9071 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sun, 31 May 2020 17:40:03 +0200
Subject: [PATCH 159/767] [Tests] fix coverage script for windows; tweak
 appveyor

---
 appveyor.yml | 23 +++++++++++++++++++++--
 package.json |  2 +-
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/appveyor.yml b/appveyor.yml
index 3981e91b47..eb2119a231 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -39,13 +39,18 @@ for:
     # install modules
     - ps: >-
         if ($env:nodejs_version -eq "4") {
-          npm install -g npm@3;
+          cmd /c npm install -g npm@3;
         }
         if ($env:nodejs_version -in @("8", "10", "12")) {
-          npm install -g npm@6.10.3;
+          cmd /c npm install -g npm@6.14.5;
         }
     - npm install
 
+    - ps: >-
+        if ([int]$env:nodejs_version -le 8) {
+          cmd /c npm i eslint@6 2`>`&1;
+        }
+
     # fix symlinks
     - git config core.symlinks true
     - git reset --hard
@@ -54,6 +59,20 @@ for:
     - cd .\resolvers\webpack && npm install && cd ..\..
     - cd .\resolvers\node && npm install && cd ..\..
 
+    # Upgrade nyc
+    - npm i --no-save nyc@15.0.1
+    - ps: >-
+        $resolverDir = "./resolvers";
+        Get-ChildItem -Directory $resolverDir |
+        ForEach-Object {
+          Push-Location $(Resolve-Path $(Join-Path $resolverDir $_));
+          cmd /c npm ls nyc 2`>`&1;
+          if ($?) {
+            cmd /c npm i --no-save nyc@15.0.1 2`>`&1;
+          }
+          Pop-Location;
+        }
+
   # Post-install test scripts.
   test_script:
 
diff --git a/package.json b/package.json
index 4191d11d26..0673205f3b 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
     "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
     "test-all": "node --require babel-register ./scripts/testAll",
     "prepublish": "not-in-publish || npm run build",
-    "coveralls": "nyc report --reporter lcovonly && cat ./coverage/lcov.info | coveralls"
+    "coveralls": "nyc report --reporter lcovonly && coveralls < ./coverage/lcov.info"
   },
   "repository": {
     "type": "git",

From 9dfef28e701c12c91e74249abfb6db655c84a3f6 Mon Sep 17 00:00:00 2001
From: Alexandre Djerbetian <alexandre.djerbetian@360learning.com>
Date: Sun, 22 Mar 2020 11:12:21 +0100
Subject: [PATCH 160/767] [Fix] `no-internal-modules`: also check `export from`
 syntax

Fixes #1481.
---
 CHANGELOG.md                                  |   3 +
 docs/rules/no-internal-modules.md             |   6 +
 src/rules/no-internal-modules.js              |   6 +
 .../typescript/plugin2/app/index.ts           |   0
 .../typescript/plugin2/index.ts               |   0
 .../typescript/plugin2/internal.ts            |   0
 .../internal-modules/typescript/plugins.ts    |   0
 tests/src/rules/no-internal-modules.js        | 103 ++++++++++++++++++
 8 files changed, 118 insertions(+)
 create mode 100644 tests/files/internal-modules/typescript/plugin2/app/index.ts
 create mode 100644 tests/files/internal-modules/typescript/plugin2/index.ts
 create mode 100644 tests/files/internal-modules/typescript/plugin2/internal.ts
 create mode 100644 tests/files/internal-modules/typescript/plugins.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dd6471a8d6..ffc185b037 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - TypeScript: Add nested namespace handling ([#1763], thanks [@julien1619])
 - [`namespace`]/`ExportMap`: Fix interface declarations for TypeScript ([#1764], thanks [@julien1619])
 - [`no-unused-modules`]: avoid order-dependence ([#1744], thanks [@darkartur])
+- [`no-internal-modules`]: also check `export from` syntax ([#1691], thanks [@adjerbetian])
 
 ### Changed
 - [Refactor] `no-extraneous-dependencies`: use moduleVisitor ([#1735], thanks [@adamborowski])
@@ -702,6 +703,7 @@ for info on changes for earlier releases.
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
 [#1719]: https://github.com/benmosher/eslint-plugin-import/pull/1719
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
+[#1691]: https://github.com/benmosher/eslint-plugin-import/pull/1691
 [#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
 [#1681]: https://github.com/benmosher/eslint-plugin-import/pull/1681
 [#1676]: https://github.com/benmosher/eslint-plugin-import/pull/1676
@@ -1186,3 +1188,4 @@ for info on changes for earlier releases.
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@barbogast]: https://github.com/barbogast
 [@adamborowski]: https://github.com/adamborowski
+[@adjerbetian]: https://github.com/adjerbetian
diff --git a/docs/rules/no-internal-modules.md b/docs/rules/no-internal-modules.md
index 8d99c35299..7bbb2edd16 100644
--- a/docs/rules/no-internal-modules.md
+++ b/docs/rules/no-internal-modules.md
@@ -49,6 +49,9 @@ The following patterns are considered problems:
 import { settings } from './app/index'; // Reaching to "./app/index" is not allowed
 import userReducer from './reducer/user'; // Reaching to "./reducer/user" is not allowed
 import configureStore from './redux/configureStore'; // Reaching to "./redux/configureStore" is not allowed
+
+export { settings } from './app/index'; // Reaching to "./app/index" is not allowed
+export * from './reducer/user'; // Reaching to "./reducer/user" is not allowed
 ```
 
 The following patterns are NOT considered problems:
@@ -61,4 +64,7 @@ The following patterns are NOT considered problems:
 import 'source-map-support/register';
 import { settings } from '../app';
 import getUser from '../actions/getUser';
+
+export * from 'source-map-support/register';
+export { settings } from '../app';
 ```
diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index 9987dfd5c5..b5d7496a2a 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -91,6 +91,12 @@ module.exports = {
       ImportDeclaration(node) {
         checkImportForReaching(node.source.value, node.source)
       },
+      ExportAllDeclaration(node) {
+        checkImportForReaching(node.source.value, node.source)
+      },
+      ExportNamedDeclaration(node) {
+        checkImportForReaching(node.source.value, node.source)
+      },
       CallExpression(node) {
         if (isStaticRequire(node)) {
           const [ firstArgument ] = node.arguments
diff --git a/tests/files/internal-modules/typescript/plugin2/app/index.ts b/tests/files/internal-modules/typescript/plugin2/app/index.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/internal-modules/typescript/plugin2/index.ts b/tests/files/internal-modules/typescript/plugin2/index.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/internal-modules/typescript/plugin2/internal.ts b/tests/files/internal-modules/typescript/plugin2/internal.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/internal-modules/typescript/plugins.ts b/tests/files/internal-modules/typescript/plugins.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js
index 8ed1c623e5..5058fcb349 100644
--- a/tests/src/rules/no-internal-modules.js
+++ b/tests/src/rules/no-internal-modules.js
@@ -7,6 +7,7 @@ const ruleTester = new RuleTester()
 
 ruleTester.run('no-internal-modules', rule, {
   valid: [
+    // imports
     test({
       code: 'import a from "./plugin2"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
@@ -57,9 +58,44 @@ ruleTester.run('no-internal-modules', rule, {
         allow: [ '**/index{.js,}' ],
       } ],
     }),
+    // exports
+    test({
+      code: 'export {a} from "./internal.js"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/index.js'),
+    }),
+    test({
+      code: 'export * from "lodash.get"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/index.js'),
+    }),
+    test({
+      code: 'export {b} from "@org/package"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+    }),
+    test({
+      code: 'export {b} from "../../api/service"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        allow: [ '**/api/*' ],
+      } ],
+    }),
+    test({
+      code: 'export * from "jquery/dist/jquery"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        allow: [ 'jquery/dist/*' ],
+      } ],
+    }),
+    test({
+      code: 'export * from "./app/index.js";\nexport * from "./app/index"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        allow: [ '**/index{.js,}' ],
+      } ],
+    }),
   ],
 
   invalid: [
+    // imports
     test({
       code: 'import "./plugin2/index.js";\nimport "./plugin2/app/index"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
@@ -126,5 +162,72 @@ ruleTester.run('no-internal-modules', rule, {
         },
       ],
     }),
+    // exports
+    test({
+      code: 'export * from "./plugin2/index.js";\nexport * from "./plugin2/app/index"',
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      options: [ {
+        allow: [ '*/index.js' ],
+      } ],
+      errors: [ {
+        message: 'Reaching to "./plugin2/app/index" is not allowed.',
+        line: 2,
+        column: 15,
+      } ],
+    }),
+    test({
+      code: 'export * from "./app/index.js"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      errors: [ {
+        message: 'Reaching to "./app/index.js" is not allowed.',
+        line: 1,
+        column: 15,
+      } ],
+    }),
+    test({
+      code: 'export {b} from "./plugin2/internal"',
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      errors: [ {
+        message: 'Reaching to "./plugin2/internal" is not allowed.',
+        line: 1,
+        column: 17,
+      } ],
+    }),
+    test({
+      code: 'export {a} from "../api/service/index"',
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      options: [ {
+        allow: [ '**/internal-modules/*' ],
+      } ],
+      errors: [
+        {
+          message: 'Reaching to "../api/service/index" is not allowed.',
+          line: 1,
+          column: 17,
+        },
+      ],
+    }),
+    test({
+      code: 'export {b} from "@org/package/internal"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      errors: [
+        {
+          message: 'Reaching to "@org/package/internal" is not allowed.',
+          line: 1,
+          column: 17,
+        },
+      ],
+    }),
+    test({
+      code: 'export {get} from "debug/node"',
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      errors: [
+        {
+          message: 'Reaching to "debug/node" is not allowed.',
+          line: 1,
+          column: 19,
+        },
+      ],
+    }),
   ],
 })

From e1ed323e070216032fadd1c66eefe32c7a845052 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sun, 31 May 2020 22:46:00 +0200
Subject: [PATCH 161/767] [Tests] Improve AppVeyor Configuration

---
 appveyor.yml             | 225 +++++++++++++++++++--------------------
 scripts/GetCI/GetCI.psm1 |  12 +++
 scripts/ci.cmd           |   8 ++
 3 files changed, 130 insertions(+), 115 deletions(-)
 create mode 100644 scripts/GetCI/GetCI.psm1
 create mode 100644 scripts/ci.cmd

diff --git a/appveyor.yml b/appveyor.yml
index eb2119a231..b79315b7be 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,10 +5,10 @@ configuration:
 # Test against this version of Node.js
 environment:
   matrix:
-  - nodejs_version: "14"
-  - nodejs_version: "12"
-  - nodejs_version: "10"
-  - nodejs_version: "8"
+    - nodejs_version: "14"
+    - nodejs_version: "12"
+    - nodejs_version: "10"
+    - nodejs_version: "8"
   # - nodejs_version: "6"
   # - nodejs_version: "4"
 
@@ -26,118 +26,113 @@ matrix:
 #   - x86
 #   - x64
 
-for:
--
-  matrix:
-    only:
-      - configuration: Native
-  # Install scripts. (runs after repo cloning)
-  install:
-    # Get the latest stable version of Node.js or io.js
-    - ps: Install-Product node $env:nodejs_version
-
-    # install modules
-    - ps: >-
-        if ($env:nodejs_version -eq "4") {
-          cmd /c npm install -g npm@3;
-        }
-        if ($env:nodejs_version -in @("8", "10", "12")) {
-          cmd /c npm install -g npm@6.14.5;
+# Initialization scripts. (runs before repo cloning)
+init:
+  # Declare version-numbers of packages to install
+  - ps: >-
+      if ($env:nodejs_version -eq "4") {
+        $env:NPM_VERSION="3"
+      }
+      if ($env:nodejs_version -in @("8", "10", "12")) {
+        $env:NPM_VERSION="6.14.5"
+      }
+  - ps: >-
+      if ([int]$env:nodejs_version -le 8) {
+        $env:ESLINT_VERSION="6"
+      }
+  - ps: $env:WINDOWS_NYC_VERSION = "15.0.1"
+
+  # Add `ci`-command to `PATH` for running commands either using cmd or wsl depending on the configuration
+  - ps: $env:PATH += ";$(Join-Path $(pwd) "scripts")"
+
+# Install scripts. (runs after repo cloning)
+before_build:
+  # Install propert `npm`-version
+  - IF DEFINED NPM_VERSION ci sudo npm install -g npm@%NPM_VERSION%
+
+  # Install dependencies
+  - ci npm install
+
+  # fix symlinks
+  - git config core.symlinks true
+  - git reset --hard
+  - ci git reset --hard
+
+  # Install dependencies of resolvers
+  - ps: >-
+      $resolverDir = "./resolvers";
+      $resolvers = @();
+      Get-ChildItem -Directory $resolverDir |
+        ForEach {
+          $resolvers += "$(Resolve-Path $(Join-Path $resolverDir $_))";
         }
-    - npm install
-
-    - ps: >-
-        if ([int]$env:nodejs_version -le 8) {
-          cmd /c npm i eslint@6 2`>`&1;
-        }
-
-    # fix symlinks
-    - git config core.symlinks true
-    - git reset --hard
-
-    # todo: learn how to do this for all .\resolvers\* on Windows
-    - cd .\resolvers\webpack && npm install && cd ..\..
-    - cd .\resolvers\node && npm install && cd ..\..
-
-    # Upgrade nyc
-    - npm i --no-save nyc@15.0.1
-    - ps: >-
-        $resolverDir = "./resolvers";
-        Get-ChildItem -Directory $resolverDir |
-        ForEach-Object {
-          Push-Location $(Resolve-Path $(Join-Path $resolverDir $_));
-          cmd /c npm ls nyc 2`>`&1;
-          if ($?) {
-            cmd /c npm i --no-save nyc@15.0.1 2`>`&1;
-          }
-          Pop-Location;
+      $env:RESOLVERS = [string]::Join(";", $resolvers);
+  - FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm install & popd )
+
+  # Install proper `eslint`-version
+  - IF DEFINED ESLINT_VERSION ci npm install --no-save eslint@%ESLINT_VERSION%
+
+# Build scripts (project isn't actually built)
+build_script:
+  - ps: "# This Project isn't actually built"
+
+# Test scripts
+test_script:
+  # Output useful info for debugging.
+  - ci node --version
+  - ci npm --version
+
+  # Run core tests
+  - ci npm run pretest
+  - ci npm run tests-only
+
+  # Run resolver tests
+  - ps: >-
+      $resolverDir = "./resolvers";
+      $resolvers = @();
+      Get-ChildItem -Directory $resolverDir |
+        ForEach {
+          $resolvers += "$(Resolve-Path $(Join-Path $resolverDir $_))";
         }
+      $env:RESOLVERS = [string]::Join(";", $resolvers);
+  - FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm test & popd )
 
-  # Post-install test scripts.
-  test_script:
+on_success:
+  - ci npm run coveralls
 
-    # Output useful info for debugging.
-    - node --version
-    - npm --version
-
-    # core tests
-    - npm run pretest
-    - npm run tests-only
-
-    # resolver tests
-    - cd .\resolvers\webpack && npm test && cd ..\..
-    - cd .\resolvers\node && npm test && cd ..\..
-
-  on_success:
-    - npm run coveralls
--
-  matrix:
-    only:
-      - configuration: WSL
-  # Install scripts. (runs after repo cloning)
-  install:
-    # Get the latest stable version of Node.js or io.js
-    - ps: $env:WSLENV += ":nodejs_version"
-    - ps: wsl curl -sL 'https://deb.nodesource.com/setup_${nodejs_version}.x' `| sudo APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 -E bash -
-    - wsl sudo DEBIAN_FRONTEND=noninteractive apt install -y nodejs
-
-    # install modules
-    - ps: >-
-        if ($env:nodejs_version -eq "4") {
-          wsl sudo npm install -g npm@3;
-        }
-        if ($env:nodejs_version -in @("8", "10", "12")) {
-          wsl sudo npm install -g npm@6.10.3;
-        }
-    - wsl npm install
-
-    # fix symlinks
-    - git config core.symlinks true
-    - git reset --hard
-    # reset new-line characters
-    - wsl git reset --hard
-
-    # todo: learn how to do this for all .\resolvers\* on Windows
-    - cd .\resolvers\webpack && wsl npm install && cd ..\..
-    - cd .\resolvers\node && wsl npm install && cd ..\..
-
-  # Post-install test scripts.
-  test_script:
-
-    # Output useful info for debugging.
-    - wsl node --version
-    - wsl npm --version
-
-    # core tests
-    - wsl npm run pretest
-    - wsl npm run tests-only
-
-    # resolver tests
-    - cd .\resolvers\webpack && wsl npm test && cd ..\..
-    - cd .\resolvers\node && wsl npm test && cd ..\..
-
-  on_success:
-    - wsl npm run coveralls
-
-# Don't actually build.
-build: off
+# Configuration-specific steps
+for:
+  - matrix:
+      except:
+        - configuration: WSL
+    install:
+      # Get the latest stable version of Node.js or io.js
+      - ps: Install-Product node $env:nodejs_version
+    before_test:
+      # Upgrade nyc
+      - ci npm i --no-save nyc@%WINDOWS_NYC_VERSION%
+      - ps: >-
+          $resolverDir = "./resolvers";
+          $resolvers = @();
+          Get-ChildItem -Directory $resolverDir |
+            ForEach {
+              Push-Location $(Resolve-Path $(Join-Path $resolverDir $_));
+              ci npm ls nyc > $null;
+              if ($?) {
+                $resolvers += "$(pwd)";
+              }
+              Pop-Location;
+            }
+          $env:RESOLVERS = [string]::Join(";", $resolvers);
+      - IF DEFINED RESOLVERS FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm install --no-save nyc@%WINDOWS_NYC_VERSION% & popd )
+  - matrix:
+      only:
+        - configuration: WSL
+    # Install scripts. (runs after repo cloning)
+    install:
+      # Get a specific version of Node.js
+      - ps: $env:WSLENV += ":nodejs_version"
+      - ps: wsl curl -sL 'https://deb.nodesource.com/setup_${nodejs_version}.x' `| sudo APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 -E bash -
+      - wsl sudo DEBIAN_FRONTEND=noninteractive apt install -y nodejs
+
+build: on
diff --git a/scripts/GetCI/GetCI.psm1 b/scripts/GetCI/GetCI.psm1
new file mode 100644
index 0000000000..818ce32fef
--- /dev/null
+++ b/scripts/GetCI/GetCI.psm1
@@ -0,0 +1,12 @@
+function Get-CICommand {
+    $arguments = [System.Collections.ArrayList]$args
+    if ($env:CONFIGURATION -eq "WSL") {
+        $arguments.Insert(0, "wsl");
+    } else {
+        if ($arguments[0] -eq "sudo") {
+        $arguments.RemoveAt(0)
+        }
+    }
+    $arguments.Insert(0, "echo");
+    cmd /c $arguments[0] $arguments[1..$($arguments.Count - 1)];
+}
diff --git a/scripts/ci.cmd b/scripts/ci.cmd
new file mode 100644
index 0000000000..04ac20265b
--- /dev/null
+++ b/scripts/ci.cmd
@@ -0,0 +1,8 @@
+@echo off
+
+FOR /F "tokens=* usebackq" %%F IN (`powershell -Command "& { Import-Module %~dp0GetCI; Get-CICommand %* }"`) DO (
+    SET args=%%F
+)
+
+echo ^> cmd /c %args%
+cmd /c %args%

From 0547c7efa0a1becd2cdf35ae03f6fe74472398d9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 5 Jun 2020 15:06:15 -0700
Subject: [PATCH 162/767] [Tests] add test case for #1645

---
 .eslintignore                              |  1 +
 package.json                               |  1 +
 tests/files/just-json-files/.eslintrc.json | 22 +++++++++
 tests/files/just-json-files/invalid.json   |  1 +
 tests/src/cli.js                           | 55 ++++++++++++++++++++++
 5 files changed, 80 insertions(+)
 create mode 100644 tests/files/just-json-files/.eslintrc.json
 create mode 100644 tests/files/just-json-files/invalid.json

diff --git a/.eslintignore b/.eslintignore
index 93daf655e5..b260021d40 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -4,6 +4,7 @@ coverage
 node_modules
 tests/files/malformed.js
 tests/files/with-syntax-error
+tests/files/just-json-files/invalid.json
 resolvers/webpack/test/files
 # we want to ignore "tests/files" here, but unfortunately doing so would
 # interfere with unit test and fail it for some reason.
diff --git a/package.json b/package.json
index 0673205f3b..6d3d512d2e 100644
--- a/package.json
+++ b/package.json
@@ -77,6 +77,7 @@
     "eslint-module-utils": "file:./utils",
     "eslint-plugin-eslint-plugin": "^2.2.1",
     "eslint-plugin-import": "2.x",
+    "eslint-plugin-json": "^2.1.1",
     "fs-copy-file-sync": "^1.1.1",
     "glob": "^7.1.6",
     "in-publish": "^2.0.0",
diff --git a/tests/files/just-json-files/.eslintrc.json b/tests/files/just-json-files/.eslintrc.json
new file mode 100644
index 0000000000..4fbf13a727
--- /dev/null
+++ b/tests/files/just-json-files/.eslintrc.json
@@ -0,0 +1,22 @@
+{
+  "root": true,
+
+  "plugins": ["import", "json"],
+
+  "rules": {
+    "import/no-unused-modules": [
+      "error",
+      {
+        "missingExports": false,
+        "unusedExports": true
+      }
+    ]
+  },
+
+  "overrides": [
+    {
+      "files": "*.json",
+      "extends": "plugin:json/recommended"
+    }
+  ]
+}
diff --git a/tests/files/just-json-files/invalid.json b/tests/files/just-json-files/invalid.json
new file mode 100644
index 0000000000..7edb2fa5bc
--- /dev/null
+++ b/tests/files/just-json-files/invalid.json
@@ -0,0 +1 @@
+,
diff --git a/tests/src/cli.js b/tests/src/cli.js
index 93a4d43d79..53d6e8fdc9 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -1,8 +1,12 @@
 /**
  * tests that require fully booting up ESLint
  */
+import path from 'path'
+
 import { expect } from 'chai'
 import { CLIEngine } from 'eslint'
+import eslintPkg from 'eslint/package.json'
+import semver from 'semver'
 
 describe('CLI regression tests', function () {
   describe('issue #210', function () {
@@ -21,4 +25,55 @@ describe('CLI regression tests', function () {
       expect(() => cli.executeOnFiles(['./tests/files/issue210.js'])).not.to.throw(Error)
     })
   })
+
+  describe('issue #1645', function () {
+    let cli
+    beforeEach(function () {
+      if (semver.satisfies(eslintPkg.version, '< 6')) {
+        this.skip()
+      } else {
+        cli = new CLIEngine({
+          useEslintrc: false,
+          configFile: './tests/files/just-json-files/.eslintrc.json',
+          rulePaths: ['./src/rules'],
+          ignore: false,
+        })
+      }
+    })
+
+    it('throws an error on invalid JSON', function () {
+      const invalidJSON = './tests/files/just-json-files/invalid.json'
+      const results = cli.executeOnFiles([invalidJSON])
+      expect(results).to.eql({
+        results: [
+          {
+            filePath: path.resolve(invalidJSON),
+            messages: [
+              {
+                column: 2,
+                endColumn: 3,
+                endLine: 1,
+                line: 1,
+                message: 'Expected a JSON object, array or literal.',
+                nodeType: results.results[0].messages[0].nodeType, // we don't care about this one
+                ruleId: 'json/*',
+                severity: 2,
+                source: '\n',
+              },
+            ],
+            errorCount: 1,
+            warningCount: 0,
+            fixableErrorCount: 0,
+            fixableWarningCount: 0,
+            source: ',\n',
+          },
+        ],
+        errorCount: 1,
+        warningCount: 0,
+        fixableErrorCount: 0,
+        fixableWarningCount: 0,
+        usedDeprecatedRules: results.usedDeprecatedRules, // we don't care about this one
+      })
+    })
+  })
 })

From 0b585a14d605eb059050bb07ab3c2a2abf3961a6 Mon Sep 17 00:00:00 2001
From: Maxim Mazurok <maxim@mazurok.com>
Date: Thu, 19 Mar 2020 17:46:19 +1100
Subject: [PATCH 163/767] [New] `import/default`: support default export in
 TSExportAssignment

---
 CHANGELOG.md                                  |  3 ++
 package.json                                  |  3 +-
 src/ExportMap.js                              | 45 ++++++++++++++-----
 .../index.d.ts                                |  3 ++
 .../tsconfig.json                             |  5 +++
 .../index.d.ts                                |  3 ++
 .../tsconfig.json                             |  5 +++
 tests/src/rules/default.js                    | 41 +++++++++++++++++
 8 files changed, 97 insertions(+), 11 deletions(-)
 create mode 100644 tests/files/typescript-export-as-default-namespace/index.d.ts
 create mode 100644 tests/files/typescript-export-as-default-namespace/tsconfig.json
 create mode 100644 tests/files/typescript-export-assign-default-namespace/index.d.ts
 create mode 100644 tests/files/typescript-export-assign-default-namespace/tsconfig.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ffc185b037..88a32dade4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])
 - [`no-cycle`]: add `ignoreExternal` option ([#1681], thanks [@sveyret])
 - [`order`]: Add support for TypeScript's "import equals"-expressions ([#1785], thanks [@manuth])
+- [`import/default`]: support default export in TSExportAssignment ([#1689], thanks [@Maxim-Mazurok])
 
 ### Fixed
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
@@ -705,6 +706,7 @@ for info on changes for earlier releases.
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
 [#1691]: https://github.com/benmosher/eslint-plugin-import/pull/1691
 [#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
+[#1689]: https://github.com/benmosher/eslint-plugin-import/pull/1689
 [#1681]: https://github.com/benmosher/eslint-plugin-import/pull/1681
 [#1676]: https://github.com/benmosher/eslint-plugin-import/pull/1676
 [#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
@@ -1189,3 +1191,4 @@ for info on changes for earlier releases.
 [@barbogast]: https://github.com/barbogast
 [@adamborowski]: https://github.com/adamborowski
 [@adjerbetian]: https://github.com/adjerbetian
+[@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
diff --git a/package.json b/package.json
index 6d3d512d2e..da8f028162 100644
--- a/package.json
+++ b/package.json
@@ -108,7 +108,8 @@
     "minimatch": "^3.0.4",
     "object.values": "^1.1.0",
     "read-pkg-up": "^2.0.0",
-    "resolve": "^1.12.0"
+    "resolve": "^1.12.0",
+    "tsconfig-paths": "^3.9.0"
   },
   "nyc": {
     "require": [
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 56f9f58b57..d72952ef4c 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -13,6 +13,12 @@ import isIgnored, { hasValidExtension } from 'eslint-module-utils/ignore'
 import { hashObject } from 'eslint-module-utils/hash'
 import * as unambiguous from 'eslint-module-utils/unambiguous'
 
+import { tsConfigLoader } from 'tsconfig-paths/lib/tsconfig-loader'
+
+import includes from 'array-includes'
+
+import {parseConfigFileTextToJson} from 'typescript'
+
 const log = debug('eslint-plugin-import:ExportMap')
 
 const exportCache = new Map()
@@ -445,8 +451,23 @@ ExportMap.parse = function (path, content, context) {
 
   const source = makeSourceCode(content, ast)
 
-  ast.body.forEach(function (n) {
+  function isEsModuleInterop() {
+    const tsConfigInfo = tsConfigLoader({
+      cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
+      getEnv: (key) => process.env[key],
+    })
+    try {
+      if (tsConfigInfo.tsConfigPath !== undefined) {
+        const jsonText = fs.readFileSync(tsConfigInfo.tsConfigPath).toString()
+        const tsConfig = parseConfigFileTextToJson(tsConfigInfo.tsConfigPath, jsonText).config
+        return tsConfig.compilerOptions.esModuleInterop
+      }
+    } catch (e) {
+      return false
+    }
+  }
 
+  ast.body.forEach(function (n) {
     if (n.type === 'ExportDefaultDeclaration') {
       const exportMeta = captureDoc(source, docStyleParsers, n)
       if (n.declaration.type === 'Identifier') {
@@ -528,9 +549,14 @@ ExportMap.parse = function (path, content, context) {
       })
     }
 
+    const isEsModuleInteropTrue = isEsModuleInterop()
+
+    const exports = ['TSExportAssignment']
+    isEsModuleInteropTrue && exports.push('TSNamespaceExportDeclaration')
+
     // This doesn't declare anything, but changes what's being exported.
-    if (n.type === 'TSExportAssignment') {
-      const exportedName = n.expression.name
+    if (includes(exports, n.type)) {
+      const exportedName = n.expression && n.expression.name || n.id.name
       const declTypes = [
         'VariableDeclaration',
         'ClassDeclaration',
@@ -541,18 +567,17 @@ ExportMap.parse = function (path, content, context) {
         'TSAbstractClassDeclaration',
         'TSModuleDeclaration',
       ]
-      const exportedDecls = ast.body.filter(({ type, id, declarations }) => 
-        declTypes.includes(type) && 
-        (
-          (id && id.name === exportedName) ||
-          (declarations && declarations.find(d => d.id.name === exportedName))
-        )
-      )
+      const exportedDecls = ast.body.filter(({ type, id, declarations }) => includes(declTypes, type) && (
+        (id && id.name === exportedName) || (declarations && declarations.find((d) => d.id.name === exportedName))
+      ))
       if (exportedDecls.length === 0) {
         // Export is not referencing any local declaration, must be re-exporting
         m.namespace.set('default', captureDoc(source, docStyleParsers, n))
         return
       }
+      if (isEsModuleInteropTrue) {
+        m.namespace.set('default', {})
+      }
       exportedDecls.forEach((decl) => {
         if (decl.type === 'TSModuleDeclaration') {
           if (decl.body && decl.body.type === 'TSModuleDeclaration') {
diff --git a/tests/files/typescript-export-as-default-namespace/index.d.ts b/tests/files/typescript-export-as-default-namespace/index.d.ts
new file mode 100644
index 0000000000..953c3410b1
--- /dev/null
+++ b/tests/files/typescript-export-as-default-namespace/index.d.ts
@@ -0,0 +1,3 @@
+export as namespace Foo
+
+export function bar(): void
diff --git a/tests/files/typescript-export-as-default-namespace/tsconfig.json b/tests/files/typescript-export-as-default-namespace/tsconfig.json
new file mode 100644
index 0000000000..a72ee3e88b
--- /dev/null
+++ b/tests/files/typescript-export-as-default-namespace/tsconfig.json
@@ -0,0 +1,5 @@
+{
+    "compilerOptions": {
+        "esModuleInterop": true
+    }
+}
diff --git a/tests/files/typescript-export-assign-default-namespace/index.d.ts b/tests/files/typescript-export-assign-default-namespace/index.d.ts
new file mode 100644
index 0000000000..2ad4822f7c
--- /dev/null
+++ b/tests/files/typescript-export-assign-default-namespace/index.d.ts
@@ -0,0 +1,3 @@
+export = FooBar;
+
+declare namespace FooBar {}
diff --git a/tests/files/typescript-export-assign-default-namespace/tsconfig.json b/tests/files/typescript-export-assign-default-namespace/tsconfig.json
new file mode 100644
index 0000000000..a72ee3e88b
--- /dev/null
+++ b/tests/files/typescript-export-assign-default-namespace/tsconfig.json
@@ -0,0 +1,5 @@
+{
+    "compilerOptions": {
+        "esModuleInterop": true
+    }
+}
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index 79d03e6c55..d3d4aae4a7 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -1,3 +1,4 @@
+import path from 'path'
 import { test, SYNTAX_CASES, getTSParsers } from '../utils'
 import { RuleTester } from 'eslint'
 
@@ -189,6 +190,28 @@ context('TypeScript', function () {
               'import/resolver': { 'eslint-import-resolver-typescript': true },
             },
           }),
+          test({
+            code: `import React from "./typescript-export-assign-default-namespace"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+            parserOptions: {
+              tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-assign-default-namespace/'),
+            },
+          }),
+          test({
+            code: `import Foo from "./typescript-export-as-default-namespace"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+            parserOptions: {
+              tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-as-default-namespace/'),
+            },
+          }),
         ],
 
         invalid: [
@@ -201,6 +224,24 @@ context('TypeScript', function () {
             },
             errors: ['No default export found in imported module "./typescript".'],
           }),
+          test({
+            code: `import React from "./typescript-export-assign-default-namespace"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+            errors: ['No default export found in imported module "./typescript-export-assign-default-namespace".'],
+          }),
+          test({
+            code: `import FooBar from "./typescript-export-as-default-namespace"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+            errors: ['No default export found in imported module "./typescript-export-as-default-namespace".'],
+          }),
         ],
       })
     })

From 0b81052dbe7b0f14d9cebd586afcf30f3b6d55a2 Mon Sep 17 00:00:00 2001
From: Vasily Malykhin <malykhinvi@gmail.com>
Date: Sat, 6 Jun 2020 08:59:23 +0300
Subject: [PATCH 164/767] [New] `no-restricted-paths`: Add custom message
 support

---
 CHANGELOG.md                           |  3 +++
 docs/rules/no-restricted-paths.md      |  1 +
 src/rules/no-restricted-paths.js       |  3 ++-
 tests/src/rules/no-restricted-paths.js | 17 +++++++++++++++++
 4 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88a32dade4..9b4cb56088 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-cycle`]: add `ignoreExternal` option ([#1681], thanks [@sveyret])
 - [`order`]: Add support for TypeScript's "import equals"-expressions ([#1785], thanks [@manuth])
 - [`import/default`]: support default export in TSExportAssignment ([#1689], thanks [@Maxim-Mazurok])
+- [`no-restricted-paths`]: add custom message support ([#1802], thanks [@malykhinvi])
 
 ### Fixed
 - [`group-exports`]: Flow type export awareness ([#1702], thanks [@ernestostifano])
@@ -688,6 +689,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1802]: https://github.com/benmosher/eslint-plugin-import/pull/1802
 [#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
 [#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
 [#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
@@ -1192,3 +1194,4 @@ for info on changes for earlier releases.
 [@adamborowski]: https://github.com/adamborowski
 [@adjerbetian]: https://github.com/adjerbetian
 [@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
+[@malykhinvi]: https://github.com/malykhinvi
diff --git a/docs/rules/no-restricted-paths.md b/docs/rules/no-restricted-paths.md
index 3776699836..bfcb9af237 100644
--- a/docs/rules/no-restricted-paths.md
+++ b/docs/rules/no-restricted-paths.md
@@ -10,6 +10,7 @@ In order to prevent such scenarios this rule allows you to define restricted zon
 This rule has one option. The option is an object containing the definition of all restricted `zones` and the optional `basePath` which is used to resolve relative paths within.
 The default value for `basePath` is the current working directory.
 Each zone consists of the `target` path and a `from` path. The `target` is the path where the restricted imports should be applied. The `from` path defines the folder that is not allowed to be used in an import. An optional `except` may be defined for a zone, allowing exception paths that would otherwise violate the related `from`. Note that `except` is relative to `from` and cannot backtrack to a parent directory.
+You may also specify an optional `message` for a zone, which will be displayed in case of the rule violation.
 
 ### Examples
 
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 221457b1c9..a94b11ec16 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -32,6 +32,7 @@ module.exports = {
                   },
                   uniqueItems: true,
                 },
+                message: { type: 'string' },
               },
               additionalProperties: false,
             },
@@ -102,7 +103,7 @@ module.exports = {
 
           context.report({
             node,
-            message: `Unexpected path "{{importPath}}" imported in restricted zone.`,
+            message: `Unexpected path "{{importPath}}" imported in restricted zone.${zone.message ? ` ${zone.message}` : ''}`,
             data: { importPath },
           })
         })
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index 1c3edb3dae..bd5ab29314 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -145,6 +145,23 @@ ruleTester.run('no-restricted-paths', rule, {
         column: 15,
       } ],
     }),
+    test({
+      code: 'import b from "../two/a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [ {
+        zones: [ {
+          target: './tests/files/restricted-paths/server/one',
+          from: './tests/files/restricted-paths/server',
+          except: ['./one'],
+          message: 'Custom message',
+        } ],
+      } ],
+      errors: [ {
+        message: 'Unexpected path "../two/a.js" imported in restricted zone. Custom message',
+        line: 1,
+        column: 15,
+      } ],
+    }),
     test({
       code: 'import b from "../two/a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),

From 0d6d12e4f8a7037080315f0e6c5ea63f706867da Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 6 Jun 2020 23:29:14 -0700
Subject: [PATCH 165/767] [Tests] add test for `export *` from a d.ts file

Closes #1801
---
 tests/src/rules/namespace.js | 52 ++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 20 deletions(-)

diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index ba8c9145d3..5627c7132a 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -1,5 +1,6 @@
 import { test, SYNTAX_CASES, getTSParsers } from '../utils'
 import { RuleTester } from 'eslint'
+import flatMap from 'array.prototype.flatmap'
 
 var ruleTester = new RuleTester({ env: { es6: true }})
   , rule = require('rules/namespace')
@@ -121,26 +122,37 @@ const valid = [
   }),
 
   // Typescript
-  ...getTSParsers().map((parser) => test({
-    code: `
-      import * as foo from "./typescript-declare-nested"
-      foo.bar.MyFunction()
-    `,
-    parser: parser,
-    settings: {
-      'import/parsers': { [parser]: ['.ts'] },
-      'import/resolver': { 'eslint-import-resolver-typescript': true },
-    },
-  })),
-
-  ...getTSParsers().map((parser) => test({
-    code: `import { foobar } from "./typescript-declare-interface"`,
-    parser: parser,
-    settings: {
-      'import/parsers': { [parser]: ['.ts'] },
-      'import/resolver': { 'eslint-import-resolver-typescript': true },
-    },
-  })),
+  ...flatMap(getTSParsers(), (parser) => [
+    test({
+      code: `
+        import * as foo from "./typescript-declare-nested"
+        foo.bar.MyFunction()
+      `,
+      parser: parser,
+      settings: {
+        'import/parsers': { [parser]: ['.ts'] },
+        'import/resolver': { 'eslint-import-resolver-typescript': true },
+      },
+    }),
+
+    test({
+      code: `import { foobar } from "./typescript-declare-interface"`,
+      parser: parser,
+      settings: {
+        'import/parsers': { [parser]: ['.ts'] },
+        'import/resolver': { 'eslint-import-resolver-typescript': true },
+      },
+    }),
+
+    test({
+      code: 'export * from "typescript/lib/typescript.d"',
+      parser: parser,
+      settings: {
+        'import/parsers': { [parser]: ['.ts'] },
+        'import/resolver': { 'eslint-import-resolver-typescript': true },
+      },
+    }),
+  ]),
 
   ...SYNTAX_CASES,
 ]

From 4ff9b923c60621ade9dd944584a0ca0112bb5b53 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 7 Jun 2020 13:56:44 -0700
Subject: [PATCH 166/767] [Fix] TypeScript: `export`: avoid a crash with
 `export =`

Fixes #1801.
---
 .eslintignore                         |  1 +
 CHANGELOG.md                          |  2 ++
 src/ExportMap.js                      |  4 +++-
 tests/files/typescript-d-ts/.eslintrc | 12 ++++++++++++
 tests/files/typescript-d-ts/file1.ts  |  6 ++++++
 tests/files/typescript-d-ts/file2.ts  |  1 +
 tests/src/cli.js                      |  4 ++--
 tests/src/rules/export.js             |  6 +++++-
 8 files changed, 32 insertions(+), 4 deletions(-)
 create mode 100644 tests/files/typescript-d-ts/.eslintrc
 create mode 100644 tests/files/typescript-d-ts/file1.ts
 create mode 100644 tests/files/typescript-d-ts/file2.ts

diff --git a/.eslintignore b/.eslintignore
index b260021d40..9d22006820 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -5,6 +5,7 @@ node_modules
 tests/files/malformed.js
 tests/files/with-syntax-error
 tests/files/just-json-files/invalid.json
+tests/files/typescript-d-ts/
 resolvers/webpack/test/files
 # we want to ignore "tests/files" here, but unfortunately doing so would
 # interfere with unit test and fail it for some reason.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b4cb56088..987da7fb6b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`namespace`]/`ExportMap`: Fix interface declarations for TypeScript ([#1764], thanks [@julien1619])
 - [`no-unused-modules`]: avoid order-dependence ([#1744], thanks [@darkartur])
 - [`no-internal-modules`]: also check `export from` syntax ([#1691], thanks [@adjerbetian])
+- TypeScript: [`export`]: avoid a crash with `export =` ([#1801], thanks [@ljharb])
 
 ### Changed
 - [Refactor] `no-extraneous-dependencies`: use moduleVisitor ([#1735], thanks [@adamborowski])
@@ -690,6 +691,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1802]: https://github.com/benmosher/eslint-plugin-import/pull/1802
+[#1801]: https://github.com/benmosher/eslint-plugin-import/issues/1801
 [#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
 [#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
 [#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
diff --git a/src/ExportMap.js b/src/ExportMap.js
index d72952ef4c..dfd9ca155d 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -590,7 +590,9 @@ ExportMap.parse = function (path, content, context) {
                 moduleBlockNode.declaration :
                 moduleBlockNode
 
-              if (namespaceDecl.type === 'VariableDeclaration') {
+              if (!namespaceDecl) {
+                // TypeScript can check this for us; we needn't
+              } else if (namespaceDecl.type === 'VariableDeclaration') {
                 namespaceDecl.declarations.forEach((d) =>
                   recursivePatternCapture(d.id, (id) => m.namespace.set(
                     id.name,
diff --git a/tests/files/typescript-d-ts/.eslintrc b/tests/files/typescript-d-ts/.eslintrc
new file mode 100644
index 0000000000..f22e9cb620
--- /dev/null
+++ b/tests/files/typescript-d-ts/.eslintrc
@@ -0,0 +1,12 @@
+{
+  "overrides": [
+    {
+      "files": "**.ts",
+      "parser": "@typescript-eslint/parser",
+      "extends": "../../../config/typescript",
+      "rules": {
+        "import/export": "error",
+      },
+    },
+  ],
+}
diff --git a/tests/files/typescript-d-ts/file1.ts b/tests/files/typescript-d-ts/file1.ts
new file mode 100644
index 0000000000..872c30e8af
--- /dev/null
+++ b/tests/files/typescript-d-ts/file1.ts
@@ -0,0 +1,6 @@
+declare namespace ts {
+  const x: string;
+  export { x };
+}
+
+export = ts;
diff --git a/tests/files/typescript-d-ts/file2.ts b/tests/files/typescript-d-ts/file2.ts
new file mode 100644
index 0000000000..e8ed5afca7
--- /dev/null
+++ b/tests/files/typescript-d-ts/file2.ts
@@ -0,0 +1 @@
+export * from './file1.ts'
diff --git a/tests/src/cli.js b/tests/src/cli.js
index 53d6e8fdc9..5e0a74e36c 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -22,7 +22,7 @@ describe('CLI regression tests', function () {
       })
     })
     it("doesn't throw an error on gratuitous, erroneous self-reference", function () {
-      expect(() => cli.executeOnFiles(['./tests/files/issue210.js'])).not.to.throw(Error)
+      expect(() => cli.executeOnFiles(['./tests/files/issue210.js'])).not.to.throw()
     })
   })
 
@@ -41,7 +41,7 @@ describe('CLI regression tests', function () {
       }
     })
 
-    it('throws an error on invalid JSON', function () {
+    it('throws an error on invalid JSON', () => {
       const invalidJSON = './tests/files/just-json-files/invalid.json'
       const results = cli.executeOnFiles([invalidJSON])
       expect(results).to.eql({
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 76fae45676..fb301495e7 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES, getTSParsers } from '../utils'
+import { test, testFilePath, SYNTAX_CASES, getTSParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
 
@@ -187,6 +187,10 @@ context('TypeScript', function () {
             }
           `,
         }, parserConfig)),
+        test(Object.assign({
+          code: 'export * from "./file1.ts"',
+          filename: testFilePath('typescript-d-ts/file-2.ts'),
+        }, parserConfig)),
       ],
       invalid: [
         // type/value name clash

From 199143c830d79d00aaef5599f0616a1bdfd51bfb Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 7 Jun 2020 16:22:42 -0700
Subject: [PATCH 167/767] [Deps] update `array-includes`,
 `array.prototype.flat`, `eslint-import-resolver-node`, `eslint-module-utils`,
 `object.values`, `resolve`

---
 package.json | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/package.json b/package.json
index da8f028162..d53b456204 100644
--- a/package.json
+++ b/package.json
@@ -97,18 +97,18 @@
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.0.0-0"
   },
   "dependencies": {
-    "array-includes": "^3.0.3",
-    "array.prototype.flat": "^1.2.1",
+    "array-includes": "^3.1.1",
+    "array.prototype.flat": "^1.2.3",
     "contains-path": "^0.1.0",
     "debug": "^2.6.9",
     "doctrine": "1.5.0",
-    "eslint-import-resolver-node": "^0.3.2",
-    "eslint-module-utils": "^2.4.1",
+    "eslint-import-resolver-node": "^0.3.3",
+    "eslint-module-utils": "^2.6.0",
     "has": "^1.0.3",
     "minimatch": "^3.0.4",
-    "object.values": "^1.1.0",
+    "object.values": "^1.1.1",
     "read-pkg-up": "^2.0.0",
-    "resolve": "^1.12.0",
+    "resolve": "^1.17.0",
     "tsconfig-paths": "^3.9.0"
   },
   "nyc": {

From d84062e290b1e2b80f459ecff7dde5ea5f8c0141 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 7 Jun 2020 16:23:46 -0700
Subject: [PATCH 168/767] [eslint] bump minimum v7 version to v7.2.0

---
 CHANGELOG.md | 1 +
 package.json | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 987da7fb6b..6d80d609f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Docs] `order`: fix bad inline config ([#1788], thanks [@nickofthyme])
 - [Tests] Add fix for Windows Subsystem for Linux ([#1786], thanks [@manuth])
 - [Docs] `no-unused-rules`: Fix docs for unused exports ([#1776], thanks [@barbogast])
+- [eslint] bump minimum v7 version to v7.2.0
 
 ## [2.20.2] - 2020-03-28
 ### Fixed
diff --git a/package.json b/package.json
index d53b456204..4bb9fb384e 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,7 @@
     "chai": "^4.2.0",
     "coveralls": "^3.0.6",
     "cross-env": "^4.0.0",
-    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.0.0-0",
+    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0",
     "eslint-import-resolver-node": "file:./resolvers/node",
     "eslint-import-resolver-typescript": "^1.0.2",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
@@ -94,7 +94,7 @@
     "typescript-eslint-parser": "^22.0.0"
   },
   "peerDependencies": {
-    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.0.0-0"
+    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0"
   },
   "dependencies": {
     "array-includes": "^3.1.1",

From 26992510364f7c6061b18249c33ee8d9a14ccc80 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 7 Jun 2020 16:25:53 -0700
Subject: [PATCH 169/767] Bump to v2.21.0

---
 CHANGELOG.md | 4 +++-
 package.json | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d80d609f4..df4599a358 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.21.0] - 2020-06-07
 ### Added
 - [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])
 - [`no-cycle`]: add `ignoreExternal` option ([#1681], thanks [@sveyret])
@@ -977,7 +978,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.2...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.0...HEAD
+[2.21.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.2...v2.21.0
 [2.20.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.1...v2.20.2
 [2.20.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.0...v2.20.1
 [2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.1...v2.20.0
diff --git a/package.json b/package.json
index 4bb9fb384e..a2beb0cc9a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.20.2",
+  "version": "2.21.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 381b2b56597bfc45e2558d916ad78a7db055f691 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 7 Jun 2020 19:40:05 -0700
Subject: [PATCH 170/767] [Fix] TypeScript: `named`: avoid requiring
 `typescript` when not using TS

Fixes #1805.
---
 src/ExportMap.js | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/ExportMap.js b/src/ExportMap.js
index dfd9ca155d..c8f03cf4f6 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -17,7 +17,7 @@ import { tsConfigLoader } from 'tsconfig-paths/lib/tsconfig-loader'
 
 import includes from 'array-includes'
 
-import {parseConfigFileTextToJson} from 'typescript'
+let parseConfigFileTextToJson
 
 const log = debug('eslint-plugin-import:ExportMap')
 
@@ -459,6 +459,10 @@ ExportMap.parse = function (path, content, context) {
     try {
       if (tsConfigInfo.tsConfigPath !== undefined) {
         const jsonText = fs.readFileSync(tsConfigInfo.tsConfigPath).toString()
+        if (!parseConfigFileTextToJson) {
+          // this is because projects not using TypeScript won't have typescript installed
+          ({parseConfigFileTextToJson} = require('typescript'))
+        }
         const tsConfig = parseConfigFileTextToJson(tsConfigInfo.tsConfigPath, jsonText).config
         return tsConfig.compilerOptions.esModuleInterop
       }
@@ -552,7 +556,9 @@ ExportMap.parse = function (path, content, context) {
     const isEsModuleInteropTrue = isEsModuleInterop()
 
     const exports = ['TSExportAssignment']
-    isEsModuleInteropTrue && exports.push('TSNamespaceExportDeclaration')
+    if (isEsModuleInteropTrue) {
+      exports.push('TSNamespaceExportDeclaration')
+    }
 
     // This doesn't declare anything, but changes what's being exported.
     if (includes(exports, n.type)) {

From 63d2a3f8c0d9ef874680c3150d1c14925fb1f36b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 7 Jun 2020 19:58:45 -0700
Subject: [PATCH 171/767] Bump to v2.21.1

---
 CHANGELOG.md | 7 ++++++-
 package.json | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index df4599a358..ca63eb5f8d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.21.1] - 2020-06-07
+### Fixed
+- TypeScript: [`import/named`]: avoid requiring `typescript` when not using TS ([#1805], thanks [@ljharb])
+
 ## [2.21.0] - 2020-06-07
 ### Added
 - [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])
@@ -978,7 +982,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.0...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...HEAD
+[2.21.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.0...v2.21.1
 [2.21.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.2...v2.21.0
 [2.20.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.1...v2.20.2
 [2.20.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.0...v2.20.1
diff --git a/package.json b/package.json
index a2beb0cc9a..4d6de7644c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.21.0",
+  "version": "2.21.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 1951ef517ab50b6d664a97bd3d799e347914e186 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 8 Jun 2020 11:18:27 -0700
Subject: [PATCH 172/767] [Tests] `order`: group TS tests together

---
 tests/src/rules/order.js | 89 ++++++++++++++++++++--------------------
 1 file changed, 44 insertions(+), 45 deletions(-)

diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index f6e2dddbaa..bad48bf38d 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -3,6 +3,7 @@ import { test, getTSParsers, getNonDefaultParsers } from '../utils'
 import { RuleTester } from 'eslint'
 import eslintPkg from 'eslint/package.json'
 import semver from 'semver'
+import flatMap from 'array.prototype.flatmap'
 
 const ruleTester = new RuleTester()
     , rule = require('rules/order')
@@ -167,8 +168,8 @@ ruleTester.run('order', rule, {
         var index = require('./');
       `,
     }),
-    // Export equals expressions should be on top alongside with ordinary import-statements.
-    ...getTSParsers().map(parser => (
+    ...flatMap(getTSParsers(), parser => [
+      // Export equals expressions should be on top alongside with ordinary import-statements.
       test({
         code: `
           import async, {foo1} from 'async';
@@ -181,8 +182,8 @@ ruleTester.run('order', rule, {
           var index = require('./');
         `,
         parser,
-      })
-    )),
+      }),
+    ]),
     // Adding unknown import types (e.g. using a resolver alias via babel) to the groups.
     test({
       code: `
@@ -1158,7 +1159,7 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur after import of `../foo/bar`',
       }],
     }),
-    ...getTSParsers().map(parser => (
+    ...flatMap(getTSParsers(), parser => [
       test({
         code: `
           var fs = require('fs');
@@ -1174,8 +1175,44 @@ ruleTester.run('order', rule, {
         errors: [{
           message: '`fs` import should occur after import of `../foo/bar`',
         }],
-      })
-    )),
+      }),
+      {
+        code: `
+          var async = require('async');
+          var fs = require('fs');
+        `,
+        output: `
+          var fs = require('fs');
+          var async = require('async');
+        `,
+        parser,
+        errors: [{
+          message: '`fs` import should occur before import of `async`',
+        }],
+      },
+      test({
+        code: `
+          import sync = require('sync');
+          import async, {foo1} from 'async';
+
+          import index from './';
+        `,
+        output: `
+          import async, {foo1} from 'async';
+          import sync = require('sync');
+
+          import index from './';
+        `,
+        options: [{
+          groups: ['external', 'index'],
+          alphabetize: {order: 'asc'},
+        }],
+        parser,
+        errors: [{
+          message: '`async` import should occur before import of `sync`',
+        }],
+      }),
+    ]),
     // Default order using import with custom import alias
     test({
       code: `
@@ -1909,20 +1946,6 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     })),
-    ...getTSParsers().map(parser => ({
-      code: `
-        var async = require('async');
-        var fs = require('fs');
-      `,
-      output: `
-        var fs = require('fs');
-        var async = require('async');
-      `,
-      parser,
-      errors: [{
-        message: '`fs` import should occur before import of `async`',
-      }],
-    })),
     // Option alphabetize: {order: 'asc'}
     test({
       code: `
@@ -1947,30 +1970,6 @@ ruleTester.run('order', rule, {
         message: '`Bar` import should occur before import of `bar`',
       }],
     }),
-    ...getTSParsers().map(parser => (
-        test({
-          code: `
-            import sync = require('sync');
-            import async, {foo1} from 'async';
-
-            import index from './';
-          `,
-          output: `
-            import async, {foo1} from 'async';
-            import sync = require('sync');
-
-            import index from './';
-          `,
-          options: [{
-            groups: ['external', 'index'],
-            alphabetize: {order: 'asc'},
-          }],
-          parser,
-          errors: [{
-            message: '`async` import should occur before import of `sync`',
-          }],
-        })
-      )),
     // Option alphabetize: {order: 'desc'}
     test({
       code: `

From cc604c1ed9267427c50dd8e598f6a1e136867173 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 8 Jun 2020 11:24:51 -0700
Subject: [PATCH 173/767] =?UTF-8?q?[Fix]=20`order`:=20avoid=20a=20crash=20?=
 =?UTF-8?q?on=20TypeScript=E2=80=99s=20`export=20import`=20syntax?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fixes #1808.
---
 CHANGELOG.md             | 5 +++++
 src/core/importType.js   | 2 +-
 src/rules/order.js       | 2 ++
 tests/src/rules/order.js | 7 +++++++
 4 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ca63eb5f8d..cb89f8723d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`order`]: avoid a crash on TypeScript’s `export import` syntax ([#1808], thanks [@ljharb])
+
 ## [2.21.1] - 2020-06-07
 ### Fixed
 - TypeScript: [`import/named`]: avoid requiring `typescript` when not using TS ([#1805], thanks [@ljharb])
@@ -897,6 +900,8 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
+[#1808]: https://github.com/benmosher/eslint-plugin-import/issues/1808
+[#1805]: https://github.com/benmosher/eslint-plugin-import/issues/1805
 [#1565]: https://github.com/benmosher/eslint-plugin-import/issues/1565
 [#1366]: https://github.com/benmosher/eslint-plugin-import/issues/1366
 [#1334]: https://github.com/benmosher/eslint-plugin-import/issues/1334
diff --git a/src/core/importType.js b/src/core/importType.js
index 4d56b86d4b..ff2d10b60f 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -12,7 +12,7 @@ function baseModule(name) {
 }
 
 export function isAbsolute(name) {
-  return name.indexOf('/') === 0
+  return name && name.startsWith('/')
 }
 
 // path is defined only when a resolver resolves to a non-standard path
diff --git a/src/rules/order.js b/src/rules/order.js
index 9edac3af91..b407145405 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -611,6 +611,8 @@ module.exports = {
         let name
         if (node.moduleReference.type === 'TSExternalModuleReference') {
           name = node.moduleReference.expression.value
+        } else if (node.isExport) {
+          name = node.moduleReference.name
         } else {
           name = null
         }
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index bad48bf38d..e8ee82ec6c 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -183,6 +183,13 @@ ruleTester.run('order', rule, {
         `,
         parser,
       }),
+
+      test({
+        code: `
+          export import CreateSomething = _CreateSomething;
+        `,
+        parser,
+      }),
     ]),
     // Adding unknown import types (e.g. using a resolver alias via babel) to the groups.
     test({

From 903e8fbcaf345544338077e23a83e669fd54bc14 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 8 Jun 2020 13:05:48 -0700
Subject: [PATCH 174/767] [Fix] `newline-after-import`: consider TypeScript
 `import =` syntax

Fixes #1811.
---
 CHANGELOG.md                            |  2 ++
 src/rules/newline-after-import.js       | 11 ++++---
 tests/src/rules/newline-after-import.js | 39 +++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb89f8723d..c58beba1a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`order`]: avoid a crash on TypeScript’s `export import` syntax ([#1808], thanks [@ljharb])
+- [`newline-after-import`]: consider TypeScript `import =` syntax' ([#1811], thanks [@ljharb])
 
 ## [2.21.1] - 2020-06-07
 ### Fixed
@@ -900,6 +901,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
+[#1811]: https://github.com/benmosher/eslint-plugin-import/issues/1811
 [#1808]: https://github.com/benmosher/eslint-plugin-import/issues/1808
 [#1805]: https://github.com/benmosher/eslint-plugin-import/issues/1805
 [#1565]: https://github.com/benmosher/eslint-plugin-import/issues/1565
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 7807dfcdab..8255b189cc 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -115,16 +115,19 @@ after ${type} statement not followed by another ${type}.`,
       level--
     }
 
-    return {
-      ImportDeclaration: function (node) {
+    function checkImport(node) {
         const { parent } = node
         const nodePosition = parent.body.indexOf(node)
         const nextNode = parent.body[nodePosition + 1]
 
-        if (nextNode && nextNode.type !== 'ImportDeclaration') {
+        if (nextNode && nextNode.type !== 'ImportDeclaration' && nextNode.type !== 'TSImportEqualsDeclaration') {
           checkForNewLine(node, nextNode, 'import')
         }
-      },
+    }
+
+    return {
+      ImportDeclaration: checkImport,
+      TSImportEqualsDeclaration: checkImport,
       CallExpression: function(node) {
         if (isStaticRequire(node) && level === 0) {
           requireCalls.push(node)
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index bb94b56dad..626e6e0261 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -1,4 +1,7 @@
 import { RuleTester } from 'eslint'
+import flatMap from 'array.prototype.flatmap'
+
+import { getTSParsers } from '../utils'
 
 const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.'
 const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => {
@@ -175,6 +178,42 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { sourceType: 'module' },
       parser: require.resolve('babel-eslint'),
     },
+    ...flatMap(getTSParsers(), (parser) => [
+      {
+        code: `
+          import { ExecaReturnValue } from 'execa';
+          import execa = require('execa');
+        `,
+        parser: parser,
+        parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      },
+      {
+        code: `
+          import execa = require('execa');
+          import { ExecaReturnValue } from 'execa';
+        `,
+        parser: parser,
+        parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      },
+      {
+        code: `
+          import { ExecaReturnValue } from 'execa';
+          import execa = require('execa');
+          import { ExecbReturnValue } from 'execb';
+        `,
+        parser: parser,
+        parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      },
+      {
+        code: `
+          import execa = require('execa');
+          import { ExecaReturnValue } from 'execa';
+          import execb = require('execb');
+        `,
+        parser: parser,
+        parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      },
+    ]),
   ],
 
   invalid: [

From 4ce280a0e1527380c25c7ca7d83767326d972442 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Jun 2020 11:49:58 -0700
Subject: [PATCH 175/767] [Fix] `no-internal-modules`: avoid a crash on a named
 export declaration

Fixes #1814.
---
 CHANGELOG.md                           |  2 ++
 src/rules/no-internal-modules.js       |  4 +++-
 tests/src/rules/no-internal-modules.js | 24 +++++++++++++++++++++++-
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c58beba1a6..0d5251dfcf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`order`]: avoid a crash on TypeScript’s `export import` syntax ([#1808], thanks [@ljharb])
 - [`newline-after-import`]: consider TypeScript `import =` syntax' ([#1811], thanks [@ljharb])
+- [`no-internal-modules`]: avoid a crash on a named export declaration ([#1814], thanks [@ljharb])
 
 ## [2.21.1] - 2020-06-07
 ### Fixed
@@ -901,6 +902,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
+[#1814]: https://github.com/benmosher/eslint-plugin-import/issues/1814
 [#1811]: https://github.com/benmosher/eslint-plugin-import/issues/1811
 [#1808]: https://github.com/benmosher/eslint-plugin-import/issues/1808
 [#1805]: https://github.com/benmosher/eslint-plugin-import/issues/1805
diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index b5d7496a2a..bd13ab07d0 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -95,7 +95,9 @@ module.exports = {
         checkImportForReaching(node.source.value, node.source)
       },
       ExportNamedDeclaration(node) {
-        checkImportForReaching(node.source.value, node.source)
+        if (node.source) {
+          checkImportForReaching(node.source.value, node.source)
+        }
       },
       CallExpression(node) {
         if (isStaticRequire(node)) {
diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js
index 5058fcb349..da9a4ca1a0 100644
--- a/tests/src/rules/no-internal-modules.js
+++ b/tests/src/rules/no-internal-modules.js
@@ -1,7 +1,8 @@
 import { RuleTester } from 'eslint'
+import flatMap from 'array.prototype.flatmap'
 import rule from 'rules/no-internal-modules'
 
-import { test, testFilePath } from '../utils'
+import { test, testFilePath, getTSParsers } from '../utils'
 
 const ruleTester = new RuleTester()
 
@@ -92,6 +93,27 @@ ruleTester.run('no-internal-modules', rule, {
         allow: [ '**/index{.js,}' ],
       } ],
     }),
+    test({
+      code: `
+        export class AuthHelper {
+
+          static checkAuth(auth) {
+          }
+        }
+      `,
+    }),
+    ...flatMap(getTSParsers(), (parser) => [
+      test({
+        code: `
+          export class AuthHelper {
+
+            public static checkAuth(auth?: string): boolean {
+            }
+          }
+        `,
+        parser: parser,
+      }),
+    ]),
   ],
 
   invalid: [

From ffd540fc7a32c154eb870d05b865de0db64fa2cb Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Jun 2020 16:04:00 -0700
Subject: [PATCH 176/767] [Dev Deps] update `in-publish`, `typescript`

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 4d6de7644c..73578badd1 100644
--- a/package.json
+++ b/package.json
@@ -80,7 +80,7 @@
     "eslint-plugin-json": "^2.1.1",
     "fs-copy-file-sync": "^1.1.1",
     "glob": "^7.1.6",
-    "in-publish": "^2.0.0",
+    "in-publish": "^2.0.1",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",
     "mocha": "^3.5.3",
@@ -90,7 +90,7 @@
     "rimraf": "^2.7.1",
     "semver": "^6.3.0",
     "sinon": "^2.4.1",
-    "typescript": "~3.8.3",
+    "typescript": "~3.9.5",
     "typescript-eslint-parser": "^22.0.0"
   },
   "peerDependencies": {

From f53e872540dfc13b129f456844373b451fa540f3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Jun 2020 16:05:17 -0700
Subject: [PATCH 177/767] Bump to v2.21.2

---
 CHANGELOG.md | 4 +++-
 package.json | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d5251dfcf..1d583358ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.21.2] - 2020-06-09
 ### Fixed
 - [`order`]: avoid a crash on TypeScript’s `export import` syntax ([#1808], thanks [@ljharb])
 - [`newline-after-import`]: consider TypeScript `import =` syntax' ([#1811], thanks [@ljharb])
@@ -991,7 +992,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.2...HEAD
+[2.21.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.21.2
 [2.21.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.0...v2.21.1
 [2.21.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.2...v2.21.0
 [2.20.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.1...v2.20.2
diff --git a/package.json b/package.json
index 73578badd1..9b42324f66 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.21.1",
+  "version": "2.21.2",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From ec5195edb89094278a6a8555643e3a876a3fa9de Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 11 Jun 2020 15:47:27 -0700
Subject: [PATCH 178/767] [Tests] `namespace`: add test case for #1818

---
 tests/src/rules/namespace.js | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 5627c7132a..1f594dbbd4 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -152,6 +152,15 @@ const valid = [
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
     }),
+
+    test({
+      code: 'export = function name() {}',
+      parser: parser,
+      settings: {
+        'import/parsers': { [parser]: ['.ts'] },
+        'import/resolver': { 'eslint-import-resolver-typescript': true },
+      },
+    }),
   ]),
 
   ...SYNTAX_CASES,

From 54eb51b873697e006287d2a19c7b906ab480a04d Mon Sep 17 00:00:00 2001
From: e020873 <nicolas.henry-partner@arcelormittal.com>
Date: Thu, 11 Jun 2020 18:20:11 +0200
Subject: [PATCH 179/767] [New] `no-unused-modules`: consider exported
 TypeScript interfaces, types and enums

Fixes #1680

Co-authored-by: e020873 <nicolas.henry-partner@arcelormittal.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 CHANGELOG.md                                  |  4 +
 src/rules/no-unused-modules.js                | 57 ++++++++-------
 .../no-unused-modules/typescript/file-ts-a.ts |  7 +-
 .../no-unused-modules/typescript/file-ts-c.ts |  1 +
 .../no-unused-modules/typescript/file-ts-d.ts |  1 +
 .../no-unused-modules/typescript/file-ts-e.ts |  1 +
 tests/src/rules/no-unused-modules.js          | 73 ++++++++++++++++++-
 7 files changed, 116 insertions(+), 28 deletions(-)
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-c.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-d.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-e.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1d583358ce..4cb0223be7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+### Added
+- [`no-unused-modules`]: consider exported TypeScript interfaces, types and enums ([#1819], thanks [@nicolashenry])
 
 ## [2.21.2] - 2020-06-09
 ### Fixed
@@ -702,6 +704,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1819]: https://github.com/benmosher/eslint-plugin-import/pull/1819
 [#1802]: https://github.com/benmosher/eslint-plugin-import/pull/1802
 [#1801]: https://github.com/benmosher/eslint-plugin-import/issues/1801
 [#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
@@ -1216,3 +1219,4 @@ for info on changes for earlier releases.
 [@adjerbetian]: https://github.com/adjerbetian
 [@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
 [@malykhinvi]: https://github.com/malykhinvi
+[@nicolashenry]: https://github.com/nicolashenry
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 25139b681f..d277ca9aed 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -63,8 +63,33 @@ const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier'
 const VARIABLE_DECLARATION = 'VariableDeclaration'
 const FUNCTION_DECLARATION = 'FunctionDeclaration'
 const CLASS_DECLARATION = 'ClassDeclaration'
+const INTERFACE_DECLARATION = 'InterfaceDeclaration'
+const TYPE_ALIAS = 'TypeAlias'
+const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration'
+const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration'
+const TS_ENUM_DECLARATION = 'TSEnumDeclaration'
 const DEFAULT = 'default'
 
+function forEachDeclarationIdentifier(declaration, cb) {
+  if (declaration) {
+    if (
+      declaration.type === FUNCTION_DECLARATION ||
+      declaration.type === CLASS_DECLARATION ||
+      declaration.type === INTERFACE_DECLARATION ||
+      declaration.type === TYPE_ALIAS ||
+      declaration.type === TS_INTERFACE_DECLARATION ||
+      declaration.type === TS_TYPE_ALIAS_DECLARATION ||
+      declaration.type === TS_ENUM_DECLARATION
+    ) {
+      cb(declaration.id.name)
+    } else if (declaration.type === VARIABLE_DECLARATION) {
+      declaration.declarations.forEach(({ id }) => {
+        cb(id.name)
+      })
+    }
+  }
+}
+
 /**
  * List of imports per file.
  *
@@ -559,19 +584,9 @@ module.exports = {
               }
             })
           }
-          if (declaration) {
-            if (
-              declaration.type === FUNCTION_DECLARATION ||
-              declaration.type === CLASS_DECLARATION
-            ) {
-              newExportIdentifiers.add(declaration.id.name)
-            }
-            if (declaration.type === VARIABLE_DECLARATION) {
-              declaration.declarations.forEach(({ id }) => {
-                newExportIdentifiers.add(id.name)
-              })
-            }
-          }
+          forEachDeclarationIdentifier(declaration, (name) => {
+            newExportIdentifiers.add(name)
+          })
         }
       })
 
@@ -883,19 +898,9 @@ module.exports = {
         node.specifiers.forEach(specifier => {
             checkUsage(node, specifier.exported.name)
         })
-        if (node.declaration) {
-          if (
-            node.declaration.type === FUNCTION_DECLARATION ||
-            node.declaration.type === CLASS_DECLARATION
-          ) {
-            checkUsage(node, node.declaration.id.name)
-          }
-          if (node.declaration.type === VARIABLE_DECLARATION) {
-            node.declaration.declarations.forEach(declaration => {
-              checkUsage(node, declaration.id.name)
-            })
-          }
-        }
+        forEachDeclarationIdentifier(node.declaration, (name) => {
+          checkUsage(node, name)
+        })
       },
     }
   },
diff --git a/tests/files/no-unused-modules/typescript/file-ts-a.ts b/tests/files/no-unused-modules/typescript/file-ts-a.ts
index a4272256e6..a5cc566715 100644
--- a/tests/files/no-unused-modules/typescript/file-ts-a.ts
+++ b/tests/files/no-unused-modules/typescript/file-ts-a.ts
@@ -1,3 +1,8 @@
 import {b} from './file-ts-b';
+import {c} from './file-ts-c';
+import {d} from './file-ts-d';
+import {e} from './file-ts-e';
 
-export const a = b + 1;
+export const a = b + 1 + e.f;
+export const a2: c = {};
+export const a3: d = {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-c.ts b/tests/files/no-unused-modules/typescript/file-ts-c.ts
new file mode 100644
index 0000000000..aedf4062be
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-c.ts
@@ -0,0 +1 @@
+export interface c {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-d.ts b/tests/files/no-unused-modules/typescript/file-ts-d.ts
new file mode 100644
index 0000000000..7679b3de03
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-d.ts
@@ -0,0 +1 @@
+export type d = {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-e.ts b/tests/files/no-unused-modules/typescript/file-ts-e.ts
new file mode 100644
index 0000000000..d1787a11af
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-e.ts
@@ -0,0 +1 @@
+export enum e { f };
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index ef2d3e66c2..74200fb0d9 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -1,4 +1,4 @@
-import { test, testFilePath } from '../utils'
+import { test, testFilePath, getTSParsers } from '../utils'
 import jsxConfig from '../../../config/react'
 import typescriptConfig from '../../../config/typescript'
 
@@ -736,10 +736,81 @@ describe('correctly work with Typescript only files', () => {
           error(`exported declaration 'b' not used within other modules`),
         ],
       }),
+      test({
+        options: unusedExportsTypescriptOptions,
+        code: `export interface c {};`,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'),
+        errors: [
+          error(`exported declaration 'c' not used within other modules`),
+        ],
+      }),
+      test({
+        options: unusedExportsTypescriptOptions,
+        code: `export type d = {};`,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'),
+        errors: [
+          error(`exported declaration 'd' not used within other modules`),
+        ],
+      }),
     ],
   })
 })
 
+context('TypeScript', function () {
+  getTSParsers().forEach((parser) => {
+    typescriptRuleTester.run('no-unused-modules', rule, {
+      valid: [
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: 'import a from "file-ts-a";',
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+        }),
+      ],
+      invalid: [
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export const b = 2;`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'),
+          errors: [
+            error(`exported declaration 'b' not used within other modules`),
+          ],
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export interface c {};`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'),
+          errors: [
+            error(`exported declaration 'c' not used within other modules`),
+          ],
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export type d = {};`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'),
+          errors: [
+            error(`exported declaration 'd' not used within other modules`),
+          ],
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export enum e { f };`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-e.ts'),
+          errors: [
+            error(`exported declaration 'e' not used within other modules`),
+          ],
+        }),
+      ],
+    })
+  })
+})
+
 describe('correctly work with JSX only files', () => {
   jsxRuleTester.run('no-unused-modules', rule, {
     valid: [

From 1f7422d2e06e4f6accd68031e5768dd38a7ac18a Mon Sep 17 00:00:00 2001
From: Fernando Pasik <fernando@pasik.com.ar>
Date: Fri, 12 Jun 2020 16:04:52 +0100
Subject: [PATCH 180/767] [Fix] `no-extraneous-dependencies`/TypeScript: do not
 error when importing type from dev dependencies

Fixes #1618.
---
 CHANGELOG.md                                  |  5 ++
 src/rules/no-extraneous-dependencies.js       |  2 +-
 .../package.json                              |  5 ++
 tests/src/rules/no-extraneous-dependencies.js | 56 ++++++++++++++++++-
 4 files changed, 66 insertions(+), 2 deletions(-)
 create mode 100644 tests/files/with-typescript-dev-dependencies/package.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4cb0223be7..6ad6bc43b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Added
 - [`no-unused-modules`]: consider exported TypeScript interfaces, types and enums ([#1819], thanks [@nicolashenry])
 
+### Fixed
+- [`no-extraneous-dependencies`]/TypeScript: do not error when importing type from dev dependencies ([#1820], thanks [@fernandopasik])
+
 ## [2.21.2] - 2020-06-09
 ### Fixed
 - [`order`]: avoid a crash on TypeScript’s `export import` syntax ([#1808], thanks [@ljharb])
@@ -704,6 +707,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1820]: https://github.com/benmosher/eslint-plugin-import/pull/1820
 [#1819]: https://github.com/benmosher/eslint-plugin-import/pull/1819
 [#1802]: https://github.com/benmosher/eslint-plugin-import/pull/1802
 [#1801]: https://github.com/benmosher/eslint-plugin-import/issues/1801
@@ -1220,3 +1224,4 @@ for info on changes for earlier releases.
 [@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
 [@malykhinvi]: https://github.com/malykhinvi
 [@nicolashenry]: https://github.com/nicolashenry
+[@fernandopasik]: https://github.com/fernandopasik
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 03c45526c0..366a684c40 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -111,7 +111,7 @@ function optDepErrorMessage(packageName) {
 
 function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types
-  if (node.importKind === 'type') {
+  if (node.importKind === 'type' || (node.parent && node.parent.importKind === 'type')) {
     return
   }
 
diff --git a/tests/files/with-typescript-dev-dependencies/package.json b/tests/files/with-typescript-dev-dependencies/package.json
new file mode 100644
index 0000000000..e17fbd9777
--- /dev/null
+++ b/tests/files/with-typescript-dev-dependencies/package.json
@@ -0,0 +1,5 @@
+{
+  "devDependencies": {
+    "@types/json-schema": "*"
+  }
+}
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 97279d8538..a3ddb07427 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -1,4 +1,4 @@
-import { test } from '../utils'
+import { getTSParsers, test } from '../utils'
 import * as path from 'path'
 import * as fs from 'fs'
 
@@ -17,6 +17,7 @@ const packageFileWithSyntaxErrorMessage = (() => {
   }
 })()
 const packageDirWithFlowTyped = path.join(__dirname, '../../files/with-flow-typed')
+const packageDirWithTypescriptDevDependencies = path.join(__dirname, '../../files/with-typescript-dev-dependencies')
 const packageDirMonoRepoRoot = path.join(__dirname, '../../files/monorepo')
 const packageDirMonoRepoWithNested = path.join(__dirname, '../../files/monorepo/packages/nested-package')
 const packageDirWithEmpty = path.join(__dirname, '../../files/empty')
@@ -312,3 +313,56 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
   ],
 })
+
+describe('TypeScript', function () {
+  getTSParsers()
+    .forEach((parser) => {
+      const parserConfig = {
+        parser: parser,
+        settings: {
+          'import/parsers': { [parser]: ['.ts'] },
+          'import/resolver': { 'eslint-import-resolver-typescript': true },
+        },
+      }
+
+      if (parser !== require.resolve('typescript-eslint-parser')) {
+        ruleTester.run('no-extraneous-dependencies', rule, {
+          valid: [
+            test(Object.assign({
+              code: 'import type { JSONSchema7Type } from "@types/json-schema";',
+              options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            }, parserConfig)),
+          ],
+          invalid: [
+            test(Object.assign({
+              code: 'import { JSONSchema7Type } from "@types/json-schema";',
+              options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+              errors: [{
+                message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+              }],
+            }, parserConfig)),
+          ],
+        })
+      } else {
+        ruleTester.run('no-extraneous-dependencies', rule, {
+          valid: [],
+          invalid: [
+            test(Object.assign({
+              code: 'import { JSONSchema7Type } from "@types/json-schema";',
+              options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+              errors: [{
+                message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+              }],
+            }, parserConfig)),
+            test(Object.assign({
+              code: 'import type { JSONSchema7Type } from "@types/json-schema";',
+              options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+              errors: [{
+                message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+              }],
+            }, parserConfig)),
+          ],
+        })
+      }
+    })
+})

From f7c7d7906b5f6ddf31d58e65d1531019f9951d71 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 13 Jun 2020 16:41:56 -0700
Subject: [PATCH 181/767] [meta] add `eol-last` eslint rule

---
 .eslintrc.yml                 | 1 +
 resolvers/node/test/native.js | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/.eslintrc.yml b/.eslintrc.yml
index 8c270e9533..4f8ccaac37 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -20,6 +20,7 @@ rules:
   semi: [2, "never"]
   curly: [2, "multi-line"]
   comma-dangle: [2, always-multiline]
+  eol-last: [2, "always"]
   eqeqeq: [2, "allow-null"]
   no-shadow: 1
   quotes:
diff --git a/resolvers/node/test/native.js b/resolvers/node/test/native.js
index 8212295922..c2a4339049 100644
--- a/resolvers/node/test/native.js
+++ b/resolvers/node/test/native.js
@@ -1 +1 @@
-exports.natively = function () { return "but where do we feature?" }
\ No newline at end of file
+exports.natively = function () { return "but where do we feature?" }

From 6f5d95af708f88c5afd8e3f476ceeaa1e7b0e0e7 Mon Sep 17 00:00:00 2001
From: Taye Adeyemi <dev@taye.me>
Date: Sat, 13 Jun 2020 13:27:51 +0200
Subject: [PATCH 182/767] [Tests] `no-extraneous-dependencies`: add tests for
 importing types

---
 CHANGELOG.md                                  |   5 +
 tests/src/rules/no-extraneous-dependencies.js | 126 ++++++++++--------
 2 files changed, 79 insertions(+), 52 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6ad6bc43b0..08f0e83c0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing type from dev dependencies ([#1820], thanks [@fernandopasik])
 
+### Changed
+- [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
+
 ## [2.21.2] - 2020-06-09
 ### Fixed
 - [`order`]: avoid a crash on TypeScript’s `export import` syntax ([#1808], thanks [@ljharb])
@@ -707,6 +710,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1824]: https://github.com/benmosher/eslint-plugin-import/pull/1824
 [#1820]: https://github.com/benmosher/eslint-plugin-import/pull/1820
 [#1819]: https://github.com/benmosher/eslint-plugin-import/pull/1819
 [#1802]: https://github.com/benmosher/eslint-plugin-import/pull/1802
@@ -1225,3 +1229,4 @@ for info on changes for earlier releases.
 [@malykhinvi]: https://github.com/malykhinvi
 [@nicolashenry]: https://github.com/nicolashenry
 [@fernandopasik]: https://github.com/fernandopasik
+[@taye]: https://github.com/taye
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index a3ddb07427..77de28b339 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -1,11 +1,15 @@
-import { getTSParsers, test } from '../utils'
-import * as path from 'path'
-import * as fs from 'fs'
+import { getTSParsers, test, testFilePath } from '../utils'
+import typescriptConfig from '../../../config/typescript'
+import path from 'path'
+import fs from 'fs'
+import semver from 'semver'
+import eslintPkg from 'eslint/package.json'
 
 import { RuleTester } from 'eslint'
 import flatMap from 'array.prototype.flatmap'
 
 const ruleTester = new RuleTester()
+const typescriptRuleTester = new RuleTester(typescriptConfig)
 const rule = require('rules/no-extraneous-dependencies')
 
 const packageDirWithSyntaxError = path.join(__dirname, '../../files/with-syntax-error')
@@ -315,54 +319,72 @@ ruleTester.run('no-extraneous-dependencies', rule, {
 })
 
 describe('TypeScript', function () {
-  getTSParsers()
-    .forEach((parser) => {
-      const parserConfig = {
-        parser: parser,
-        settings: {
-          'import/parsers': { [parser]: ['.ts'] },
-          'import/resolver': { 'eslint-import-resolver-typescript': true },
-        },
-      }
+  getTSParsers().forEach((parser) => {
+    const parserConfig = {
+      parser: parser,
+      settings: {
+        'import/parsers': { [parser]: ['.ts'] },
+        'import/resolver': { 'eslint-import-resolver-typescript': true },
+      },
+    }
 
-      if (parser !== require.resolve('typescript-eslint-parser')) {
-        ruleTester.run('no-extraneous-dependencies', rule, {
-          valid: [
-            test(Object.assign({
-              code: 'import type { JSONSchema7Type } from "@types/json-schema";',
-              options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
-            }, parserConfig)),
-          ],
-          invalid: [
-            test(Object.assign({
-              code: 'import { JSONSchema7Type } from "@types/json-schema";',
-              options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
-              errors: [{
-                message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
-              }],
-            }, parserConfig)),
-          ],
-        })
-      } else {
-        ruleTester.run('no-extraneous-dependencies', rule, {
-          valid: [],
-          invalid: [
-            test(Object.assign({
-              code: 'import { JSONSchema7Type } from "@types/json-schema";',
-              options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
-              errors: [{
-                message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
-              }],
-            }, parserConfig)),
-            test(Object.assign({
-              code: 'import type { JSONSchema7Type } from "@types/json-schema";',
-              options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
-              errors: [{
-                message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
-              }],
-            }, parserConfig)),
-          ],
-        })
-      }
-    })
+    if (parser !== require.resolve('typescript-eslint-parser')) {
+      ruleTester.run('no-extraneous-dependencies', rule, {
+        valid: [
+          test(Object.assign({
+            code: 'import type { JSONSchema7Type } from "@types/json-schema";',
+            options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+          }, parserConfig)),
+        ],
+        invalid: [
+          test(Object.assign({
+            code: 'import { JSONSchema7Type } from "@types/json-schema";',
+            options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            errors: [{
+              message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+            }],
+          }, parserConfig)),
+        ],
+      })
+    } else {
+      ruleTester.run('no-extraneous-dependencies', rule, {
+        valid: [],
+        invalid: [
+          test(Object.assign({
+            code: 'import { JSONSchema7Type } from "@types/json-schema";',
+            options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            errors: [{
+              message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+            }],
+          }, parserConfig)),
+          test(Object.assign({
+            code: 'import type { JSONSchema7Type } from "@types/json-schema";',
+            options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            errors: [{
+              message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+            }],
+          }, parserConfig)),
+        ],
+      })
+    }
+  })
 })
+
+if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
+  typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', rule, {
+    valid: [
+      test({
+        code: 'import type MyType from "not-a-dependency";',
+        filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+        parser: require.resolve('babel-eslint'),
+      }),
+      test({
+        code: 'import type { MyType } from "not-a-dependency";',
+        filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+        parser: require.resolve('babel-eslint'),
+      }),
+    ],
+    invalid: [
+    ],
+  })
+}

From b22a183b37859162d86048df4e0654a8103b21a6 Mon Sep 17 00:00:00 2001
From: AndrewLeedham <AndrewLeedham@Outlook.com>
Date: Fri, 12 Jun 2020 12:54:54 +0100
Subject: [PATCH 183/767] [Fix] `default`: avoid crash with `export =`

Fixes #1818.

Co-authored-by: AndrewLeedham <AndrewLeedham@Outlook.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 CHANGELOG.md                                     | 3 +++
 src/ExportMap.js                                 | 4 +++-
 tests/files/typescript-export-assign-function.ts | 1 +
 tests/src/rules/default.js                       | 8 ++++++++
 4 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 tests/files/typescript-export-assign-function.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 08f0e83c0d..ef8bffd8af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing type from dev dependencies ([#1820], thanks [@fernandopasik])
+- [`default`]: avoid crash with `export =` ([#1822], thanks [@AndrewLeedham])
 
 ### Changed
 - [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
@@ -711,6 +712,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1824]: https://github.com/benmosher/eslint-plugin-import/pull/1824
+[#1822]: https://github.com/benmosher/eslint-plugin-import/pull/1822
 [#1820]: https://github.com/benmosher/eslint-plugin-import/pull/1820
 [#1819]: https://github.com/benmosher/eslint-plugin-import/pull/1819
 [#1802]: https://github.com/benmosher/eslint-plugin-import/pull/1802
@@ -1230,3 +1232,4 @@ for info on changes for earlier releases.
 [@nicolashenry]: https://github.com/nicolashenry
 [@fernandopasik]: https://github.com/fernandopasik
 [@taye]: https://github.com/taye
+[@AndrewLeedham]: https://github.com/AndrewLeedham
diff --git a/src/ExportMap.js b/src/ExportMap.js
index c8f03cf4f6..6978b844cb 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -562,7 +562,9 @@ ExportMap.parse = function (path, content, context) {
 
     // This doesn't declare anything, but changes what's being exported.
     if (includes(exports, n.type)) {
-      const exportedName = n.expression && n.expression.name || n.id.name
+      const exportedName = n.type === 'TSNamespaceExportDeclaration'
+        ? n.id.name
+        : n.expression && n.expression.name || n.expression.id.name
       const declTypes = [
         'VariableDeclaration',
         'ClassDeclaration',
diff --git a/tests/files/typescript-export-assign-function.ts b/tests/files/typescript-export-assign-function.ts
new file mode 100644
index 0000000000..930d6dacee
--- /dev/null
+++ b/tests/files/typescript-export-assign-function.ts
@@ -0,0 +1 @@
+export = function foo() {};
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index d3d4aae4a7..c040a478d5 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -174,6 +174,14 @@ context('TypeScript', function () {
               'import/resolver': { 'eslint-import-resolver-typescript': true },
             },
           }),
+          test({
+            code: `import foobar from "./typescript-export-assign-function"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+          }),
           test({
             code: `import foobar from "./typescript-export-assign-mixed"`,
             parser: parser,

From f5d95e8cfb0a6078746532facda2d2d2c1c1f405 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Fri, 12 Jun 2020 22:34:59 +0200
Subject: [PATCH 184/767] [Fix] `order`/TypeScript: properly support `import =
 object` expressions

Just like ordinary `import x =` expressions, `export import x =` expressions can come with a number of different module-references.
Either a require-expression such as `export import fs = require("fs")`, a literal such as `export import Console = console;` or an object-path `export import log = console.log`.

This means, that the `isExport` property merely says whether the `TSImportEqualsDeclaration` has a leading `export`, but not what the `moduleReference` looks like.

----

This arguably is a semver-minor, but since it should have been included in #1785, I'm calling this a bugfix.

Fixes #1821. Fixes #1808.
---
 .babelrc                 |  1 +
 CHANGELOG.md             |  2 ++
 docs/rules/order.md      |  9 +++--
 src/rules/order.js       | 32 ++++++++++-------
 tests/src/cli.js         |  4 +--
 tests/src/rules/order.js | 75 ++++++++++++++++++++++++++++++++++++++--
 6 files changed, 104 insertions(+), 19 deletions(-)

diff --git a/.babelrc b/.babelrc
index 2cbf5c811c..604f307fee 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,6 +1,7 @@
 {
   "presets": [ "es2015-argon" ],
   "sourceMaps": "inline",
+  "retainLines": true,
   "env": {
     "test": {
       "plugins": [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef8bffd8af..8dbb5376ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: consider exported TypeScript interfaces, types and enums ([#1819], thanks [@nicolashenry])
 
 ### Fixed
+- [`order`]/TypeScript: properly support `import = object` expressions ([#1823], thanks [@manuth])
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing type from dev dependencies ([#1820], thanks [@fernandopasik])
 - [`default`]: avoid crash with `export =` ([#1822], thanks [@AndrewLeedham])
 
@@ -712,6 +713,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1824]: https://github.com/benmosher/eslint-plugin-import/pull/1824
+[#1823]: https://github.com/benmosher/eslint-plugin-import/pull/1823
 [#1822]: https://github.com/benmosher/eslint-plugin-import/pull/1822
 [#1820]: https://github.com/benmosher/eslint-plugin-import/pull/1820
 [#1819]: https://github.com/benmosher/eslint-plugin-import/pull/1819
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 3aa41bbf50..7d91efd6f5 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -22,6 +22,8 @@ import bar from './bar';
 import baz from './bar/baz';
 // 6. "index" of the current directory
 import main from './';
+// 7. "object"-imports (only available in TypeScript)
+import log = console.log;
 ```
 
 Unassigned imports are ignored, as the order they are imported in may be important.
@@ -77,12 +79,15 @@ This rule supports the following options:
 
 ### `groups: [array]`:
 
-How groups are defined, and the order to respect. `groups` must be an array of `string` or [`string`]. The only allowed `string`s are: `"builtin"`, `"external"`, `"internal"`, `"unknown"`, `"parent"`, `"sibling"`, `"index"`. The enforced order is the same as the order of each element in a group. Omitted types are implicitly grouped together as the last element. Example:
+How groups are defined, and the order to respect. `groups` must be an array of `string` or [`string`]. The only allowed `string`s are:
+`"builtin"`, `"external"`, `"internal"`, `"unknown"`, `"parent"`, `"sibling"`, `"index"`, `"object"`.
+The enforced order is the same as the order of each element in a group. Omitted types are implicitly grouped together as the last element. Example:
 ```js
 [
   'builtin', // Built-in types are first
   ['sibling', 'parent'], // Then sibling and parent types. They can be mingled together
   'index', // Then the index file
+  'object',
   // Then the rest: internal and external type
 ]
 ```
@@ -91,7 +96,7 @@ The default value is `["builtin", "external", "parent", "sibling", "index"]`.
 You can set the options like this:
 
 ```js
-"import/order": ["error", {"groups": ["index", "sibling", "parent", "internal", "external", "builtin"]}]
+"import/order": ["error", {"groups": ["index", "sibling", "parent", "internal", "external", "builtin", "object"]}]
 ```
 
 ### `pathGroups: [array of objects]`:
diff --git a/src/rules/order.js b/src/rules/order.js
index b407145405..7f0160fe10 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -248,14 +248,14 @@ function makeOutOfOrderReport(context, imported) {
 }
 
 function getSorter(ascending) {
-  let multiplier = (ascending ? 1 : -1)
+  const multiplier = ascending ? 1 : -1
 
   return function importsSorter(importA, importB) {
     let result
 
-    if ((importA < importB) || importB === null) {
+    if (importA < importB) {
       result = -1
-    } else if ((importA > importB) || importA === null) {
+    } else if (importA > importB) {
       result = 1
     } else {
       result = 0
@@ -310,8 +310,13 @@ function computePathRank(ranks, pathGroups, path, maxPosition) {
   }
 }
 
-function computeRank(context, ranks, name, type, excludedImportTypes) {
-  const impType = importType(name, context)
+function computeRank(context, node, ranks, name, type, excludedImportTypes) {
+  let impType
+  if (type === 'import:object') {
+    impType = 'object'
+  } else {
+    impType = importType(name, context)
+  }
   let rank
   if (!excludedImportTypes.has(impType)) {
     rank = computePathRank(ranks.groups, ranks.pathGroups, name, ranks.maxPosition)
@@ -319,7 +324,7 @@ function computeRank(context, ranks, name, type, excludedImportTypes) {
   if (typeof rank === 'undefined') {
     rank = ranks.groups[impType]
   }
-  if (type !== 'import') {
+  if (type !== 'import' && !type.startsWith('import:')) {
     rank += 100
   }
 
@@ -327,7 +332,7 @@ function computeRank(context, ranks, name, type, excludedImportTypes) {
 }
 
 function registerNode(context, node, name, type, ranks, imported, excludedImportTypes) {
-  const rank = computeRank(context, ranks, name, type, excludedImportTypes)
+  const rank = computeRank(context, node, ranks, name, type, excludedImportTypes)
   if (rank !== -1) {
     imported.push({name, rank, node})
   }
@@ -338,7 +343,7 @@ function isInVariableDeclarator(node) {
     (node.type === 'VariableDeclarator' || isInVariableDeclarator(node.parent))
 }
 
-const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index']
+const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object']
 
 // Creates an object with type-rank pairs.
 // Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
@@ -563,7 +568,7 @@ module.exports = {
   create: function importOrderRule (context) {
     const options = context.options[0] || {}
     const newlinesBetweenImports = options['newlines-between'] || 'ignore'
-    const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external'])
+    const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external', 'object'])
     const alphabetize = getAlphabetizeConfig(options)
     let ranks
 
@@ -609,18 +614,19 @@ module.exports = {
       },
       TSImportEqualsDeclaration: function handleImports(node) {
         let name
+        let type
         if (node.moduleReference.type === 'TSExternalModuleReference') {
           name = node.moduleReference.expression.value
-        } else if (node.isExport) {
-          name = node.moduleReference.name
+          type = 'import'
         } else {
-          name = null
+          name = context.getSourceCode().getText(node.moduleReference)
+          type = 'import:object'
         }
         registerNode(
           context,
           node,
           name,
-          'import',
+          type,
           ranks,
           imported,
           pathGroupsExcludedImportTypes
diff --git a/tests/src/cli.js b/tests/src/cli.js
index 5e0a74e36c..9a2d796ade 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -58,14 +58,14 @@ describe('CLI regression tests', function () {
                 nodeType: results.results[0].messages[0].nodeType, // we don't care about this one
                 ruleId: 'json/*',
                 severity: 2,
-                source: '\n',
+                source: results.results[0].messages[0].source, // NewLine-characters might differ depending on git-settings
               },
             ],
             errorCount: 1,
             warningCount: 0,
             fixableErrorCount: 0,
             fixableWarningCount: 0,
-            source: ',\n',
+            source: results.results[0].source, // NewLine-characters might differ depending on git-settings
           },
         ],
         errorCount: 1,
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index e8ee82ec6c..281baa2c90 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -711,6 +711,49 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    ...flatMap(getTSParsers, parser => [
+      // Order of the `import ... = require(...)` syntax
+      test({
+        code: `
+          import blah = require('./blah');
+          import { hello } from './hello';`,
+        parser,
+        options: [
+          {
+            alphabetize: {
+              order: 'asc',
+            },
+          },
+        ],
+      }),
+      // Order of object-imports
+      test({
+        code: `
+          import blah = require('./blah');
+          import log = console.log;`,
+        parser,
+        options: [
+          {
+            alphabetize: {
+              order: 'asc',
+            },
+          },
+        ],
+      }),
+      test({
+        code: `
+          import debug = console.debug;
+          import log = console.log;`,
+        parser,
+        options: [
+          {
+            alphabetize: {
+              order: 'asc',
+            },
+          },
+        ],
+      }),
+    ]),
   ],
   invalid: [
     // builtin before external module (require)
@@ -1167,6 +1210,7 @@ ruleTester.run('order', rule, {
       }],
     }),
     ...flatMap(getTSParsers(), parser => [
+      // Order of the `import ... = require(...)` syntax
       test({
         code: `
           var fs = require('fs');
@@ -1183,7 +1227,7 @@ ruleTester.run('order', rule, {
           message: '`fs` import should occur after import of `../foo/bar`',
         }],
       }),
-      {
+      test({
         code: `
           var async = require('async');
           var fs = require('fs');
@@ -1196,7 +1240,7 @@ ruleTester.run('order', rule, {
         errors: [{
           message: '`fs` import should occur before import of `async`',
         }],
-      },
+      }),
       test({
         code: `
           import sync = require('sync');
@@ -1219,6 +1263,33 @@ ruleTester.run('order', rule, {
           message: '`async` import should occur before import of `sync`',
         }],
       }),
+      // Order of object-imports
+      test({
+        code: `
+          import log = console.log;
+          import blah = require('./blah');`,
+        parser,
+        errors: [{
+          message: '`./blah` import should occur before import of `console.log`',
+        }],
+      }),
+      // Alphabetization of object-imports
+      test({
+        code: `
+          import log = console.log;
+          import debug = console.debug;`,
+        parser,
+        errors: [{
+          message: '`console.debug` import should occur before import of `console.log`',
+        }],
+        options: [
+          {
+            alphabetize: {
+              order: 'asc',
+            },
+          },
+        ],
+      }),
     ]),
     // Default order using import with custom import alias
     test({

From 44b42c028fa1ce7d44238e5f1dc1824ec03f6554 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 16 Jun 2020 10:26:03 -0700
Subject: [PATCH 185/767] [resolvers/webpack] v0.12.2

---
 resolvers/webpack/CHANGELOG.md | 9 +++++++++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index e06203823d..5b31c350ac 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,9 +5,16 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## 0.12.2 - 2020-06-16
+
 ### Fixed
 - [fix] provide config fallback ([#1705], thanks [@migueloller])
 
+## 0.12.1 - 2020-01-10
+
+### Changed
+- [meta] copy LICENSE file to all npm packages on prepublish ([#1595], thanks [@opichals])
+
 ## 0.12.0 - 2019-12-07
 
 ### Added
@@ -126,6 +133,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
   Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
 [#1705]: https://github.com/benmosher/eslint-plugin-import/pull/1705
+[#1595]: https://github.com/benmosher/eslint-plugin-import/pull/1595
 [#1503]: https://github.com/benmosher/eslint-plugin-import/pull/1503
 [#1297]: https://github.com/benmosher/eslint-plugin-import/pull/1297
 [#1261]: https://github.com/benmosher/eslint-plugin-import/pull/1261
@@ -179,3 +187,4 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@echenley]: https://github.com/echenley
 [@Aghassi]: https://github.com/Aghassi
 [@migueloller]: https://github.com/migueloller
+[@opichals]: https://github.com/opichals
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 72959fa886..7de2690b2d 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.12.1",
+  "version": "0.12.2",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 4a38ef4f65d7cbc241527eea45ad48db14c75a70 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 16 Jun 2020 10:30:01 -0700
Subject: [PATCH 186/767] [resolvers/node] v0.3.4

---
 resolvers/node/CHANGELOG.md | 8 ++++++++
 resolvers/node/package.json | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index 1418844082..8fa31bed7d 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -4,9 +4,15 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## Unreleased
+
+## v0.3.4 - 2020-06-16
 ### Added
 - add `.node` extension ([#1663])
 
+## v0.3.3 - 2020-01-10
+### Changed
+- [meta] copy LICENSE file to all npm packages on prepublish ([#1595], thanks [@opichals])
+
 ## v0.3.2 - 2018-01-05
 ### Added
 - `.mjs` extension detected by default to support `experimental-modules` ([#939])
@@ -45,6 +51,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [#438]: https://github.com/benmosher/eslint-plugin-import/pull/438
 
 [#1663]: https://github.com/benmosher/eslint-plugin-import/issues/1663
+[#1595]: https://github.com/benmosher/eslint-plugin-import/pull/1595
 [#939]: https://github.com/benmosher/eslint-plugin-import/issues/939
 [#531]: https://github.com/benmosher/eslint-plugin-import/issues/531
 [#437]: https://github.com/benmosher/eslint-plugin-import/issues/437
@@ -53,3 +60,4 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@lukeapage]: https://github.com/lukeapage
 [@SkeLLLa]: https://github.com/SkeLLLa
 [@ljharb]: https://github.com/ljharb
+[@opichals]: https://github.com/opichals
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 03eadafbf6..27daa907f9 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-node",
-  "version": "0.3.3",
+  "version": "0.3.4",
   "description": "Node default behavior import resolution plugin for eslint-plugin-import.",
   "main": "index.js",
   "files": [

From 296262842b52a50c5b107ba91bb2d13c05b2a104 Mon Sep 17 00:00:00 2001
From: be5invis <belleve@typeof.net>
Date: Thu, 18 Jun 2020 22:48:52 -0700
Subject: [PATCH 187/767] [Fix] `order`/`newline-after-import`: ignore
 TypeScript's "export import object"

Co-authored-by: be5invis <belleve@typeof.net>
Co-authored-by: Manuel Thalmann <m@nuth.ch>
---
 CHANGELOG.md                            |  3 +++
 src/rules/newline-after-import.js       |  7 ++++++-
 src/rules/order.js                      |  4 ++++
 tests/src/rules/newline-after-import.js | 18 ++++++++++++++++++
 tests/src/rules/order.js                | 15 +++++++++++++++
 5 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dbb5376ff..32c1753ead 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]/TypeScript: properly support `import = object` expressions ([#1823], thanks [@manuth])
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing type from dev dependencies ([#1820], thanks [@fernandopasik])
 - [`default`]: avoid crash with `export =` ([#1822], thanks [@AndrewLeedham])
+- [`order`]/[`newline-after-import`]: ignore TypeScript's "export import object" ([#1830], thanks [@be5invis])
 
 ### Changed
 - [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
@@ -712,6 +713,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1830]: https://github.com/benmosher/eslint-plugin-import/pull/1830
 [#1824]: https://github.com/benmosher/eslint-plugin-import/pull/1824
 [#1823]: https://github.com/benmosher/eslint-plugin-import/pull/1823
 [#1822]: https://github.com/benmosher/eslint-plugin-import/pull/1822
@@ -1235,3 +1237,4 @@ for info on changes for earlier releases.
 [@fernandopasik]: https://github.com/fernandopasik
 [@taye]: https://github.com/taye
 [@AndrewLeedham]: https://github.com/AndrewLeedham
+[@be5invis]: https://github.com/be5invis
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 8255b189cc..0336b0dc25 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -119,8 +119,13 @@ after ${type} statement not followed by another ${type}.`,
         const { parent } = node
         const nodePosition = parent.body.indexOf(node)
         const nextNode = parent.body[nodePosition + 1]
+        
+        // skip "export import"s
+        if (node.type === 'TSImportEqualsDeclaration' && node.isExport) {
+          return
+        }
 
-        if (nextNode && nextNode.type !== 'ImportDeclaration' && nextNode.type !== 'TSImportEqualsDeclaration') {
+        if (nextNode && nextNode.type !== 'ImportDeclaration' && (nextNode.type !== 'TSImportEqualsDeclaration' || nextNode.isExport)) {
           checkForNewLine(node, nextNode, 'import')
         }
     }
diff --git a/src/rules/order.js b/src/rules/order.js
index 7f0160fe10..15b266ca9b 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -615,6 +615,10 @@ module.exports = {
       TSImportEqualsDeclaration: function handleImports(node) {
         let name
         let type
+        // skip "export import"s
+        if (node.isExport) {
+          return
+        }
         if (node.moduleReference.type === 'TSExternalModuleReference') {
           name = node.moduleReference.expression.value
           type = 'import'
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 626e6e0261..fcd7c72a9f 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -213,6 +213,24 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         parser: parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
+      {
+        code: `
+          export import a = obj;\nf(a);
+        `,
+        parser: parser,
+        parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      },
+      {
+        code: `
+          import { a } from "./a";
+
+          export namespace SomeNamespace {
+              export import a2 = a;
+              f(a);
+          }`,
+        parser: parser,
+        parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      },
     ]),
   ],
 
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 281baa2c90..25d046b51d 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -753,6 +753,21 @@ ruleTester.run('order', rule, {
           },
         ],
       }),
+      test({
+        code: `
+          import { a } from "./a";
+          export namespace SomeNamespace {
+              export import a2 = a;
+          }
+        `,
+        parser,
+        options: [
+          {
+            groups: ['external', 'index'],
+            alphabetize: { order: 'asc' },
+          },
+        ],
+      }),
     ]),
   ],
   invalid: [

From 4d6c5394286e40bd239abca26ae23823727a6485 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noe=CC=81=20Lebrun?= <lebrun.noe@icloud.com>
Date: Sun, 21 Jun 2020 01:53:44 +0200
Subject: [PATCH 188/767] [Fix] `dynamic-import-chunkname`/TypeScript: support
 `@typescript-eslint/parser`

Fixes #1771.
---
 .travis.yml                                 |   3 +
 CHANGELOG.md                                |   3 +
 package.json                                |   2 +-
 src/rules/dynamic-import-chunkname.js       | 117 ++++----
 tests/src/rules/dynamic-import-chunkname.js | 308 +++++++++++++++++++-
 5 files changed, 376 insertions(+), 57 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index fda8f0a5a6..5aec9ffcad 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,6 +23,9 @@ matrix:
   include:
   - env: LINT=true
     node_js: lts/*
+  - env: TS_PARSER=2 ESLINT_VERSION=7
+    node_js: lts/*
+    before_script: 'npm install --no-save @typescript-eslint/parser@2'
   - env: PACKAGE=resolvers/node
     node_js: 14
   - env: PACKAGE=resolvers/node
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32c1753ead..9256cd7f9b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing type from dev dependencies ([#1820], thanks [@fernandopasik])
 - [`default`]: avoid crash with `export =` ([#1822], thanks [@AndrewLeedham])
 - [`order`]/[`newline-after-import`]: ignore TypeScript's "export import object" ([#1830], thanks [@be5invis])
+- [`dynamic-import-chunkname`]/TypeScript: supports `@typescript-eslint/parser` ([#1833], thanks [@noelebrun])
 
 ### Changed
 - [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
@@ -713,6 +714,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1833]: https://github.com/benmosher/eslint-plugin-import/pull/1833
 [#1830]: https://github.com/benmosher/eslint-plugin-import/pull/1830
 [#1824]: https://github.com/benmosher/eslint-plugin-import/pull/1824
 [#1823]: https://github.com/benmosher/eslint-plugin-import/pull/1823
@@ -1238,3 +1240,4 @@ for info on changes for earlier releases.
 [@taye]: https://github.com/taye
 [@AndrewLeedham]: https://github.com/AndrewLeedham
 [@be5invis]: https://github.com/be5invis
+[@noelebrun]: https://github.com/noelebrun
diff --git a/package.json b/package.json
index 9b42324f66..4bc07ee707 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
   "devDependencies": {
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
-    "@typescript-eslint/parser": "^2.23.0",
+    "@typescript-eslint/parser": "^2.23.0 || ^3.3.0",
     "array.prototype.flatmap": "^1.2.3",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 40b99239ab..cff4b1c2a1 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -34,78 +34,85 @@ module.exports = {
     const chunkSubstrFormat = ` webpackChunkName: "${webpackChunknameFormat}",? `
     const chunkSubstrRegex = new RegExp(chunkSubstrFormat)
 
-    return {
-      CallExpression(node) {
-        if (node.callee.type !== 'Import' && importFunctions.indexOf(node.callee.name) < 0) {
-          return
-        }
+    function run(node, arg) {
+      const sourceCode = context.getSourceCode()
+      const leadingComments = sourceCode.getCommentsBefore
+        ? sourceCode.getCommentsBefore(arg) // This method is available in ESLint >= 4.
+        : sourceCode.getComments(arg).leading // This method is deprecated in ESLint 7.
 
-        const sourceCode = context.getSourceCode()
-        const arg = node.arguments[0]
-        const leadingComments = sourceCode.getCommentsBefore
-          ? sourceCode.getCommentsBefore(arg) // This method is available in ESLint >= 4.
-          : sourceCode.getComments(arg).leading // This method is deprecated in ESLint 7.
+      if (!leadingComments || leadingComments.length === 0) {
+        context.report({
+          node,
+          message: 'dynamic imports require a leading comment with the webpack chunkname',
+        })
+        return
+      }
 
-        if (!leadingComments || leadingComments.length === 0) {
+      let isChunknamePresent = false
+
+      for (const comment of leadingComments) {
+        if (comment.type !== 'Block') {
           context.report({
             node,
-            message: 'dynamic imports require a leading comment with the webpack chunkname',
+            message: 'dynamic imports require a /* foo */ style comment, not a // foo comment',
           })
           return
         }
 
-        let isChunknamePresent = false
-
-        for (const comment of leadingComments) {
-          if (comment.type !== 'Block') {
-            context.report({
-              node,
-              message: 'dynamic imports require a /* foo */ style comment, not a // foo comment',
-            })
-            return
-          }
-
-          if (!paddedCommentRegex.test(comment.value)) {
-            context.report({
-              node,
-              message: `dynamic imports require a block comment padded with spaces - /* foo */`,
-            })
-            return
-          }
-
-          try {
-            // just like webpack itself does
-            vm.runInNewContext(`(function(){return {${comment.value}}})()`)
-          }
-          catch (error) {
-            context.report({
-              node,
-              message: `dynamic imports require a "webpack" comment with valid syntax`,
-            })
-            return
-          }
-
-          if (!commentStyleRegex.test(comment.value)) {
-            context.report({
-              node,
-              message:
-                `dynamic imports require a leading comment in the form /*${chunkSubstrFormat}*/`,
-            })
-            return
-          }
+        if (!paddedCommentRegex.test(comment.value)) {
+          context.report({
+            node,
+            message: `dynamic imports require a block comment padded with spaces - /* foo */`,
+          })
+          return
+        }
 
-          if (chunkSubstrRegex.test(comment.value)) {
-            isChunknamePresent = true
-          }
+        try {
+          // just like webpack itself does
+          vm.runInNewContext(`(function(){return {${comment.value}}})()`)
+        }
+        catch (error) {
+          context.report({
+            node,
+            message: `dynamic imports require a "webpack" comment with valid syntax`,
+          })
+          return
         }
 
-        if (!isChunknamePresent) {
+        if (!commentStyleRegex.test(comment.value)) {
           context.report({
             node,
             message:
               `dynamic imports require a leading comment in the form /*${chunkSubstrFormat}*/`,
           })
+          return
         }
+
+        if (chunkSubstrRegex.test(comment.value)) {
+          isChunknamePresent = true
+        }
+      }
+
+      if (!isChunknamePresent) {
+        context.report({
+          node,
+          message:
+            `dynamic imports require a leading comment in the form /*${chunkSubstrFormat}*/`,
+        })
+      }
+    }
+
+    return {
+      ImportExpression(node) {
+        run(node, node.source)
+      },
+
+      CallExpression(node) {
+        if (node.callee.type !== 'Import' && importFunctions.indexOf(node.callee.name) < 0) {
+          return
+        }
+
+        run(node, node.arguments[0])
       },
     }
   },
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index e8cbb9c6f9..938f542e91 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -1,5 +1,6 @@
-import { SYNTAX_CASES } from '../utils'
+import { SYNTAX_CASES, getTSParsers } from '../utils'
 import { RuleTester } from 'eslint'
+import semver from 'semver'
 
 const rule = require('rules/dynamic-import-chunkname')
 const ruleTester = new RuleTester()
@@ -482,3 +483,308 @@ ruleTester.run('dynamic-import-chunkname', rule, {
     },
   ],
 })
+
+context('TypeScript', () => {
+  getTSParsers().forEach((typescriptParser) => {
+    const nodeType = typescriptParser.includes('typescript-eslint-parser') || (typescriptParser.includes('@typescript-eslint/parser') && semver.satisfies(require('@typescript-eslint/parser/package.json').version, '^2'))
+      ? 'CallExpression'
+      : 'ImportExpression'
+
+    ruleTester.run('dynamic-import-chunkname', rule, {
+      valid: [
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "Some_Other_Module" */
+            "test"
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "SomeModule123" */
+            "test"
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule", webpackPrefetch: true */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule", webpackPrefetch: true, */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: true, webpackChunkName: "someModule" */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: true, webpackChunkName: "someModule", */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: true */
+            /* webpackChunkName: "someModule" */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackPrefetch: true */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options: pickyCommentOptions,
+          parser: typescriptParser,
+          errors: [{
+            message: pickyCommentFormatError,
+            type: nodeType,
+          }],
+        },
+      ],
+      invalid: [
+        {
+          code: `import(
+            // webpackChunkName: "someModule"
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            // webpackChunkName: "someModule"
+            'someModule'
+          )`,
+          errors: [{
+            message: nonBlockCommentError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: 'import(\'test\')',
+          options,
+          parser: typescriptParser,
+          output: 'import(\'test\')',
+          errors: [{
+            message: noLeadingCommentError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName: someModule */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName: someModule */
+            'someModule'
+          )`,
+          errors: [{
+            message: invalidSyntaxCommentError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName: 'someModule' */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName: 'someModule' */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: invalidSyntaxCommentError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName:"someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName:"someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /*webpackChunkName: "someModule"*/
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /*webpackChunkName: "someModule"*/
+            'someModule'
+          )`,
+          errors: [{
+            message: noPaddingCommentError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName  :  "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName  :  "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" ; */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName: "someModule" ; */
+            'someModule'
+          )`,
+          errors: [{
+            message: invalidSyntaxCommentError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* totally not webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* totally not webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: invalidSyntaxCommentError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: true */
+            /* webpackChunk: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackPrefetch: true */
+            /* webpackChunk: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: true, webpackChunk: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackPrefetch: true, webpackChunk: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule123" */
+            'someModule'
+          )`,
+          options: pickyCommentOptions,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName: "someModule123" */
+            'someModule'
+          )`,
+          errors: [{
+            message: pickyCommentFormatError,
+            type: nodeType,
+          }],
+        },
+      ],
+    })
+  })
+})

From bfc50b72d4a5f390fbd8f2ba8aa7183a24995dc8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 22 Jun 2020 13:07:23 -0700
Subject: [PATCH 189/767] =?UTF-8?q?[New]=20`no-cycle`:=20allow=20`maxDepth?=
 =?UTF-8?q?`=20option=20to=20be=20`"=E2=88=9E"`?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md                |  1 +
 docs/rules/no-cycle.md      |  2 +-
 src/rules/no-cycle.js       | 18 +++++++++++++-----
 tests/src/rules/no-cycle.js | 10 ++++++++++
 4 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9256cd7f9b..97473c44e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 ### Added
 - [`no-unused-modules`]: consider exported TypeScript interfaces, types and enums ([#1819], thanks [@nicolashenry])
+- [`no-cycle`]: allow `maxDepth` option to be `"∞"` (thanks [@ljharb])
 
 ### Fixed
 - [`order`]/TypeScript: properly support `import = object` expressions ([#1823], thanks [@manuth])
diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md
index 6329bb272e..7d54e81ff8 100644
--- a/docs/rules/no-cycle.md
+++ b/docs/rules/no-cycle.md
@@ -2,7 +2,7 @@
 
 Ensures that there is no resolvable path back to this module via its dependencies.
 
-This includes cycles of depth 1 (imported module imports me) to `Infinity`, if the
+This includes cycles of depth 1 (imported module imports me) to `"∞"` (or `Infinity`), if the
 [`maxDepth`](#maxdepth) option is not set.
 
 ```js
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 8f39246b5c..2ad381e91a 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -14,10 +14,18 @@ module.exports = {
     type: 'suggestion',
     docs: { url: docsUrl('no-cycle') },
     schema: [makeOptionsSchema({
-      maxDepth:{
-        description: 'maximum dependency depth to traverse',
-        type: 'integer',
-        minimum: 1,
+      maxDepth: {
+        oneOf: [
+          {
+            description: 'maximum dependency depth to traverse',
+            type: 'integer',
+            minimum: 1,
+          },
+          {
+            enum: ['∞'],
+            type: 'string',
+          },
+        ],
       },
       ignoreExternal: {
         description: 'ignore external modules',
@@ -32,7 +40,7 @@ module.exports = {
     if (myPath === '<text>') return {} // can't cycle-check a non-file
 
     const options = context.options[0] || {}
-    const maxDepth = options.maxDepth || Infinity
+    const maxDepth = typeof options.maxDepth === 'number' ? options.maxDepth : Infinity
     const ignoreModule = (name) => options.ignoreExternal ? isExternalModule(name) : false
 
     function checkSourceValue(sourceNode, importer) {
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index b0f4153e8d..2539ba5945 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -161,6 +161,16 @@ ruleTester.run('no-cycle', rule, {
       parser: require.resolve('babel-eslint'),
       errors: [error(`Dependency cycle via ./flow-types-depth-two:4=>./depth-one:1`)],
     }),
+    test({
+      code: 'import { foo } from "./depth-two"',
+      options: [{ maxDepth: Infinity }],
+      errors: [error(`Dependency cycle via ./depth-one:1`)],
+    }),
+    test({
+      code: 'import { foo } from "./depth-two"',
+      options: [{ maxDepth: '∞' }],
+      errors: [error(`Dependency cycle via ./depth-one:1`)],
+    }),
   ],
 })
 // })

From c38b1699f8e8c7e615fb84b54a90baac8e464f58 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Fri, 19 Jun 2020 12:36:32 +0200
Subject: [PATCH 190/767] [patch] `order`/TypeScript: ignore ordering of object
 imports

---
 CHANGELOG.md             |  2 ++
 src/rules/order.js       | 67 ++++++++++++++++++++++------------------
 tests/src/rules/order.js | 31 +++++++++----------
 3 files changed, 53 insertions(+), 47 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 97473c44e8..4dc09b1c55 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`default`]: avoid crash with `export =` ([#1822], thanks [@AndrewLeedham])
 - [`order`]/[`newline-after-import`]: ignore TypeScript's "export import object" ([#1830], thanks [@be5invis])
 - [`dynamic-import-chunkname`]/TypeScript: supports `@typescript-eslint/parser` ([#1833], thanks [@noelebrun])
+- [`order`]/TypeScript: ignore ordering of object imports ([#1831], thanks [@manuth])
 
 ### Changed
 - [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
@@ -716,6 +717,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1833]: https://github.com/benmosher/eslint-plugin-import/pull/1833
+[#1831]: https://github.com/benmosher/eslint-plugin-import/pull/1831
 [#1830]: https://github.com/benmosher/eslint-plugin-import/pull/1830
 [#1824]: https://github.com/benmosher/eslint-plugin-import/pull/1824
 [#1823]: https://github.com/benmosher/eslint-plugin-import/pull/1823
diff --git a/src/rules/order.js b/src/rules/order.js
index 15b266ca9b..1d7d3efd62 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -11,11 +11,7 @@ const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index']
 
 function reverse(array) {
   return array.map(function (v) {
-    return {
-      name: v.name,
-      rank: -v.rank,
-      node: v.node,
-    }
+    return Object.assign({}, v, { rank: -v.rank })
   }).reverse()
 }
 
@@ -197,8 +193,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
     newCode = newCode + '\n'
   }
 
-  const message = '`' + secondNode.name + '` import should occur ' + order +
-      ' import of `' + firstNode.name + '`'
+  const message = `\`${secondNode.displayName}\` import should occur ${order} import of \`${firstNode.displayName}\``
 
   if (order === 'before') {
     context.report({
@@ -270,7 +265,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
     if (!Array.isArray(acc[importedItem.rank])) {
       acc[importedItem.rank] = []
     }
-    acc[importedItem.rank].push(importedItem.name)
+    acc[importedItem.rank].push(importedItem.value)
     return acc
   }, {})
 
@@ -295,7 +290,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
 
   // mutate the original group-rank with alphabetized-rank
   imported.forEach(function(importedItem) {
-    importedItem.rank = alphabetizedRanks[importedItem.name]
+    importedItem.rank = alphabetizedRanks[importedItem.value]
   })
 }
 
@@ -310,31 +305,31 @@ function computePathRank(ranks, pathGroups, path, maxPosition) {
   }
 }
 
-function computeRank(context, node, ranks, name, type, excludedImportTypes) {
+function computeRank(context, ranks, importEntry, excludedImportTypes) {
   let impType
-  if (type === 'import:object') {
+  let rank
+  if (importEntry.type === 'import:object') {
     impType = 'object'
   } else {
-    impType = importType(name, context)
+    impType = importType(importEntry.value, context)
   }
-  let rank
   if (!excludedImportTypes.has(impType)) {
-    rank = computePathRank(ranks.groups, ranks.pathGroups, name, ranks.maxPosition)
+    rank = computePathRank(ranks.groups, ranks.pathGroups, importEntry.value, ranks.maxPosition)
   }
   if (typeof rank === 'undefined') {
     rank = ranks.groups[impType]
   }
-  if (type !== 'import' && !type.startsWith('import:')) {
+  if (importEntry.type !== 'import' && !importEntry.type.startsWith('import:')) {
     rank += 100
   }
 
   return rank
 }
 
-function registerNode(context, node, name, type, ranks, imported, excludedImportTypes) {
-  const rank = computeRank(context, node, ranks, name, type, excludedImportTypes)
+function registerNode(context, importEntry, ranks, imported, excludedImportTypes) {
+  const rank = computeRank(context, ranks, importEntry, excludedImportTypes)
   if (rank !== -1) {
-    imported.push({name, rank, node})
+    imported.push(Object.assign({}, importEntry, { rank }))
   }
 }
 
@@ -603,9 +598,12 @@ module.exports = {
           const name = node.source.value
           registerNode(
             context,
-            node,
-            name,
-            'import',
+            {
+              node,
+              value: name,
+              displayName: name,
+              type: 'import',
+            },
             ranks,
             imported,
             pathGroupsExcludedImportTypes
@@ -613,24 +611,30 @@ module.exports = {
         }
       },
       TSImportEqualsDeclaration: function handleImports(node) {
-        let name
+        let displayName
+        let value
         let type
         // skip "export import"s
         if (node.isExport) {
           return
         }
         if (node.moduleReference.type === 'TSExternalModuleReference') {
-          name = node.moduleReference.expression.value
+          value = node.moduleReference.expression.value
+          displayName = value
           type = 'import'
         } else {
-          name = context.getSourceCode().getText(node.moduleReference)
+          value = ''
+          displayName = context.getSourceCode().getText(node.moduleReference)
           type = 'import:object'
         }
         registerNode(
           context,
-          node,
-          name,
-          type,
+          {
+            node,
+            value,
+            displayName,
+            type,
+          },
           ranks,
           imported,
           pathGroupsExcludedImportTypes
@@ -643,9 +647,12 @@ module.exports = {
         const name = node.arguments[0].value
         registerNode(
           context,
-          node,
-          name,
-          'require',
+          {
+            node,
+            value: name,
+            displayName: name,
+            type: 'require',
+          },
           ranks,
           imported,
           pathGroupsExcludedImportTypes
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 25d046b51d..0c5405823f 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -740,6 +740,7 @@ ruleTester.run('order', rule, {
           },
         ],
       }),
+      // Object-imports should not be forced to be alphabetized
       test({
         code: `
           import debug = console.debug;
@@ -753,6 +754,19 @@ ruleTester.run('order', rule, {
           },
         ],
       }),
+      test({
+        code: `
+          import log = console.log;
+          import debug = console.debug;`,
+        parser,
+        options: [
+          {
+            alphabetize: {
+              order: 'asc',
+            },
+          },
+        ],
+      }),
       test({
         code: `
           import { a } from "./a";
@@ -1288,23 +1302,6 @@ ruleTester.run('order', rule, {
           message: '`./blah` import should occur before import of `console.log`',
         }],
       }),
-      // Alphabetization of object-imports
-      test({
-        code: `
-          import log = console.log;
-          import debug = console.debug;`,
-        parser,
-        errors: [{
-          message: '`console.debug` import should occur before import of `console.log`',
-        }],
-        options: [
-          {
-            alphabetize: {
-              order: 'asc',
-            },
-          },
-        ],
-      }),
     ]),
     // Default order using import with custom import alias
     test({

From 2468f101dafb73b471dcfb0f929f1ea75301423d Mon Sep 17 00:00:00 2001
From: Beatriz Rezener <beatrizrezener@gmail.com>
Date: Tue, 23 Jun 2020 13:43:46 -0300
Subject: [PATCH 191/767] [docs] `no-default-export`: Fix docs url

Added docsUrl to no-default-export rule

Closes #1769

Signed-off-by: Beatriz Rezener <beatrizrezener@gmail.com>
---
 CHANGELOG.md                   | 3 +++
 src/rules/no-default-export.js | 6 +++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4dc09b1c55..8be96cf9d1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Changed
 - [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
+- [docs] [`no-default-export`]: Fix docs url ([#1836], thanks [@beatrizrezener])
 
 ## [2.21.2] - 2020-06-09
 ### Fixed
@@ -716,6 +717,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
 [#1833]: https://github.com/benmosher/eslint-plugin-import/pull/1833
 [#1831]: https://github.com/benmosher/eslint-plugin-import/pull/1831
 [#1830]: https://github.com/benmosher/eslint-plugin-import/pull/1830
@@ -1244,3 +1246,4 @@ for info on changes for earlier releases.
 [@AndrewLeedham]: https://github.com/AndrewLeedham
 [@be5invis]: https://github.com/be5invis
 [@noelebrun]: https://github.com/noelebrun
+[@beatrizrezener]: https://github.com/beatrizrezener
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index 0a46fd35f7..fdc709696d 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -1,7 +1,11 @@
+import docsUrl from '../docsUrl'
+
 module.exports = {
   meta: {
     type: 'suggestion',
-    docs: {},
+    docs: {
+      url: docsUrl('no-default-export'),
+    },
     schema: [],
   },
 

From a6cd6bdc112f4611ed8b1b22de51faaa487c6af0 Mon Sep 17 00:00:00 2001
From: Beatriz Rezener <beatrizrezener@gmail.com>
Date: Tue, 23 Jun 2020 12:29:29 -0300
Subject: [PATCH 192/767] [docs] `imports-first`: deprecation info and link to
 `first` docs

Closes #1638.

Signed-off-by: Beatriz Rezener <beatrizrezener@gmail.com>
---
 CHANGELOG.md                | 2 ++
 docs/rules/imports-first.md | 3 +++
 2 files changed, 5 insertions(+)
 create mode 100644 docs/rules/imports-first.md

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8be96cf9d1..f126e45d1e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
 - [docs] [`no-default-export`]: Fix docs url ([#1836], thanks [@beatrizrezener])
+- [docs] [`imports-first`]: deprecation info and link to `first` docs ([#1835], thanks [@beatrizrezener])
 
 ## [2.21.2] - 2020-06-09
 ### Fixed
@@ -718,6 +719,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
+[#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
 [#1833]: https://github.com/benmosher/eslint-plugin-import/pull/1833
 [#1831]: https://github.com/benmosher/eslint-plugin-import/pull/1831
 [#1830]: https://github.com/benmosher/eslint-plugin-import/pull/1830
diff --git a/docs/rules/imports-first.md b/docs/rules/imports-first.md
new file mode 100644
index 0000000000..b7f20754af
--- /dev/null
+++ b/docs/rules/imports-first.md
@@ -0,0 +1,3 @@
+# imports-first
+
+This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md).

From a963e8de03534d6c9c870c62b53e1401535cd75c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 23 Jun 2020 13:15:41 -0700
Subject: [PATCH 193/767] [Refactor] `namespace`: clean up the code a bit

---
 src/rules/namespace.js | 70 ++++++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 34 deletions(-)

diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index dd840b86f6..013e04d72c 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -12,17 +12,15 @@ module.exports = {
 
     schema: [
       {
-        'type': 'object',
-        'properties': {
-          'allowComputed': {
-            'description':
-              'If `false`, will report computed (and thus, un-lintable) references ' +
-              'to namespace members.',
-            'type': 'boolean',
-            'default': false,
+        type: 'object',
+        properties: {
+          allowComputed: {
+            description: 'If `false`, will report computed (and thus, un-lintable) references to namespace members.',
+            type: 'boolean',
+            default: false,
           },
         },
-        'additionalProperties': false,
+        additionalProperties: false,
       },
     ],
   },
@@ -37,15 +35,12 @@ module.exports = {
     const namespaces = new Map()
 
     function makeMessage(last, namepath) {
-       return `'${last.name}' not found in` +
-              (namepath.length > 1 ? ' deeply ' : ' ') +
-              `imported namespace '${namepath.join('.')}'.`
+      return `'${last.name}' not found in ${namepath.length > 1 ? 'deeply ' : ''}imported namespace '${namepath.join('.')}'.`
     }
 
     return {
-
       // pick up all imports at body entry time, to properly respect hoisting
-      Program: function ({ body }) {
+      Program({ body }) {
         function processBodyStatement(declaration) {
           if (declaration.type !== 'ImportDeclaration') return
 
@@ -63,8 +58,10 @@ module.exports = {
             switch (specifier.type) {
               case 'ImportNamespaceSpecifier':
                 if (!imports.size) {
-                  context.report(specifier,
-                    `No exported names found in module '${declaration.source.value}'.`)
+                  context.report(
+                    specifier,
+                    `No exported names found in module '${declaration.source.value}'.`
+                  )
                 }
                 namespaces.set(specifier.local.name, imports)
                 break
@@ -72,8 +69,9 @@ module.exports = {
               case 'ImportSpecifier': {
                 const meta = imports.get(
                   // default to 'default' for default http://i.imgur.com/nj6qAWy.jpg
-                  specifier.imported ? specifier.imported.name : 'default')
-                if (!meta || !meta.namespace) break
+                  specifier.imported ? specifier.imported.name : 'default'
+                )
+                if (!meta || !meta.namespace) { break }
                 namespaces.set(specifier.local.name, meta.namespace)
                 break
               }
@@ -84,7 +82,7 @@ module.exports = {
       },
 
       // same as above, but does not add names to local map
-      ExportNamespaceSpecifier: function (namespace) {
+      ExportNamespaceSpecifier(namespace) {
         var declaration = importDeclaration(context)
 
         var imports = Exports.get(declaration.source.value, context)
@@ -96,35 +94,38 @@ module.exports = {
         }
 
         if (!imports.size) {
-          context.report(namespace,
-            `No exported names found in module '${declaration.source.value}'.`)
+          context.report(
+            namespace,
+            `No exported names found in module '${declaration.source.value}'.`
+          )
         }
       },
 
       // todo: check for possible redefinition
 
-      MemberExpression: function (dereference) {
+      MemberExpression(dereference) {
         if (dereference.object.type !== 'Identifier') return
         if (!namespaces.has(dereference.object.name)) return
 
-        if (dereference.parent.type === 'AssignmentExpression' &&
-            dereference.parent.left === dereference) {
-            context.report(dereference.parent,
-                `Assignment to member of namespace '${dereference.object.name}'.`)
+        if (dereference.parent.type === 'AssignmentExpression' && dereference.parent.left === dereference) {
+            context.report(
+              dereference.parent,
+              `Assignment to member of namespace '${dereference.object.name}'.`
+            )
         }
 
         // go deep
         var namespace = namespaces.get(dereference.object.name)
         var namepath = [dereference.object.name]
         // while property is namespace and parent is member expression, keep validating
-        while (namespace instanceof Exports &&
-               dereference.type === 'MemberExpression') {
+        while (namespace instanceof Exports && dereference.type === 'MemberExpression') {
 
           if (dereference.computed) {
             if (!allowComputed) {
-              context.report(dereference.property,
-                'Unable to validate computed reference to imported namespace \'' +
-                dereference.object.name + '\'.')
+              context.report(
+                dereference.property,
+                `Unable to validate computed reference to imported namespace '${dereference.object.name}'.`
+              )
             }
             return
           }
@@ -132,7 +133,8 @@ module.exports = {
           if (!namespace.has(dereference.property.name)) {
             context.report(
               dereference.property,
-              makeMessage(dereference.property, namepath))
+              makeMessage(dereference.property, namepath)
+            )
             break
           }
 
@@ -147,7 +149,7 @@ module.exports = {
 
       },
 
-      VariableDeclarator: function ({ id, init }) {
+      VariableDeclarator({ id, init }) {
         if (init == null) return
         if (init.type !== 'Identifier') return
         if (!namespaces.has(init.name)) return
@@ -199,7 +201,7 @@ module.exports = {
         testKey(id, namespaces.get(init.name))
       },
 
-      JSXMemberExpression: function({object, property}) {
+      JSXMemberExpression({object, property}) {
          if (!namespaces.has(object.name)) return
          var namespace = namespaces.get(object.name)
          if (!namespace.has(property.name)) {

From b944e941b51fdc24805f5816a3a5d6022961682e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 23 Jun 2020 13:22:51 -0700
Subject: [PATCH 194/767] [Fix] `namespace`: do not report on shadowed import
 names

Fixes #518.
---
 CHANGELOG.md                 | 2 ++
 src/rules/namespace.js       | 1 +
 tests/files/color.js         | 1 +
 tests/src/rules/namespace.js | 8 ++++++++
 4 files changed, 12 insertions(+)
 create mode 100644 tests/files/color.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f126e45d1e..8cca878150 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]/[`newline-after-import`]: ignore TypeScript's "export import object" ([#1830], thanks [@be5invis])
 - [`dynamic-import-chunkname`]/TypeScript: supports `@typescript-eslint/parser` ([#1833], thanks [@noelebrun])
 - [`order`]/TypeScript: ignore ordering of object imports ([#1831], thanks [@manuth])
+- [`namespace`]: do not report on shadowed import names ([#518], thanks [@ljharb])
 
 ### Changed
 - [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
@@ -887,6 +888,7 @@ for info on changes for earlier releases.
 [#555]: https://github.com/benmosher/eslint-plugin-import/pull/555
 [#538]: https://github.com/benmosher/eslint-plugin-import/pull/538
 [#527]: https://github.com/benmosher/eslint-plugin-import/pull/527
+[#518]: https://github.com/benmosher/eslint-plugin-import/pull/518
 [#509]: https://github.com/benmosher/eslint-plugin-import/pull/509
 [#508]: https://github.com/benmosher/eslint-plugin-import/pull/508
 [#503]: https://github.com/benmosher/eslint-plugin-import/pull/503
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 013e04d72c..90784c076e 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -106,6 +106,7 @@ module.exports = {
       MemberExpression(dereference) {
         if (dereference.object.type !== 'Identifier') return
         if (!namespaces.has(dereference.object.name)) return
+        if (declaredScope(context, dereference.object.name) !== 'module') return
 
         if (dereference.parent.type === 'AssignmentExpression' && dereference.parent.left === dereference) {
             context.report(
diff --git a/tests/files/color.js b/tests/files/color.js
new file mode 100644
index 0000000000..dcdbf84ac3
--- /dev/null
+++ b/tests/files/color.js
@@ -0,0 +1 @@
+export const example = 'example';
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 1f594dbbd4..93d503eb4f 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -164,6 +164,14 @@ const valid = [
   ]),
 
   ...SYNTAX_CASES,
+
+  test({
+    code: `
+    import * as color from './color';
+    export const getBackgroundFromColor = (color) => color.bg;
+    export const getExampleColor = () => color.example
+    `,
+  }),
 ]
 
 const invalid = [

From 07dc92a22319a7e24c46a64132370012779a7df3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 23 Jun 2020 14:02:47 -0700
Subject: [PATCH 195/767] [Fix] `export`: avoid warning on `export * as`
 non-conflicts

Fixes #1834.
---
 CHANGELOG.md                            |  2 ++
 src/rules/export.js                     |  9 +++++++--
 tests/files/named-export-collision/a.js |  1 +
 tests/files/named-export-collision/b.js |  1 +
 tests/src/rules/export.js               | 17 +++++++++++++++++
 5 files changed, 28 insertions(+), 2 deletions(-)
 create mode 100644 tests/files/named-export-collision/a.js
 create mode 100644 tests/files/named-export-collision/b.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8cca878150..11df4a2fb7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`dynamic-import-chunkname`]/TypeScript: supports `@typescript-eslint/parser` ([#1833], thanks [@noelebrun])
 - [`order`]/TypeScript: ignore ordering of object imports ([#1831], thanks [@manuth])
 - [`namespace`]: do not report on shadowed import names ([#518], thanks [@ljharb])
+- [`export`]: avoid warning on `export * as` non-conflicts ([#1834], thanks [@ljharb])
 
 ### Changed
 - [`no-extraneous-dependencies`]: add tests for importing types ([#1824], thanks [@taye])
@@ -721,6 +722,7 @@ for info on changes for earlier releases.
 
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
 [#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
+[#1834]: https://github.com/benmosher/eslint-plugin-import/issues/1834
 [#1833]: https://github.com/benmosher/eslint-plugin-import/pull/1833
 [#1831]: https://github.com/benmosher/eslint-plugin-import/pull/1831
 [#1830]: https://github.com/benmosher/eslint-plugin-import/pull/1830
diff --git a/src/rules/export.js b/src/rules/export.js
index f131374df3..340972eda0 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -118,6 +118,9 @@ module.exports = {
       'ExportAllDeclaration': function (node) {
         if (node.source == null) return // not sure if this is ever true
 
+        // `export * as X from 'path'` does not conflict
+        if (node.exported && node.exported.name) return
+
         const remoteExports = ExportMap.get(node.source.value, context)
         if (remoteExports == null) return
 
@@ -135,8 +138,10 @@ module.exports = {
           addNamed(name, node, parent))
 
         if (!any) {
-          context.report(node.source,
-            `No named exports found in module '${node.source.value}'.`)
+          context.report(
+            node.source,
+            `No named exports found in module '${node.source.value}'.`
+          )
         }
       },
 
diff --git a/tests/files/named-export-collision/a.js b/tests/files/named-export-collision/a.js
new file mode 100644
index 0000000000..cb04b2cb26
--- /dev/null
+++ b/tests/files/named-export-collision/a.js
@@ -0,0 +1 @@
+export const FOO = 'a-foobar';
diff --git a/tests/files/named-export-collision/b.js b/tests/files/named-export-collision/b.js
new file mode 100644
index 0000000000..ebf954ee0c
--- /dev/null
+++ b/tests/files/named-export-collision/b.js
@@ -0,0 +1 @@
+export const FOO = 'b-foobar';
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index fb301495e7..b31ab82dc2 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -24,6 +24,15 @@ ruleTester.run('export', rule, {
     test({ code: 'export default foo; export * from "./bar"' }),
 
     ...SYNTAX_CASES,
+
+    test({
+      code: `
+        import * as A from './named-export-collision/a';
+        import * as B from './named-export-collision/b';
+
+        export { A, B };
+      `,
+    }),
   ],
 
   invalid: [
@@ -191,6 +200,14 @@ context('TypeScript', function () {
           code: 'export * from "./file1.ts"',
           filename: testFilePath('typescript-d-ts/file-2.ts'),
         }, parserConfig)),
+
+        test({
+          code: `
+            export * as A from './named-export-collision/a';
+            export * as B from './named-export-collision/b';
+          `,
+          parser: parser,
+        }),
       ],
       invalid: [
         // type/value name clash

From 7ceae48d31240be627f6ee89b28e4c2ba698bb9e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 23 Jun 2020 14:44:18 -0700
Subject: [PATCH 196/767] [Tests] `export`: skip `export * as` tests in eslint
 < 6

---
 tests/src/rules/export.js | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index b31ab82dc2..43711ffae6 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -1,6 +1,8 @@
 import { test, testFilePath, SYNTAX_CASES, getTSParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
+import eslintPkg from 'eslint/package.json'
+import semver from 'semver'
 
 var ruleTester = new RuleTester()
   , rule = require('rules/export')
@@ -201,13 +203,15 @@ context('TypeScript', function () {
           filename: testFilePath('typescript-d-ts/file-2.ts'),
         }, parserConfig)),
 
-        test({
-          code: `
-            export * as A from './named-export-collision/a';
-            export * as B from './named-export-collision/b';
-          `,
-          parser: parser,
-        }),
+        ...(semver.satisfies(eslintPkg.version, '< 6' ? [] : [
+          test({
+            code: `
+              export * as A from './named-export-collision/a';
+              export * as B from './named-export-collision/b';
+            `,
+            parser: parser,
+          }),
+        ])),
       ],
       invalid: [
         // type/value name clash

From 36a535b6a6628545ef76eb46fcf2cf515a65e7b9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 23 Jun 2020 14:44:18 -0700
Subject: [PATCH 197/767] fixup: [Tests] `export`: skip `export * as` tests in
 eslint < 6

---
 tests/src/rules/export.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 43711ffae6..f21da9b708 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -203,7 +203,7 @@ context('TypeScript', function () {
           filename: testFilePath('typescript-d-ts/file-2.ts'),
         }, parserConfig)),
 
-        ...(semver.satisfies(eslintPkg.version, '< 6' ? [] : [
+        ...(semver.satisfies(eslintPkg.version, '< 6') ? [] : [
           test({
             code: `
               export * as A from './named-export-collision/a';
@@ -211,7 +211,7 @@ context('TypeScript', function () {
             `,
             parser: parser,
           }),
-        ])),
+        ]),
       ],
       invalid: [
         // type/value name clash

From 878ce6efd055cb13c0cdd15123ae2734a5832ace Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 26 Jun 2020 22:44:00 -0700
Subject: [PATCH 198/767] Bump to v2.22.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 11df4a2fb7..c0aaae190d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
 ## [Unreleased]
+
+## [2.22.0] - 2020-06-26
 ### Added
 - [`no-unused-modules`]: consider exported TypeScript interfaces, types and enums ([#1819], thanks [@nicolashenry])
 - [`no-cycle`]: allow `maxDepth` option to be `"∞"` (thanks [@ljharb])
@@ -1022,7 +1024,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.2...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.0...HEAD
+[2.22.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.22.0
 [2.21.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.21.2
 [2.21.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.0...v2.21.1
 [2.21.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.2...v2.21.0
diff --git a/package.json b/package.json
index 4bc07ee707..8356d2443e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.21.2",
+  "version": "2.22.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From a5a277ff3463cd7666b2ca119bd3575d5bff1ab9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 3 Jul 2020 14:49:09 -0700
Subject: [PATCH 199/767] [Fix] `default`/TypeScript: avoid crash on `export =`
 with a MemberExpression

Fixes #1841
---
 CHANGELOG.md               | 4 ++++
 src/ExportMap.js           | 2 +-
 tests/src/rules/default.js | 8 ++++++++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0aaae190d..4f3d1b0d2e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
+
 ## [2.22.0] - 2020-06-26
 ### Added
 - [`no-unused-modules`]: consider exported TypeScript interfaces, types and enums ([#1819], thanks [@nicolashenry])
@@ -722,6 +725,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1841]: https://github.com/benmosher/eslint-plugin-import/issues/1841
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
 [#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
 [#1834]: https://github.com/benmosher/eslint-plugin-import/issues/1834
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 6978b844cb..eb6ad58fcc 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -564,7 +564,7 @@ ExportMap.parse = function (path, content, context) {
     if (includes(exports, n.type)) {
       const exportedName = n.type === 'TSNamespaceExportDeclaration'
         ? n.id.name
-        : n.expression && n.expression.name || n.expression.id.name
+        : (n.expression && n.expression.name || (n.expression.id && n.expression.id.name) || null)
       const declTypes = [
         'VariableDeclaration',
         'ClassDeclaration',
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index c040a478d5..3f2c8dac1f 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -220,6 +220,14 @@ context('TypeScript', function () {
               tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-as-default-namespace/'),
             },
           }),
+          test({
+            code: `import foobar from "./typescript-export-assign-property"`,
+            parser: parser,
+            settings: {
+              'import/parsers': { [parser]: ['.ts'] },
+              'import/resolver': { 'eslint-import-resolver-typescript': true },
+            },
+          }),
         ],
 
         invalid: [

From 843055c80cc5df78f9720a0be3a78f69567eb11a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 3 Jul 2020 15:00:35 -0700
Subject: [PATCH 200/767] [Tests] `no-unused-modules`: fix formatting; add test
 case from #1844

---
 tests/src/rules/no-unused-modules.js | 66 ++++++++++++++++++++--------
 1 file changed, 47 insertions(+), 19 deletions(-)

diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 74200fb0d9..b6554d129a 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -37,25 +37,53 @@ const unusedExportsJsxOptions = [{
 // tests for missing exports
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ code: 'export default function noOptions() {}' }),
-    test({ options: missingExportsOptions,
-           code: 'export default () => 1'}),
-    test({ options: missingExportsOptions,
-           code: 'export const a = 1'}),
-    test({ options: missingExportsOptions,
-           code: 'const a = 1; export { a }'}),
-    test({ options: missingExportsOptions,
-           code: 'function a() { return true }; export { a }'}),
-    test({ options: missingExportsOptions,
-           code: 'const a = 1; const b = 2; export { a, b }'}),
-    test({ options: missingExportsOptions,
-           code: 'const a = 1; export default a'}),
-    test({ options: missingExportsOptions,
-           code: 'export class Foo {}'}),
-    test({ options: missingExportsOptions,
-           code: 'export const [foobar] = [];'}),
-    test({ options: missingExportsOptions,
-           code: 'export const [foobar] = foobarFactory();'}),
+    test({
+      code: 'export default function noOptions() {}',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'export default () => 1',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'export const a = 1',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'const a = 1; export { a }',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'function a() { return true }; export { a }',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'const a = 1; const b = 2; export { a, b }',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'const a = 1; export default a',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'export class Foo {}',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'export const [foobar] = [];',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: 'export const [foobar] = foobarFactory();',
+    }),
+    test({
+      options: missingExportsOptions,
+      code: `
+        export default function NewComponent () {
+          return 'I am new component'
+        }
+      `,
+    }),
   ],
   invalid: [
     test({

From 3e65a70bc73e404ace72ee858889e39732284d12 Mon Sep 17 00:00:00 2001
From: Artur Tagisow <atagisow@protonmail.com>
Date: Sun, 12 Jul 2020 18:46:12 +0200
Subject: [PATCH 201/767] [Fix] `extensions`/importType: Fix @/abc being
 treated as scoped module

Fixes #1851

Before this commit, @/abc was being wrongly detected as a scoped module.
This was a problem when somebody had a webpack alias `@`. (eg. @ -> ./src)

In general, scoped modules can't start with @/, I think they have to be like @/abcd.
---
 CHANGELOG.md                  |  3 +++
 src/core/importType.js        |  2 +-
 tests/src/core/importType.js  |  7 ++++++-
 tests/src/rules/extensions.js | 10 ++++++++++
 4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4f3d1b0d2e..e9e04d630b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
+- [`extensions`]/importType: Fix @/abc being treated as scoped module ([#1854], thanks [@3nuc])
 
 ## [2.22.0] - 2020-06-26
 ### Added
@@ -725,6 +726,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
 [#1841]: https://github.com/benmosher/eslint-plugin-import/issues/1841
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
 [#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
@@ -1260,3 +1262,4 @@ for info on changes for earlier releases.
 [@be5invis]: https://github.com/be5invis
 [@noelebrun]: https://github.com/noelebrun
 [@beatrizrezener]: https://github.com/beatrizrezener
+[@3nuc]: https://github.com/3nuc
diff --git a/src/core/importType.js b/src/core/importType.js
index ff2d10b60f..25ab2bdced 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -93,7 +93,7 @@ function typeTest(name, settings, path) {
 }
 
 export function isScopedModule(name) {
-  return name.indexOf('@') === 0
+  return name.indexOf('@') === 0 && !name.startsWith('@/')
 }
 
 export default function resolveImportType(name, context) {
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index b3bfb6bb62..f6db95158c 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -1,7 +1,7 @@
 import { expect } from 'chai'
 import * as path from 'path'
 
-import importType, {isExternalModule} from 'core/importType'
+import importType, {isExternalModule, isScopedModule} from 'core/importType'
 
 import { testContext, testFilePath } from '../utils'
 
@@ -237,4 +237,9 @@ describe('importType(name)', function () {
       'import/external-module-folders': ['E:\\path\\to\\node_modules'],
     }, 'E:\\path\\to\\node_modules\\foo')).to.equal(true)
   })
+
+  it('correctly identifies scoped modules with `isScopedModule`', () => {
+    expect(isScopedModule('@/abc')).to.equal(false)
+    expect(isScopedModule('@a/abc')).to.equal(true)
+  })
 })
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 8cdb3399d8..93860c16ab 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -444,5 +444,15 @@ ruleTester.run('extensions', rule, {
         },
       ],
     }),
+    test({
+      code: 'import foo from "@/ImNotAScopedModule"',
+      options: ['always'],
+      errors: [
+        {
+          message: 'Missing file extension for "@/ImNotAScopedModule"',
+          line: 1,
+        },
+      ],
+    }),
   ],
 })

From 5fe14e391f8c74c23f1d78fd547791f79ad30146 Mon Sep 17 00:00:00 2001
From: Alex Young <foray1010@users.noreply.github.com>
Date: Fri, 14 Aug 2020 09:22:49 +0800
Subject: [PATCH 202/767] [Fix] allow using rest operator in named export

---
 CHANGELOG.md                 | 3 +++
 src/ExportMap.js             | 8 ++++++++
 tests/files/named-exports.js | 4 ++--
 tests/src/core/getExports.js | 2 +-
 tests/src/utils.js           | 2 +-
 5 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9e04d630b..56c6fb4c4f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
 - [`extensions`]/importType: Fix @/abc being treated as scoped module ([#1854], thanks [@3nuc])
+- allow using rest operator in named export ([#1878], thanks [@foray1010])
 
 ## [2.22.0] - 2020-06-26
 ### Added
@@ -726,6 +727,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
 [#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
 [#1841]: https://github.com/benmosher/eslint-plugin-import/issues/1841
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
@@ -1263,3 +1265,4 @@ for info on changes for earlier releases.
 [@noelebrun]: https://github.com/noelebrun
 [@beatrizrezener]: https://github.com/beatrizrezener
 [@3nuc]: https://github.com/3nuc
+[@foray1010]: https://github.com/foray1010
diff --git a/src/ExportMap.js b/src/ExportMap.js
index eb6ad58fcc..837546aeb4 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -650,6 +650,10 @@ export function recursivePatternCapture(pattern, callback) {
 
     case 'ObjectPattern':
       pattern.properties.forEach(p => {
+        if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
+          callback(p.argument)
+          return
+        }
         recursivePatternCapture(p.value, callback)
       })
       break
@@ -657,6 +661,10 @@ export function recursivePatternCapture(pattern, callback) {
     case 'ArrayPattern':
       pattern.elements.forEach((element) => {
         if (element == null) return
+        if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
+          callback(element.argument)
+          return
+        }
         recursivePatternCapture(element, callback)
       })
       break
diff --git a/tests/files/named-exports.js b/tests/files/named-exports.js
index f2881c10c5..d8b17bb908 100644
--- a/tests/files/named-exports.js
+++ b/tests/files/named-exports.js
@@ -13,9 +13,9 @@ export class ExportedClass {
 
 // destructuring exports
 
-export var { destructuredProp } = {}
+export var { destructuredProp, ...restProps } = {}
          , { destructingAssign = null } = {}
          , { destructingAssign: destructingRenamedAssign = null } = {}
-         , [ arrayKeyProp ] = []
+         , [ arrayKeyProp, ...arrayRestKeyProps ] = []
          , [ { deepProp } ] = []
          , { arr: [ ,, deepSparseElement ] } = {}
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index d61544e7a9..145f236f10 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -295,7 +295,7 @@ describe('ExportMap', function () {
     context('#size', function () {
 
       it('counts the names', () => expect(ExportMap.get('./named-exports', fakeContext))
-        .to.have.property('size', 10))
+        .to.have.property('size', 12))
 
       it('includes exported namespace size', () => expect(ExportMap.get('./export-all', fakeContext))
         .to.have.property('size', 1))
diff --git a/tests/src/utils.js b/tests/src/utils.js
index 4bc8f0119a..0f45e7bf28 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -37,7 +37,7 @@ export function test(t) {
   }, t, {
     parserOptions: Object.assign({
       sourceType: 'module',
-      ecmaVersion: 6,
+      ecmaVersion: 9,
     }, t.parserOptions),
   })
 }

From 1a67453752af2a596ecf2590b6efe4c4512935fc Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 21 Aug 2020 14:13:06 -0700
Subject: [PATCH 203/767] [Tests] `export`: add tests for a name collision with
 `export * from`

Closes #1704.

Co-authored-by: Tom Prats <tom@tomify.me>
---
 CHANGELOG.md              | 5 +++++
 tests/src/rules/export.js | 9 +++++++++
 2 files changed, 14 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 56c6fb4c4f..bca4603c38 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extensions`]/importType: Fix @/abc being treated as scoped module ([#1854], thanks [@3nuc])
 - allow using rest operator in named export ([#1878], thanks [@foray1010])
 
+### Changed
+- [`export`]: add tests for a name collision with `export * from` ([#1704], thanks @tomprats)
+
 ## [2.22.0] - 2020-06-26
 ### Added
 - [`no-unused-modules`]: consider exported TypeScript interfaces, types and enums ([#1819], thanks [@nicolashenry])
@@ -758,6 +761,7 @@ for info on changes for earlier releases.
 [#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
 [#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
 [#1719]: https://github.com/benmosher/eslint-plugin-import/pull/1719
+[#1704]: https://github.com/benmosher/eslint-plugin-import/issues/1704
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
 [#1691]: https://github.com/benmosher/eslint-plugin-import/pull/1691
 [#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
@@ -1266,3 +1270,4 @@ for info on changes for earlier releases.
 [@beatrizrezener]: https://github.com/beatrizrezener
 [@3nuc]: https://github.com/3nuc
 [@foray1010]: https://github.com/foray1010
+[@tomprats]: https://github.com/tomprats
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index f21da9b708..ec0cf5c083 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -35,6 +35,15 @@ ruleTester.run('export', rule, {
         export { A, B };
       `,
     }),
+    test({
+      code: `
+        export * as A from './named-export-collision/a';
+        export * as B from './named-export-collision/b';
+      `,
+      parserOptions: {
+        ecmaVersion: 2020,
+      },
+    }),
   ],
 
   invalid: [

From b2d3707fdfb512b2c2c69ee27617eef0fa48db17 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 21 Aug 2020 14:52:25 -0700
Subject: [PATCH 204/767] fixup! [Tests] `export`: add tests for a name
 collision with `export * from`

---
 tests/src/rules/export.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index ec0cf5c083..91ff9e304f 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -1,4 +1,4 @@
-import { test, testFilePath, SYNTAX_CASES, getTSParsers } from '../utils'
+import { test, testFilePath, SYNTAX_CASES, getTSParsers, testVersion } from '../utils'
 
 import { RuleTester } from 'eslint'
 import eslintPkg from 'eslint/package.json'
@@ -35,7 +35,7 @@ ruleTester.run('export', rule, {
         export { A, B };
       `,
     }),
-    test({
+    testVersion('>= 6', () => ({
       code: `
         export * as A from './named-export-collision/a';
         export * as B from './named-export-collision/b';
@@ -43,7 +43,7 @@ ruleTester.run('export', rule, {
       parserOptions: {
         ecmaVersion: 2020,
       },
-    }),
+    })),
   ],
 
   invalid: [

From 569d72688fa6ae5c038c51eafa4f6016fc1ee802 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 21 Aug 2020 14:52:25 -0700
Subject: [PATCH 205/767] fixup! [Tests] `export`: add tests for a name
 collision with `export * from`

---
 tests/src/rules/export.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 91ff9e304f..5ecfcae20e 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -8,7 +8,7 @@ var ruleTester = new RuleTester()
   , rule = require('rules/export')
 
 ruleTester.run('export', rule, {
-  valid: [
+  valid: [].concat(
     test({ code: 'import "./malformed.js"' }),
 
     // default
@@ -43,8 +43,8 @@ ruleTester.run('export', rule, {
       parserOptions: {
         ecmaVersion: 2020,
       },
-    })),
-  ],
+    })) || [],
+  ),
 
   invalid: [
     // multiple defaults

From 227d9a25098b359c11cce3c95d6168acdb87eb99 Mon Sep 17 00:00:00 2001
From: David Straub <Scinvention@gmail.com>
Date: Tue, 7 Jul 2020 18:00:09 -0400
Subject: [PATCH 206/767] [Fix] `dynamic-import-chunkname`: allow single quotes
 to match Webpack support

Fixes #1130.
---
 CHANGELOG.md                                |  3 +
 docs/rules/dynamic-import-chunkname.md      | 12 ++--
 src/rules/dynamic-import-chunkname.js       |  4 +-
 tests/src/rules/dynamic-import-chunkname.js | 79 +++++++++++++++------
 4 files changed, 67 insertions(+), 31 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bca4603c38..eb1666b499 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
 - [`extensions`]/importType: Fix @/abc being treated as scoped module ([#1854], thanks [@3nuc])
 - allow using rest operator in named export ([#1878], thanks [@foray1010])
+- [`dynamic-import-chunkname`]: allow single quotes to match Webpack support ([#1848], thanks [@straub])
 
 ### Changed
 - [`export`]: add tests for a name collision with `export * from` ([#1704], thanks @tomprats)
@@ -732,6 +733,7 @@ for info on changes for earlier releases.
 
 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
 [#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
+[#1848]: https://github.com/benmosher/eslint-plugin-import/pull/1848
 [#1841]: https://github.com/benmosher/eslint-plugin-import/issues/1841
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
 [#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
@@ -1271,3 +1273,4 @@ for info on changes for earlier releases.
 [@3nuc]: https://github.com/3nuc
 [@foray1010]: https://github.com/foray1010
 [@tomprats]: https://github.com/tomprats
+[@straub]: https://github.com/straub
diff --git a/docs/rules/dynamic-import-chunkname.md b/docs/rules/dynamic-import-chunkname.md
index 4bcc5a98b1..d29c06bbaa 100644
--- a/docs/rules/dynamic-import-chunkname.md
+++ b/docs/rules/dynamic-import-chunkname.md
@@ -39,12 +39,6 @@ import(
   'someModule',
 );
 
-// using single quotes instead of double quotes
-import(
-  /* webpackChunkName: 'someModule' */
-  'someModule',
-);
-
 // invalid syntax for webpack comment
 import(
   /* totally not webpackChunkName: "someModule" */
@@ -78,6 +72,12 @@ The following patterns are valid:
     /* webpackChunkName: "someModule", webpackPrefetch: true */
     'someModule',
   );
+
+  // using single quotes instead of double quotes
+  import(
+    /* webpackChunkName: 'someModule' */
+    'someModule',
+  );
 ```
 
 ## When Not To Use It
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index cff4b1c2a1..5ac89e1e64 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -30,8 +30,8 @@ module.exports = {
     const { webpackChunknameFormat = '[0-9a-zA-Z-_/.]+' } = config || {}
 
     const paddedCommentRegex = /^ (\S[\s\S]+\S) $/
-    const commentStyleRegex = /^( \w+: ("[^"]*"|\d+|false|true),?)+ $/
-    const chunkSubstrFormat = ` webpackChunkName: "${webpackChunknameFormat}",? `
+    const commentStyleRegex = /^( \w+: (["'][^"']*["']|\d+|false|true),?)+ $/
+    const chunkSubstrFormat = ` webpackChunkName: ["']${webpackChunknameFormat}["'],? `
     const chunkSubstrRegex = new RegExp(chunkSubstrFormat)
 
     function run(node, arg) {
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index 938f542e91..cd321019d2 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -21,8 +21,8 @@ const noLeadingCommentError = 'dynamic imports require a leading comment with th
 const nonBlockCommentError = 'dynamic imports require a /* foo */ style comment, not a // foo comment'
 const noPaddingCommentError = 'dynamic imports require a block comment padded with spaces - /* foo */'
 const invalidSyntaxCommentError = 'dynamic imports require a "webpack" comment with valid syntax'
-const commentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: "${commentFormat}",? */`
-const pickyCommentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: "${pickyCommentFormat}",? */`
+const commentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${commentFormat}["'],? */`
+const pickyCommentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${pickyCommentFormat}["'],? */`
 
 ruleTester.run('dynamic-import-chunkname', rule, {
   valid: [
@@ -132,6 +132,14 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       options,
       parser,
     },
+    {
+      code: `import(
+        /* webpackChunkName: 'someModule' */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
     {
       code: `import(
         /* webpackChunkName: "someModule" */
@@ -192,17 +200,33 @@ ruleTester.run('dynamic-import-chunkname', rule, {
     },
     {
       code: `import(
-        /* webpackChunkName: 'someModule' */
+        /* webpackChunkName: "someModule' */
         'someModule'
       )`,
       options,
       parser,
       output: `import(
-        /* webpackChunkName: 'someModule' */
+        /* webpackChunkName: "someModule' */
         'someModule'
       )`,
       errors: [{
-        message: commentFormatError,
+        message: invalidSyntaxCommentError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackChunkName: 'someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackChunkName: 'someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
     },
@@ -421,21 +445,6 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         type: 'CallExpression',
       }],
     },
-    {
-      code: `dynamicImport(
-        /* webpackChunkName: 'someModule' */
-        'someModule'
-      )`,
-      options,
-      output: `dynamicImport(
-        /* webpackChunkName: 'someModule' */
-        'someModule'
-      )`,
-      errors: [{
-        message: commentFormatError,
-        type: 'CallExpression',
-      }],
-    },
     {
       code: `dynamicImport(
         /* webpackChunkName "someModule" */
@@ -578,6 +587,14 @@ context('TypeScript', () => {
             type: nodeType,
           }],
         },
+        {
+          code: `import(
+            /* webpackChunkName: 'someModule' */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
       ],
       invalid: [
         {
@@ -624,17 +641,33 @@ context('TypeScript', () => {
         },
         {
           code: `import(
-            /* webpackChunkName: 'someModule' */
+            /* webpackChunkName "someModule' */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
           output: `import(
-            /* webpackChunkName: 'someModule' */
+            /* webpackChunkName "someModule' */
             'someModule'
           )`,
           errors: [{
-            message: commentFormatError,
+            message: invalidSyntaxCommentError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName 'someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName 'someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: invalidSyntaxCommentError,
             type: nodeType,
           }],
         },

From f40c8aef2af736867ce9399326b3ae6faba06d94 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 5 Sep 2020 09:43:45 -0700
Subject: [PATCH 207/767] [meta] convert eslint config to json

---
 .eslintrc     | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++
 .eslintrc.yml | 48 ------------------------------------------
 2 files changed, 58 insertions(+), 48 deletions(-)
 create mode 100644 .eslintrc
 delete mode 100644 .eslintrc.yml

diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000000..2d69852e7c
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,58 @@
+{
+    "root": true,
+    "plugins": [
+        "eslint-plugin",
+        "import",
+    ],
+    "extends": [
+        "eslint:recommended",
+        "plugin:eslint-plugin/recommended",
+        "plugin:import/recommended",
+    ],
+    "env": {
+        "node": true,
+        "es6": true,
+    },
+    "parserOptions": {
+        "sourceType": "module",
+        "ecmaVersion": 6,
+    },
+    "rules": {
+        "max-len": [1, 99, 2],
+        "semi": [2, "never"],
+        "curly": [2, "multi-line"],
+        "comma-dangle": [2, "always-multiline"],
+        "eol-last": [2, "always"],
+        "eqeqeq": [2, "allow-null"],
+        "no-shadow": 1,
+        "quotes": [2, "single", {
+            "allowTemplateLiterals": true,
+            "avoidEscape": true,
+        }],
+        "eslint-plugin/consistent-output": [
+            "error",
+            "always",
+        ],
+        "eslint-plugin/meta-property-ordering": "error",
+        "eslint-plugin/no-deprecated-context-methods": "error",
+        "eslint-plugin/no-deprecated-report-api": "off",
+        "eslint-plugin/prefer-replace-text": "error",
+        "eslint-plugin/report-message-format": "error",
+        "eslint-plugin/require-meta-schema": "error",
+        "eslint-plugin/require-meta-type": "error",
+
+        // dog fooding
+        "import/no-extraneous-dependencies": "error",
+        "import/unambiguous": "off",
+    },
+
+    "settings": {
+        "import/resolver": {
+            "node": {
+                "paths": [
+                    "src",
+                ],
+            },
+        },
+    },
+}
diff --git a/.eslintrc.yml b/.eslintrc.yml
deleted file mode 100644
index 4f8ccaac37..0000000000
--- a/.eslintrc.yml
+++ /dev/null
@@ -1,48 +0,0 @@
----
-plugins:
-  - eslint-plugin
-  - import
-extends:
-  - eslint:recommended
-  - plugin:eslint-plugin/recommended
-  - plugin:import/recommended
-
-env:
-  node: true
-  es6: true
-
-parserOptions:
-  sourceType: module
-  ecmaVersion: 6
-
-rules:
-  max-len: [1, 99, 2]
-  semi: [2, "never"]
-  curly: [2, "multi-line"]
-  comma-dangle: [2, always-multiline]
-  eol-last: [2, "always"]
-  eqeqeq: [2, "allow-null"]
-  no-shadow: 1
-  quotes:
-    - 2
-    - single
-    - allowTemplateLiterals: true
-      avoidEscape: true
-
-  eslint-plugin/consistent-output: ["error", "always"]
-  eslint-plugin/meta-property-ordering: "error"
-  eslint-plugin/no-deprecated-context-methods: "error"
-  eslint-plugin/no-deprecated-report-api: "off"
-  eslint-plugin/prefer-replace-text: "error"
-  eslint-plugin/report-message-format: "error"
-  eslint-plugin/require-meta-schema: "error"
-  eslint-plugin/require-meta-type: "error"
-
-  # dog fooding
-  import/no-extraneous-dependencies: "error"
-  import/unambiguous: "off"
-
-settings:
-  import/resolver:
-    node:
-      paths: [ src ]

From bbe529a4ffe7ddb76a1620e55c90be884400456f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 5 Sep 2020 09:46:14 -0700
Subject: [PATCH 208/767] =?UTF-8?q?[eslint]=20don=E2=80=99t=20warn=20about?=
 =?UTF-8?q?=20console=20logs=20in=20scripts?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .eslintrc | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/.eslintrc b/.eslintrc
index 2d69852e7c..d02c02a69d 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -55,4 +55,13 @@
             },
         },
     },
+
+    "overrides": [
+        {
+            "files": "scripts/**",
+            "rules": {
+                "no-console": "off",
+            },
+        },
+    ],
 }

From fef718cb134016855afe61682e32c63ba3ed9281 Mon Sep 17 00:00:00 2001
From: Cyril Auburtin <cyril.auburtin@gmail.com>
Date: Tue, 29 Jan 2019 18:07:48 +0100
Subject: [PATCH 209/767] [resolvers/webpack] [Breaking] Allow to resolve
 config path relative to working directory

Co-Authored-By: caub <cyril.auburtin@gmail.com>
---
 resolvers/webpack/README.md      | 12 +++++++++++-
 resolvers/webpack/index.js       |  6 +++++-
 resolvers/webpack/test/config.js |  8 ++++++++
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/resolvers/webpack/README.md b/resolvers/webpack/README.md
index 4fc3b0ffff..9646dc24e4 100644
--- a/resolvers/webpack/README.md
+++ b/resolvers/webpack/README.md
@@ -42,7 +42,7 @@ settings:
       config: 'webpack.dev.config.js'
 ```
 
-or with explicit config file name:
+or with explicit config file index:
 
 ```yaml
 ---
@@ -53,6 +53,16 @@ settings:
       config-index: 1   # take the config at index 1
 ```
 
+or with explicit config file path relative to your projects's working directory:
+
+```yaml
+---
+settings:
+  import/resolver:
+    webpack:
+      config: './configs/webpack.dev.config.js'
+```
+
 or with explicit config object:
 
 ```yaml
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 20c594847b..677d7584cf 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -48,7 +48,7 @@ exports.resolve = function (source, file, settings) {
 
   var webpackConfig
 
-  var configPath = get(settings, 'config')
+  var _configPath = get(settings, 'config')
     /**
      * Attempt to set the current working directory.
      * If none is passed, default to the `cwd` where the config is located.
@@ -59,6 +59,10 @@ exports.resolve = function (source, file, settings) {
     , argv = get(settings, 'argv', {})
     , packageDir
 
+  var configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
+    ? path.resolve(_configPath)
+    : _configPath
+
   log('Config path from settings:', configPath)
 
   // see if we've got a config path, a config object, an array of config objects or a config function
diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index ff0c0bd669..add282b672 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -72,6 +72,14 @@ describe("config", function () {
         .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'))
   })
 
+  it("finds config object when config uses a path relative to working dir", function () {
+    var settings = {
+      config: './test/files/some/absolute.path.webpack.config.js',
+    }
+    expect(resolve('foo', file, settings)).to.have.property('path')
+        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'))
+  })
+
   it("finds the first config with a resolve section when config is an array of config objects", function () {
     var settings = {
       config: require(path.join(__dirname, './files/webpack.config.multiple.js')),

From b366e50be8c0738b6ac27ccde7b689785a5a3309 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 27 Sep 2020 13:53:04 -0700
Subject: [PATCH 210/767] [Deps] update `eslint-import-resolver-node`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 8356d2443e..028b5ed0a3 100644
--- a/package.json
+++ b/package.json
@@ -102,7 +102,7 @@
     "contains-path": "^0.1.0",
     "debug": "^2.6.9",
     "doctrine": "1.5.0",
-    "eslint-import-resolver-node": "^0.3.3",
+    "eslint-import-resolver-node": "^0.3.4",
     "eslint-module-utils": "^2.6.0",
     "has": "^1.0.3",
     "minimatch": "^3.0.4",

From aa427595698ec1ad7ab9b347c122eac33de8a136 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 27 Sep 2020 13:58:32 -0700
Subject: [PATCH 211/767] [Dev Deps] update `coveralls`,
 `eslint-import-resolver-typescript`, `eslint-plugin-eslint-plugin`,
 `eslint-plugin-json`

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 028b5ed0a3..2183414ba7 100644
--- a/package.json
+++ b/package.json
@@ -67,17 +67,17 @@
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
     "chai": "^4.2.0",
-    "coveralls": "^3.0.6",
+    "coveralls": "^3.1.0",
     "cross-env": "^4.0.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0",
     "eslint-import-resolver-node": "file:./resolvers/node",
-    "eslint-import-resolver-typescript": "^1.0.2",
+    "eslint-import-resolver-typescript": "^1.1.1",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
     "eslint-import-test-order-redirect": "file:./tests/files/order-redirect",
     "eslint-module-utils": "file:./utils",
-    "eslint-plugin-eslint-plugin": "^2.2.1",
+    "eslint-plugin-eslint-plugin": "^2.3.0",
     "eslint-plugin-import": "2.x",
-    "eslint-plugin-json": "^2.1.1",
+    "eslint-plugin-json": "^2.1.2",
     "fs-copy-file-sync": "^1.1.1",
     "glob": "^7.1.6",
     "in-publish": "^2.0.1",

From bdda0691cf703f13f6472b6e824d5168343dd52e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 27 Sep 2020 13:59:45 -0700
Subject: [PATCH 212/767] Bump to v2.22.1

---
 CHANGELOG.md | 4 +++-
 package.json | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb1666b499..5ba0cb63a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.22.1] - 2020-09-27
 ### Fixed
 - [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
 - [`extensions`]/importType: Fix @/abc being treated as scoped module ([#1854], thanks [@3nuc])
@@ -1038,7 +1039,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.0...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.1...HEAD
+[2.22.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.0...v2.22.1
 [2.22.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.22.0
 [2.21.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.21.2
 [2.21.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.0...v2.21.1
diff --git a/package.json b/package.json
index 2183414ba7..18fd70af20 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.22.0",
+  "version": "2.22.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From c51b6a97de1e0edad77a247d5da4c36db7c8d039 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 27 Sep 2020 16:05:34 -0700
Subject: [PATCH 213/767] [resolvers/webpack] v0.13.0

---
 resolvers/webpack/CHANGELOG.md | 5 +++++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 5b31c350ac..df66f8bbb6 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## 0.13.0 - 2020-09-27
+
+### Breaking
+- [Breaking] Allow to resolve config path relative to working directory (#1276)
+
 ## 0.12.2 - 2020-06-16
 
 ### Fixed
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 7de2690b2d..ee13908bbc 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.12.2",
+  "version": "0.13.0",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 5ade15602cc5532d282f3eaead5d21407e455c47 Mon Sep 17 00:00:00 2001
From: e020873 <nicolas.henry-partner@arcelormittal.com>
Date: Mon, 21 Sep 2020 12:45:41 +0000
Subject: [PATCH 214/767] [Fix] `no-unused-modules`: ignore flow type imports

Fixes #1564.
---
 src/rules/no-unused-modules.js                |   4 -
 tests/files/no-unused-modules/flow/flow-0.js  |   1 +
 tests/files/no-unused-modules/flow/flow-1.js  |   3 +
 tests/files/no-unused-modules/flow/flow-2.js  |   3 +
 tests/files/no-unused-modules/flow/flow-3.js  |   1 +
 tests/files/no-unused-modules/flow/flow-4.js  |   3 +
 .../typescript/file-ts-a-import-type.ts       |   9 +
 .../no-unused-modules/typescript/file-ts-a.ts |   6 +-
 .../typescript/file-ts-b-unused.ts            |   1 +
 .../typescript/file-ts-b-used-as-type.ts      |   1 +
 .../typescript/file-ts-c-unused.ts            |   1 +
 .../typescript/file-ts-c-used-as-type.ts      |   1 +
 .../typescript/file-ts-d-unused.ts            |   1 +
 .../typescript/file-ts-d-used-as-type.ts      |   1 +
 .../typescript/file-ts-e-unused.ts            |   1 +
 .../typescript/file-ts-e-used-as-type.ts      |   1 +
 tests/src/rules/no-unused-modules.js          | 173 +++++++++++++-----
 17 files changed, 157 insertions(+), 54 deletions(-)
 create mode 100644 tests/files/no-unused-modules/flow/flow-0.js
 create mode 100644 tests/files/no-unused-modules/flow/flow-1.js
 create mode 100644 tests/files/no-unused-modules/flow/flow-2.js
 create mode 100644 tests/files/no-unused-modules/flow/flow-3.js
 create mode 100644 tests/files/no-unused-modules/flow/flow-4.js
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-a-import-type.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-b-unused.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-b-used-as-type.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-c-unused.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-c-used-as-type.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-d-unused.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-d-used-as-type.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-e-unused.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-e-used-as-type.ts

diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index d277ca9aed..9f38ac8e1c 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -63,8 +63,6 @@ const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier'
 const VARIABLE_DECLARATION = 'VariableDeclaration'
 const FUNCTION_DECLARATION = 'FunctionDeclaration'
 const CLASS_DECLARATION = 'ClassDeclaration'
-const INTERFACE_DECLARATION = 'InterfaceDeclaration'
-const TYPE_ALIAS = 'TypeAlias'
 const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration'
 const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration'
 const TS_ENUM_DECLARATION = 'TSEnumDeclaration'
@@ -75,8 +73,6 @@ function forEachDeclarationIdentifier(declaration, cb) {
     if (
       declaration.type === FUNCTION_DECLARATION ||
       declaration.type === CLASS_DECLARATION ||
-      declaration.type === INTERFACE_DECLARATION ||
-      declaration.type === TYPE_ALIAS ||
       declaration.type === TS_INTERFACE_DECLARATION ||
       declaration.type === TS_TYPE_ALIAS_DECLARATION ||
       declaration.type === TS_ENUM_DECLARATION
diff --git a/tests/files/no-unused-modules/flow/flow-0.js b/tests/files/no-unused-modules/flow/flow-0.js
new file mode 100644
index 0000000000..b5e5d8b015
--- /dev/null
+++ b/tests/files/no-unused-modules/flow/flow-0.js
@@ -0,0 +1 @@
+import { type FooType, type FooInterface } from './flow-2';
diff --git a/tests/files/no-unused-modules/flow/flow-1.js b/tests/files/no-unused-modules/flow/flow-1.js
new file mode 100644
index 0000000000..4828eb575c
--- /dev/null
+++ b/tests/files/no-unused-modules/flow/flow-1.js
@@ -0,0 +1,3 @@
+// @flow strict
+export type Bar = number;
+export interface BarInterface {};
diff --git a/tests/files/no-unused-modules/flow/flow-2.js b/tests/files/no-unused-modules/flow/flow-2.js
new file mode 100644
index 0000000000..0c632c2476
--- /dev/null
+++ b/tests/files/no-unused-modules/flow/flow-2.js
@@ -0,0 +1,3 @@
+// @flow strict
+export type FooType = string;
+export interface FooInterface {};
diff --git a/tests/files/no-unused-modules/flow/flow-3.js b/tests/files/no-unused-modules/flow/flow-3.js
new file mode 100644
index 0000000000..ade5393a7d
--- /dev/null
+++ b/tests/files/no-unused-modules/flow/flow-3.js
@@ -0,0 +1 @@
+import type { FooType, FooInterface } from './flow-4';
diff --git a/tests/files/no-unused-modules/flow/flow-4.js b/tests/files/no-unused-modules/flow/flow-4.js
new file mode 100644
index 0000000000..0c632c2476
--- /dev/null
+++ b/tests/files/no-unused-modules/flow/flow-4.js
@@ -0,0 +1,3 @@
+// @flow strict
+export type FooType = string;
+export interface FooInterface {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-a-import-type.ts b/tests/files/no-unused-modules/typescript/file-ts-a-import-type.ts
new file mode 100644
index 0000000000..357d890b9d
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-a-import-type.ts
@@ -0,0 +1,9 @@
+import type {b} from './file-ts-b-used-as-type';
+import type {c} from './file-ts-c-used-as-type';
+import type {d} from './file-ts-d-used-as-type';
+import type {e} from './file-ts-e-used-as-type';
+
+const a: typeof b = 2;
+const a2: c = {};
+const a3: d = {};
+const a4: typeof e = undefined;
diff --git a/tests/files/no-unused-modules/typescript/file-ts-a.ts b/tests/files/no-unused-modules/typescript/file-ts-a.ts
index a5cc566715..2e7984cb95 100644
--- a/tests/files/no-unused-modules/typescript/file-ts-a.ts
+++ b/tests/files/no-unused-modules/typescript/file-ts-a.ts
@@ -3,6 +3,6 @@ import {c} from './file-ts-c';
 import {d} from './file-ts-d';
 import {e} from './file-ts-e';
 
-export const a = b + 1 + e.f;
-export const a2: c = {};
-export const a3: d = {};
+const a = b + 1 + e.f;
+const a2: c = {};
+const a3: d = {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-b-unused.ts b/tests/files/no-unused-modules/typescript/file-ts-b-unused.ts
new file mode 100644
index 0000000000..202103085c
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-b-unused.ts
@@ -0,0 +1 @@
+export const b = 2;
diff --git a/tests/files/no-unused-modules/typescript/file-ts-b-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-b-used-as-type.ts
new file mode 100644
index 0000000000..202103085c
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-b-used-as-type.ts
@@ -0,0 +1 @@
+export const b = 2;
diff --git a/tests/files/no-unused-modules/typescript/file-ts-c-unused.ts b/tests/files/no-unused-modules/typescript/file-ts-c-unused.ts
new file mode 100644
index 0000000000..aedf4062be
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-c-unused.ts
@@ -0,0 +1 @@
+export interface c {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-c-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-c-used-as-type.ts
new file mode 100644
index 0000000000..aedf4062be
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-c-used-as-type.ts
@@ -0,0 +1 @@
+export interface c {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-d-unused.ts b/tests/files/no-unused-modules/typescript/file-ts-d-unused.ts
new file mode 100644
index 0000000000..7679b3de03
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-d-unused.ts
@@ -0,0 +1 @@
+export type d = {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-d-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-d-used-as-type.ts
new file mode 100644
index 0000000000..7679b3de03
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-d-used-as-type.ts
@@ -0,0 +1 @@
+export type d = {};
diff --git a/tests/files/no-unused-modules/typescript/file-ts-e-unused.ts b/tests/files/no-unused-modules/typescript/file-ts-e-unused.ts
new file mode 100644
index 0000000000..d1787a11af
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-e-unused.ts
@@ -0,0 +1 @@
+export enum e { f };
diff --git a/tests/files/no-unused-modules/typescript/file-ts-e-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-e-used-as-type.ts
new file mode 100644
index 0000000000..d1787a11af
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-e-used-as-type.ts
@@ -0,0 +1 @@
+export enum e { f };
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index b6554d129a..3e63a6ac9d 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -744,65 +744,96 @@ describe('Avoid errors if re-export all from umd compiled library', () => {
   })
 })
 
-describe('correctly work with Typescript only files', () => {
-  typescriptRuleTester.run('no-unused-modules', rule, {
-    valid: [
-      test({
-        options: unusedExportsTypescriptOptions,
-        code: 'import a from "file-ts-a";',
-        parser: require.resolve('babel-eslint'),
-        filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
-      }),
-    ],
-    invalid: [
-      test({
-        options: unusedExportsTypescriptOptions,
-        code: `export const b = 2;`,
-        parser: require.resolve('babel-eslint'),
-        filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'),
-        errors: [
-          error(`exported declaration 'b' not used within other modules`),
-        ],
-      }),
-      test({
-        options: unusedExportsTypescriptOptions,
-        code: `export interface c {};`,
-        parser: require.resolve('babel-eslint'),
-        filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'),
-        errors: [
-          error(`exported declaration 'c' not used within other modules`),
-        ],
-      }),
-      test({
-        options: unusedExportsTypescriptOptions,
-        code: `export type d = {};`,
-        parser: require.resolve('babel-eslint'),
-        filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'),
-        errors: [
-          error(`exported declaration 'd' not used within other modules`),
-        ],
-      }),
-    ],
-  })
-})
-
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     typescriptRuleTester.run('no-unused-modules', rule, {
       valid: [
         test({
           options: unusedExportsTypescriptOptions,
-          code: 'import a from "file-ts-a";',
+          code: `
+          import {b} from './file-ts-b';
+          import {c} from './file-ts-c';
+          import {d} from './file-ts-d';
+          import {e} from './file-ts-e';
+
+          const a = b + 1 + e.f;
+          const a2: c = {};
+          const a3: d = {};
+          `,
           parser: parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
         }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export const b = 2;`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export interface c {};`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export type d = {};`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export enum e { f };`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-e.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `
+          import type {b} from './file-ts-b-used-as-type';
+          import type {c} from './file-ts-c-used-as-type';
+          import type {d} from './file-ts-d-used-as-type';
+          import type {e} from './file-ts-e-used-as-type';
+
+          const a: typeof b = 2;
+          const a2: c = {};
+          const a3: d = {};
+          const a4: typeof e = undefined;
+          `,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-a-import-type.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export const b = 2;`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-b-used-as-type.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export interface c {};`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-c-used-as-type.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export type d = {};`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-d-used-as-type.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export enum e { f };`,
+          parser: parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-e-used-as-type.ts'),
+        }),
       ],
       invalid: [
         test({
           options: unusedExportsTypescriptOptions,
           code: `export const b = 2;`,
           parser: parser,
-          filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'),
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-b-unused.ts'),
           errors: [
             error(`exported declaration 'b' not used within other modules`),
           ],
@@ -811,7 +842,7 @@ context('TypeScript', function () {
           options: unusedExportsTypescriptOptions,
           code: `export interface c {};`,
           parser: parser,
-          filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'),
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-c-unused.ts'),
           errors: [
             error(`exported declaration 'c' not used within other modules`),
           ],
@@ -820,7 +851,7 @@ context('TypeScript', function () {
           options: unusedExportsTypescriptOptions,
           code: `export type d = {};`,
           parser: parser,
-          filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'),
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-d-unused.ts'),
           errors: [
             error(`exported declaration 'd' not used within other modules`),
           ],
@@ -829,7 +860,7 @@ context('TypeScript', function () {
           options: unusedExportsTypescriptOptions,
           code: `export enum e { f };`,
           parser: parser,
-          filename: testFilePath('./no-unused-modules/typescript/file-ts-e.ts'),
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-e-unused.ts'),
           errors: [
             error(`exported declaration 'e' not used within other modules`),
           ],
@@ -862,3 +893,51 @@ describe('correctly work with JSX only files', () => {
     ],
   })
 })
+
+describe('ignore flow types', () => {
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsOptions,
+        code: 'import { type FooType, type FooInterface } from "./flow-2";',
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/flow/flow-0.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: `// @flow strict
+               export type FooType = string;
+               export interface FooInterface {};
+               `,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/flow/flow-2.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: 'import type { FooType, FooInterface } from "./flow-4";',
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/flow/flow-3.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: `// @flow strict
+               export type FooType = string;
+               export interface FooInterface {};
+               `,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/flow/flow-4.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: `// @flow strict
+               export type Bar = number;
+               export interface BarInterface {};
+               `,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/flow/flow-1.js'),
+      }),
+    ],
+    invalid: [],
+  })
+})
+

From a00727ee143355f8c9c935025299e41367b1c321 Mon Sep 17 00:00:00 2001
From: Andreu Botella <abb@randomunok.com>
Date: Thu, 20 Aug 2020 20:56:52 +0200
Subject: [PATCH 215/767] [Fix] `export`/TypeScript: properly detect export
 specifiers as children of a TS module block

Fixes #1773
---
 CHANGELOG.md              |  5 ++++
 src/rules/export.js       |  6 ++++-
 tests/src/rules/export.js | 48 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ba0cb63a3..2b47aaa55e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
+
 ## [2.22.1] - 2020-09-27
 ### Fixed
 - [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
@@ -732,6 +735,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1889]: https://github.com/benmosher/eslint-plugin-import/pull/1889
 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
 [#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
 [#1848]: https://github.com/benmosher/eslint-plugin-import/pull/1848
@@ -1276,3 +1280,4 @@ for info on changes for earlier releases.
 [@foray1010]: https://github.com/foray1010
 [@tomprats]: https://github.com/tomprats
 [@straub]: https://github.com/straub
+[@andreubotella]: https://github.com/andreubotella
diff --git a/src/rules/export.js b/src/rules/export.js
index 340972eda0..212a60f6e6 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -87,7 +87,11 @@ module.exports = {
     return {
       'ExportDefaultDeclaration': (node) => addNamed('default', node, getParent(node)),
 
-      'ExportSpecifier': (node) => addNamed(node.exported.name, node.exported, getParent(node)),
+      'ExportSpecifier': (node) => addNamed(
+        node.exported.name,
+        node.exported,
+        getParent(node.parent)
+      ),
 
       'ExportNamedDeclaration': function (node) {
         if (node.declaration == null) return
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 5ecfcae20e..12341c7da9 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -221,6 +221,30 @@ context('TypeScript', function () {
             parser: parser,
           }),
         ]),
+
+        // Exports in ambient modules
+        test(Object.assign({
+          code: `
+            declare module "a" {
+              const Foo = 1;
+              export {Foo as default};
+            }
+            declare module "b" {
+              const Bar = 2;
+              export {Bar as default};
+            }
+          `,
+        }, parserConfig)),
+        test(Object.assign({
+          code: `
+            declare module "a" {
+              const Foo = 1;
+              export {Foo as default};
+            }
+            const Bar = 2;
+            export {Bar as default};
+          `,
+        }, parserConfig)),
       ],
       invalid: [
         // type/value name clash
@@ -312,6 +336,30 @@ context('TypeScript', function () {
             },
           ],
         }, parserConfig)),
+
+        // Exports in ambient modules
+        test(Object.assign({
+          code: `
+            declare module "a" {
+              const Foo = 1;
+              export {Foo as default};
+            }
+            const Bar = 2;
+            export {Bar as default};
+            const Baz = 3;
+            export {Baz as default};
+          `,
+          errors: [
+            {
+              message: 'Multiple default exports.',
+              line: 7,
+            },
+            {
+              message: 'Multiple default exports.',
+              line: 9,
+            },
+          ],
+        }, parserConfig)),
       ],
     })
   })

From 13aa29c4d7a4c0fc86a1739d31c576c43150d4ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= <jlhwung@gmail.com>
Date: Mon, 19 Oct 2020 16:51:19 -0400
Subject: [PATCH 216/767] [Refactor] `importType`: use `is-core-module` instead
 of `resolve/lib/core`

---
 package.json           | 1 +
 src/core/importType.js | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 18fd70af20..f584a8dda4 100644
--- a/package.json
+++ b/package.json
@@ -105,6 +105,7 @@
     "eslint-import-resolver-node": "^0.3.4",
     "eslint-module-utils": "^2.6.0",
     "has": "^1.0.3",
+    "is-core-module": "^1.0.2",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.1",
     "read-pkg-up": "^2.0.0",
diff --git a/src/core/importType.js b/src/core/importType.js
index 25ab2bdced..dc7f889df7 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -1,4 +1,4 @@
-import coreModules from 'resolve/lib/core'
+import isCoreModule from 'is-core-module'
 
 import resolve from 'eslint-module-utils/resolve'
 
@@ -20,7 +20,7 @@ export function isBuiltIn(name, settings, path) {
   if (path || !name) return false
   const base = baseModule(name)
   const extras = (settings && settings['import/core-modules']) || []
-  return coreModules[base] || extras.indexOf(base) > -1
+  return isCoreModule(base) || extras.indexOf(base) > -1
 }
 
 function isExternalPath(path, name, settings) {

From 00a9ad9d64bea44e6a5084f7e5d7bb49a02008bf Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 9 Nov 2020 11:06:47 -0800
Subject: [PATCH 217/767] [meta] remove trailing whitespaces; ensure trailing
 file newlines

---
 .coveralls.yml                   |  2 +-
 docs/rules/no-unused-modules.md  | 12 ++++++------
 tests/src/rules/named.js         |  6 +++---
 tests/src/rules/no-duplicates.js |  4 ++--
 utils/parse.js                   |  4 ++--
 5 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/.coveralls.yml b/.coveralls.yml
index 77bcfb3743..b8ebe05a18 100644
--- a/.coveralls.yml
+++ b/.coveralls.yml
@@ -1,2 +1,2 @@
 ---
-repo_token: fW3moW39Z8pKOgqTnUMT68DnNCd2SM8Ly
\ No newline at end of file
+repo_token: fW3moW39Z8pKOgqTnUMT68DnNCd2SM8Ly
diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index 8c234202f8..4c04333ad3 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -12,7 +12,7 @@ Note: dynamic imports are currently not supported.
 
 In order for this plugin to work, one of the options `missingExports` or `unusedExports` must be enabled (see "Options" section below). In the future, these options will be enabled by default (see https://github.com/benmosher/eslint-plugin-import/issues/1324)
 
-Example: 
+Example:
 ```
 "rules: {
   ...otherRules,
@@ -27,13 +27,13 @@ This rule takes the following option:
 - **`missingExports`**: if `true`, files without any exports are reported (defaults to `false`)
 - **`unusedExports`**: if `true`, exports without any static usage within other modules are reported (defaults to `false`)
 - `src`: an array with files/paths to be analyzed. It only applies to unused exports. Defaults to `process.cwd()`, if not provided
-- `ignoreExports`: an array with files/paths for which unused exports will not be reported (e.g module entry points in a published package) 
+- `ignoreExports`: an array with files/paths for which unused exports will not be reported (e.g module entry points in a published package)
 
 
 ### Example for missing exports
 #### The following will be reported
 ```js
-const class MyClass { /*...*/ } 
+const class MyClass { /*...*/ }
 
 function makeClass() { return new MyClass(...arguments) }
 ```
@@ -41,10 +41,10 @@ function makeClass() { return new MyClass(...arguments) }
 #### The following will not be reported
 
 ```js
-export default function () { /*...*/ } 
+export default function () { /*...*/ }
 ```
 ```js
-export const foo = function () { /*...*/ } 
+export const foo = function () { /*...*/ }
 ```
 ```js
 export { foo, bar }
@@ -61,7 +61,7 @@ import { f } from 'file-b'
 import * as fileC from  'file-c'
 export { default, i0 } from 'file-d' // both will be reported
 
-export const j = 99 // will be reported 
+export const j = 99 // will be reported
 ```
 and file-d:
 ```js
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index eba7bec1ad..030368877f 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -286,9 +286,9 @@ ruleTester.run('named (export *)', rule, {
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     [
-      'typescript', 
-      'typescript-declare', 
-      'typescript-export-assign-namespace', 
+      'typescript',
+      'typescript-declare',
+      'typescript-export-assign-namespace',
       'typescript-export-assign-namespace-merged',
     ].forEach((source) => {
       ruleTester.run(`named`, rule, {
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 0137221b03..65ebc5665e 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -306,7 +306,7 @@ ruleTester.run('no-duplicates', rule, {
       // Not autofix bail.
       output: `
         import {x,y} from './foo'
-        
+
         // some-tool-disable-next-line
       `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
@@ -324,7 +324,7 @@ ruleTester.run('no-duplicates', rule, {
         import {x,y} from './foo'
         // comment
 
-        
+
       `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
diff --git a/utils/parse.js b/utils/parse.js
index b3a469221d..8f3104bf90 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -31,14 +31,14 @@ exports.default = function parse(path, content, context) {
   // provide the `filePath` like eslint itself does, in `parserOptions`
   // https://github.com/eslint/eslint/blob/3ec436ee/lib/linter.js#L637
   parserOptions.filePath = path
-  
+
   // @typescript-eslint/parser will parse the entire project with typechecking if you provide
   // "project" or "projects" in parserOptions. Removing these options means the parser will
   // only parse one file in isolate mode, which is much, much faster.
   // https://github.com/benmosher/eslint-plugin-import/issues/1408#issuecomment-509298962
   delete parserOptions.project
   delete parserOptions.projects
-  
+
   // require the parser relative to the main module (i.e., ESLint)
   const parser = moduleRequire(parserPath)
 

From 6cd1fe15882c06d266bfc3758ccac5df83bd53f2 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 10 Nov 2020 18:07:57 -0800
Subject: [PATCH 218/767] [Tests] fix broken test from 00a9ad9d

---
 tests/src/rules/no-duplicates.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 65ebc5665e..0137221b03 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -306,7 +306,7 @@ ruleTester.run('no-duplicates', rule, {
       // Not autofix bail.
       output: `
         import {x,y} from './foo'
-
+        
         // some-tool-disable-next-line
       `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
@@ -324,7 +324,7 @@ ruleTester.run('no-duplicates', rule, {
         import {x,y} from './foo'
         // comment
 
-
+        
       `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),

From 957092a8ecfd479c524bb0fa5d37ba9f5921bd5e Mon Sep 17 00:00:00 2001
From: Chiawen Chen <golopot@gmail.com>
Date: Tue, 10 Nov 2020 12:44:56 +0800
Subject: [PATCH 219/767] [Fix] `order`: ignore non-module-level requires

Fixes #1936.
---
 CHANGELOG.md             |  2 ++
 src/rules/order.js       | 38 ++++++++++++++++----------------------
 tests/src/rules/order.js | 14 +++++++++++++-
 3 files changed, 31 insertions(+), 23 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b47aaa55e..10c77d4e6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
+- [`order`]: ignore non-module-level requires ([#1940], thanks [@golopot])
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -735,6 +736,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940
 [#1889]: https://github.com/benmosher/eslint-plugin-import/pull/1889
 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
 [#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
diff --git a/src/rules/order.js b/src/rules/order.js
index 1d7d3efd62..fe2376cfe1 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -333,9 +333,21 @@ function registerNode(context, importEntry, ranks, imported, excludedImportTypes
   }
 }
 
-function isInVariableDeclarator(node) {
-  return node &&
-    (node.type === 'VariableDeclarator' || isInVariableDeclarator(node.parent))
+function isModuleLevelRequire(node) {
+  let n = node
+  // Handle cases like `const baz = require('foo').bar.baz`
+  // and `const foo = require('foo')()`
+  while ( 
+    (n.parent.type === 'MemberExpression' && n.parent.object === n) ||
+    (n.parent.type === 'CallExpression' && n.parent.callee === n)
+   ) {
+    n = n.parent
+  }
+  return (
+    n.parent.type === 'VariableDeclarator' &&
+    n.parent.parent.type === 'VariableDeclaration' &&
+    n.parent.parent.parent.type === 'Program' 
+  )
 }
 
 const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object']
@@ -583,14 +595,6 @@ module.exports = {
       }
     }
     let imported = []
-    let level = 0
-
-    function incrementLevel() {
-      level++
-    }
-    function decrementLevel() {
-      level--
-    }
 
     return {
       ImportDeclaration: function handleImports(node) {
@@ -641,7 +645,7 @@ module.exports = {
         )
       },
       CallExpression: function handleRequires(node) {
-        if (level !== 0 || !isStaticRequire(node) || !isInVariableDeclarator(node.parent)) {
+        if (!isStaticRequire(node) || !isModuleLevelRequire(node)) {
           return
         }
         const name = node.arguments[0].value
@@ -671,16 +675,6 @@ module.exports = {
 
         imported = []
       },
-      FunctionDeclaration: incrementLevel,
-      FunctionExpression: incrementLevel,
-      ArrowFunctionExpression: incrementLevel,
-      BlockStatement: incrementLevel,
-      ObjectExpression: incrementLevel,
-      'FunctionDeclaration:exit': decrementLevel,
-      'FunctionExpression:exit': decrementLevel,
-      'ArrowFunctionExpression:exit': decrementLevel,
-      'BlockStatement:exit': decrementLevel,
-      'ObjectExpression:exit': decrementLevel,
     }
   },
 }
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 0c5405823f..497911ffbe 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -74,7 +74,7 @@ ruleTester.run('order', rule, {
         var result = add(1, 2);
         var _ = require('lodash');`,
     }),
-    // Ignore requires that are not at the top-level
+    // Ignore requires that are not at the top-level #1
     test({
       code: `
         var index = require('./');
@@ -86,6 +86,18 @@ ruleTester.run('order', rule, {
           require('fs');
         }`,
     }),
+    // Ignore requires that are not at the top-level #2
+    test({
+      code: `
+        const foo = [
+          require('./foo'),
+          require('fs'),
+        ]`,
+    }),
+    // Ignore requires in template literal (#1936)
+    test({
+      code: "const foo = `${require('./a')} ${require('fs')}`",
+    }),
     // Ignore unknown/invalid cases
     test({
       code: `

From dd4e416939f83de61298610c0bee455b25063915 Mon Sep 17 00:00:00 2001
From: Leonardo Dino <leonardo@kunstdesign.com.br>
Date: Mon, 16 Nov 2020 21:17:33 +0000
Subject: [PATCH 220/767] [Fix] `no-webpack-loader-syntax`/TypeScript: avoid
 crash on missing name

---
 CHANGELOG.md                                |  2 ++
 src/rules/no-webpack-loader-syntax.js       |  2 +-
 tests/src/rules/no-webpack-loader-syntax.js | 25 ++++++++++++++++++++-
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 10c77d4e6e..7ff3b8bcec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
 - [`order`]: ignore non-module-level requires ([#1940], thanks [@golopot])
+- [`no-webpack-loader-syntax`]/TypeScript: avoid crash on missing name ([#1947], thanks @leonardodino)
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -736,6 +737,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1947]: https://github.com/benmosher/eslint-plugin-import/pull/1947
 [#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940
 [#1889]: https://github.com/benmosher/eslint-plugin-import/pull/1889
 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
diff --git a/src/rules/no-webpack-loader-syntax.js b/src/rules/no-webpack-loader-syntax.js
index 8075a6f9eb..a80bc112d5 100644
--- a/src/rules/no-webpack-loader-syntax.js
+++ b/src/rules/no-webpack-loader-syntax.js
@@ -2,7 +2,7 @@ import isStaticRequire from '../core/staticRequire'
 import docsUrl from '../docsUrl'
 
 function reportIfNonStandard(context, node, name) {
-  if (name.indexOf('!') !== -1) {
+  if (name && name.indexOf('!') !== -1) {
     context.report(node, `Unexpected '!' in '${name}'. ` +
       'Do not use import syntax to configure webpack loaders.'
     )
diff --git a/tests/src/rules/no-webpack-loader-syntax.js b/tests/src/rules/no-webpack-loader-syntax.js
index 23a1190fb5..a56e142e71 100644
--- a/tests/src/rules/no-webpack-loader-syntax.js
+++ b/tests/src/rules/no-webpack-loader-syntax.js
@@ -1,4 +1,4 @@
-import { test } from '../utils'
+import { test, getTSParsers } from '../utils'
 
 import { RuleTester } from 'eslint'
 
@@ -72,3 +72,26 @@ ruleTester.run('no-webpack-loader-syntax', rule, {
     }),
   ],
 })
+
+context('TypeScript', function () {
+  getTSParsers().forEach((parser) => {
+    const parserConfig = {
+      parser: parser,
+      settings: {
+        'import/parsers': { [parser]: ['.ts'] },
+        'import/resolver': { 'eslint-import-resolver-typescript': true },
+      },
+    }
+    ruleTester.run('no-webpack-loader-syntax', rule, {
+      valid: [
+        test(Object.assign({
+          code: 'import { foo } from\nalert()',
+        }, parserConfig)),
+        test(Object.assign({
+          code: 'import foo from\nalert()',
+        }, parserConfig)),
+      ],
+      invalid: [],
+    })
+  })
+})

From 8c1a65d0bdf446b03e513cc2b7377ca49232a6c3 Mon Sep 17 00:00:00 2001
From: eric wang <eric@canva.com>
Date: Wed, 18 Nov 2020 15:50:16 +1100
Subject: [PATCH 221/767] [patch] `no-extraneous-dependencies`: Add
 package.json cache

---
 CHANGELOG.md                            |  2 ++
 src/rules/no-extraneous-dependencies.js | 13 ++++++++++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7ff3b8bcec..f46786c923 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
 - [`order`]: ignore non-module-level requires ([#1940], thanks [@golopot])
 - [`no-webpack-loader-syntax`]/TypeScript: avoid crash on missing name ([#1947], thanks @leonardodino)
+- [`no-extraneous-dependencies`]: Add package.json cache ([#1948], thanks @fa93hws)
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -737,6 +738,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
 [#1947]: https://github.com/benmosher/eslint-plugin-import/pull/1947
 [#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940
 [#1889]: https://github.com/benmosher/eslint-plugin-import/pull/1889
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 366a684c40..56bda2cb3a 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -7,6 +7,8 @@ import moduleVisitor from 'eslint-module-utils/moduleVisitor'
 import importType from '../core/importType'
 import docsUrl from '../docsUrl'
 
+const depFieldCache = new Map()
+
 function hasKeys(obj = {}) {
   return Object.keys(obj).length > 0
 }
@@ -49,9 +51,14 @@ function getDependencies(context, packageDir) {
     if (paths.length > 0) {
       // use rule config to find package.json
       paths.forEach(dir => {
-        const _packageContent = extractDepFields(
-          JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'))
-        )
+        const packageJsonPath = path.join(dir, 'package.json')
+        if (!depFieldCache.has(packageJsonPath)) {
+          const depFields = extractDepFields(
+            JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
+          )
+          depFieldCache.set(packageJsonPath, depFields)
+        }
+        const _packageContent = depFieldCache.get(packageJsonPath)
         Object.keys(packageContent).forEach(depsKey =>
           Object.assign(packageContent[depsKey], _packageContent[depsKey])
         )

From e6f601812c2b30531beb7f5155c2e0a774db8ee4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 15 Dec 2020 15:24:52 -0800
Subject: [PATCH 222/767] [Fix] `prefer-default-export`: handle empty array
 destructuring

Fixes #1965
---
 CHANGELOG.md                             | 2 ++
 src/rules/prefer-default-export.js       | 4 ++--
 tests/src/rules/prefer-default-export.js | 6 ++++++
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f46786c923..3c5da1d455 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]: ignore non-module-level requires ([#1940], thanks [@golopot])
 - [`no-webpack-loader-syntax`]/TypeScript: avoid crash on missing name ([#1947], thanks @leonardodino)
 - [`no-extraneous-dependencies`]: Add package.json cache ([#1948], thanks @fa93hws)
+- [`prefer-default-export`]: handle empty array destructuring ([#1965], thanks @ljharb)
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -738,6 +739,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
 [#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
 [#1947]: https://github.com/benmosher/eslint-plugin-import/pull/1947
 [#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index f1db4eaaa6..002cf2870f 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -19,13 +19,13 @@ module.exports = {
     let namedExportNode = null
 
     function captureDeclaration(identifierOrPattern) {
-      if (identifierOrPattern.type === 'ObjectPattern') {
+      if (identifierOrPattern && identifierOrPattern.type === 'ObjectPattern') {
         // recursively capture
         identifierOrPattern.properties
           .forEach(function(property) {
             captureDeclaration(property.value)
           })
-      } else if (identifierOrPattern.type === 'ArrayPattern') {
+      } else if (identifierOrPattern && identifierOrPattern.type === 'ArrayPattern') {
         identifierOrPattern.elements
           .forEach(captureDeclaration)
       } else  {
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 9e38cea926..dae930a73d 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -88,6 +88,12 @@ ruleTester.run('prefer-default-export', rule, {
       parser: require.resolve('babel-eslint'),
     }),
     // ...SYNTAX_CASES,
+    {
+      code: `
+        export const [CounterProvider,, withCounter] = func();;
+      `,
+      parser: require.resolve('babel-eslint'),
+    },
   ],
   invalid: [
     test({

From 18f9bd31fb613d9062dd6fe8057b0e1f519e4154 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 20 Dec 2020 22:49:14 -0800
Subject: [PATCH 223/767] [Tests] `prefer-default-export`: fix test case

See https://github.com/benmosher/eslint-plugin-import/commit/e6f601812c2b30531beb7f5155c2e0a774db8ee4#r45298298
---
 tests/src/rules/prefer-default-export.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index dae930a73d..e948b9f9e0 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -88,12 +88,12 @@ ruleTester.run('prefer-default-export', rule, {
       parser: require.resolve('babel-eslint'),
     }),
     // ...SYNTAX_CASES,
-    {
+    test({
       code: `
         export const [CounterProvider,, withCounter] = func();;
       `,
       parser: require.resolve('babel-eslint'),
-    },
+    }),
   ],
   invalid: [
     test({

From ff50964df1234515bc6f7969b90d87ada1982008 Mon Sep 17 00:00:00 2001
From: Anders Kaseorg <andersk@mit.edu>
Date: Mon, 21 Dec 2020 20:07:58 -0800
Subject: [PATCH 224/767] [resolvers/webpack] Replace node-libs-browser with
 is-core-module

This significantly shrinks our dependency tree.  Fixes #631.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
---
 resolvers/webpack/index.js     | 6 +++---
 resolvers/webpack/package.json | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 677d7584cf..c15bfafe03 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -5,7 +5,7 @@ var findRoot = require('find-root')
   , find = require('array-find')
   , interpret = require('interpret')
   , fs = require('fs')
-  , coreLibs = require('node-libs-browser')
+  , isCore = require('is-core-module')
   , resolve = require('resolve')
   , semver = require('semver')
   , has = require('has')
@@ -142,8 +142,8 @@ exports.resolve = function (source, file, settings) {
   try {
     return { found: true, path: resolveSync(path.dirname(file), source) }
   } catch (err) {
-    if (source in coreLibs) {
-      return { found: true, path: coreLibs[source] }
+    if (isCore(source)) {
+      return { found: true, path: null }
     }
 
     log('Error during module resolution:', err)
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index ee13908bbc..82ff610de5 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -38,8 +38,8 @@
     "find-root": "^1.1.0",
     "has": "^1.0.3",
     "interpret": "^1.2.0",
+    "is-core-module": "^2.0.0",
     "lodash": "^4.17.15",
-    "node-libs-browser": "^1.0.0 || ^2.0.0",
     "resolve": "^1.13.1",
     "semver": "^5.7.1"
   },

From 369b502b68ad8b3a69ea52605cf81b3bacc8ebf0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 17 Jan 2021 10:00:26 -0800
Subject: [PATCH 225/767] [meta] fix `semi` rule.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Sorry, it‘s time.
---
 .eslintrc                                     |   6 +-
 config/electron.js                            |   2 +-
 config/errors.js                              |   2 +-
 config/react-native.js                        |   2 +-
 config/react.js                               |   2 +-
 config/recommended.js                         |   2 +-
 config/stage-0.js                             |   2 +-
 config/typescript.js                          |   4 +-
 config/warnings.js                            |   2 +-
 memo-parser/index.js                          |  34 +-
 resolvers/node/index.js                       |  32 +-
 resolvers/node/test/native.js                 |   2 +-
 resolvers/node/test/paths.js                  |  48 +-
 resolvers/webpack/config.js                   |   2 +-
 resolvers/webpack/index.js                    | 236 +++----
 resolvers/webpack/test/alias.js               |  18 +-
 .../config-extensions/webpack.config.babel.js |   4 +-
 resolvers/webpack/test/config.js              |  96 +--
 .../test/custom-extensions/webpack.config.js  |   2 +-
 resolvers/webpack/test/example.js             |  10 +-
 resolvers/webpack/test/extensions.js          |  26 +-
 resolvers/webpack/test/externals.js           |  40 +-
 resolvers/webpack/test/fallback.js            |  24 +-
 resolvers/webpack/test/loaders.js             |  24 +-
 resolvers/webpack/test/modules.js             |  16 +-
 .../test/package-mains/webpack.alt.config.js  |   2 +-
 resolvers/webpack/test/packageMains.js        |  36 +-
 resolvers/webpack/test/plugins.js             |  28 +-
 resolvers/webpack/test/root.js                |  36 +-
 scripts/copyMetafiles.js                      |  16 +-
 scripts/resolverDirectories.js                |   4 +-
 scripts/testAll.js                            |  14 +-
 src/ExportMap.js                              | 476 ++++++-------
 src/core/importType.js                        |  90 +--
 src/core/staticRequire.js                     |   2 +-
 src/docsUrl.js                                |   6 +-
 src/importDeclaration.js                      |   4 +-
 src/index.js                                  |   4 +-
 src/rules/default.js                          |  20 +-
 src/rules/dynamic-import-chunkname.js         |  60 +-
 src/rules/export.js                           |  78 +--
 src/rules/exports-last.js                     |  18 +-
 src/rules/extensions.js                       |  90 +--
 src/rules/first.js                            |  78 +--
 src/rules/group-exports.js                    |  70 +-
 src/rules/imports-first.js                    |   8 +-
 src/rules/max-dependencies.js                 |  32 +-
 src/rules/named.js                            |  38 +-
 src/rules/namespace.js                        | 126 ++--
 src/rules/newline-after-import.js             |  92 +--
 src/rules/no-absolute-path.js                 |  14 +-
 src/rules/no-amd.js                           |  20 +-
 src/rules/no-anonymous-default-export.js      |  28 +-
 src/rules/no-commonjs.js                      |  64 +-
 src/rules/no-cycle.js                         |  62 +-
 src/rules/no-default-export.js                |  20 +-
 src/rules/no-deprecated.js                    | 110 +--
 src/rules/no-duplicates.js                    | 156 ++---
 src/rules/no-dynamic-require.js               |  12 +-
 src/rules/no-extraneous-dependencies.js       | 114 +--
 src/rules/no-internal-modules.js              |  58 +-
 src/rules/no-mutable-exports.js               |  22 +-
 src/rules/no-named-as-default-member.js       |  60 +-
 src/rules/no-named-as-default.js              |  24 +-
 src/rules/no-named-default.js                 |  10 +-
 src/rules/no-named-export.js                  |  18 +-
 src/rules/no-namespace.js                     |  90 +--
 src/rules/no-nodejs-modules.js                |  20 +-
 src/rules/no-relative-parent-imports.js       |  30 +-
 src/rules/no-restricted-paths.js              |  68 +-
 src/rules/no-self-import.js                   |  18 +-
 src/rules/no-unassigned-import.js             |  34 +-
 src/rules/no-unresolved.js                    |  22 +-
 src/rules/no-unused-modules.js                | 648 +++++++++---------
 src/rules/no-useless-path-segments.js         |  70 +-
 src/rules/no-webpack-loader-syntax.js         |  14 +-
 src/rules/order.js                            | 440 ++++++------
 src/rules/prefer-default-export.js            |  58 +-
 src/rules/unambiguous.js                      |  12 +-
 tests/src/cli.js                              |  42 +-
 tests/src/config/typescript.js                |  18 +-
 tests/src/core/docsUrl.js                     |  16 +-
 tests/src/core/eslintParser.js                |   4 +-
 tests/src/core/getExports.js                  | 370 +++++-----
 tests/src/core/hash.js                        |  76 +-
 tests/src/core/ignore.js                      |  88 +--
 tests/src/core/importType.js                  | 266 +++----
 tests/src/core/parse.js                       |  96 +--
 tests/src/core/parseStubParser.js             |   2 +-
 tests/src/core/resolve.js                     | 284 ++++----
 tests/src/package.js                          |  58 +-
 tests/src/rules/default.js                    |  20 +-
 tests/src/rules/dynamic-import-chunkname.js   |  44 +-
 tests/src/rules/export.js                     |  20 +-
 tests/src/rules/exports-last.js               |  12 +-
 tests/src/rules/extensions.js                 |  10 +-
 tests/src/rules/first.js                      |   8 +-
 tests/src/rules/group-exports.js              |  16 +-
 tests/src/rules/max-dependencies.js           |   8 +-
 tests/src/rules/named.js                      |  24 +-
 tests/src/rules/namespace.js                  |  20 +-
 tests/src/rules/newline-after-import.js       |  18 +-
 tests/src/rules/no-absolute-path.js           |  10 +-
 tests/src/rules/no-amd.js                     |  10 +-
 .../src/rules/no-anonymous-default-export.js  |  10 +-
 tests/src/rules/no-commonjs.js                |  12 +-
 tests/src/rules/no-cycle.js                   |  12 +-
 tests/src/rules/no-default-export.js          |   8 +-
 tests/src/rules/no-deprecated.js              |  18 +-
 tests/src/rules/no-duplicates.js              |  20 +-
 tests/src/rules/no-dynamic-require.js         |  10 +-
 tests/src/rules/no-extraneous-dependencies.js |  62 +-
 tests/src/rules/no-internal-modules.js        |  12 +-
 tests/src/rules/no-mutable-exports.js         |  10 +-
 tests/src/rules/no-named-as-default-member.js |  10 +-
 tests/src/rules/no-named-as-default.js        |   8 +-
 tests/src/rules/no-named-default.js           |   8 +-
 tests/src/rules/no-named-export.js            |   8 +-
 tests/src/rules/no-namespace.js               |  16 +-
 tests/src/rules/no-nodejs-modules.js          |  10 +-
 tests/src/rules/no-relative-parent-imports.js |  12 +-
 tests/src/rules/no-restricted-paths.js        |  10 +-
 tests/src/rules/no-self-import.js             |  10 +-
 tests/src/rules/no-unassigned-import.js       |  12 +-
 tests/src/rules/no-unresolved.js              |  34 +-
 tests/src/rules/no-unused-modules.js          | 170 ++---
 tests/src/rules/no-useless-path-segments.js   |  12 +-
 tests/src/rules/no-webpack-loader-syntax.js   |  18 +-
 tests/src/rules/order.js                      |  24 +-
 tests/src/rules/prefer-default-export.js      |  16 +-
 tests/src/rules/unambiguous.js                |   6 +-
 tests/src/utils.js                            |  34 +-
 utils/ModuleCache.js                          |  32 +-
 utils/declaredScope.js                        |  14 +-
 utils/hash.js                                 |  60 +-
 utils/ignore.js                               |  50 +-
 utils/module-require.js                       |  28 +-
 utils/moduleVisitor.js                        |  90 +--
 utils/parse.js                                |  68 +-
 utils/resolve.js                              | 176 ++---
 utils/unambiguous.js                          |  16 +-
 141 files changed, 3524 insertions(+), 3524 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index d02c02a69d..16bd77655d 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -18,17 +18,17 @@
         "ecmaVersion": 6,
     },
     "rules": {
-        "max-len": [1, 99, 2],
-        "semi": [2, "never"],
-        "curly": [2, "multi-line"],
         "comma-dangle": [2, "always-multiline"],
+        "curly": [2, "multi-line"],
         "eol-last": [2, "always"],
         "eqeqeq": [2, "allow-null"],
+        "max-len": [1, 99, 2],
         "no-shadow": 1,
         "quotes": [2, "single", {
             "allowTemplateLiterals": true,
             "avoidEscape": true,
         }],
+        "semi": [2, "always"],
         "eslint-plugin/consistent-output": [
             "error",
             "always",
diff --git a/config/electron.js b/config/electron.js
index 6fab4e8b9e..f98ff0614b 100644
--- a/config/electron.js
+++ b/config/electron.js
@@ -5,4 +5,4 @@ module.exports = {
   settings: {
     'import/core-modules': ['electron'],
   },
-}
+};
diff --git a/config/errors.js b/config/errors.js
index d99a9dacf0..d13ef4ba09 100644
--- a/config/errors.js
+++ b/config/errors.js
@@ -11,4 +11,4 @@ module.exports = {
          , 'import/default': 2
          , 'import/export': 2,
          },
-}
+};
diff --git a/config/react-native.js b/config/react-native.js
index fbc8652c9f..a1aa0ee565 100644
--- a/config/react-native.js
+++ b/config/react-native.js
@@ -10,4 +10,4 @@ module.exports = {
       },
     },
   },
-}
+};
diff --git a/config/react.js b/config/react.js
index fe1b5f2ec1..68555512d7 100644
--- a/config/react.js
+++ b/config/react.js
@@ -15,4 +15,4 @@ module.exports = {
     ecmaFeatures: { jsx: true },
   },
 
-}
+};
diff --git a/config/recommended.js b/config/recommended.js
index 9970918933..8e7ca9fd05 100644
--- a/config/recommended.js
+++ b/config/recommended.js
@@ -25,4 +25,4 @@ module.exports = {
     sourceType: 'module',
     ecmaVersion: 2018,
   },
-}
+};
diff --git a/config/stage-0.js b/config/stage-0.js
index 25ad75feb1..42419123f0 100644
--- a/config/stage-0.js
+++ b/config/stage-0.js
@@ -9,4 +9,4 @@ module.exports = {
   rules: {
     'import/no-deprecated': 1,
   },
-}
+};
diff --git a/config/typescript.js b/config/typescript.js
index 705faaf372..0138d6378c 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -2,7 +2,7 @@
  * Adds `.jsx`, `.ts` and `.tsx` as an extension, and enables JSX/TSX parsing.
  */
 
-var allExtensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx']
+var allExtensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx'];
 
 module.exports = {
 
@@ -25,4 +25,4 @@ module.exports = {
     // TypeScript compilation already ensures that named imports exist in the referenced module
     'import/named': 'off',
   },
-}
+};
diff --git a/config/warnings.js b/config/warnings.js
index c05eb0722a..5d74143b28 100644
--- a/config/warnings.js
+++ b/config/warnings.js
@@ -9,4 +9,4 @@ module.exports = {
     'import/no-named-as-default-member': 1,
     'import/no-duplicates': 1,
   },
-}
+};
diff --git a/memo-parser/index.js b/memo-parser/index.js
index b64f854219..1460f8ff38 100644
--- a/memo-parser/index.js
+++ b/memo-parser/index.js
@@ -1,10 +1,10 @@
-'use strict'
+'use strict';
 
 const crypto = require('crypto')
     , moduleRequire = require('eslint-module-utils/module-require').default
-    , hashObject = require('eslint-module-utils/hash').hashObject
+    , hashObject = require('eslint-module-utils/hash').hashObject;
 
-const cache = new Map()
+const cache = new Map();
 
 // must match ESLint default options or we'll miss the cache every time
 const parserOptions = {
@@ -14,28 +14,28 @@ const parserOptions = {
   tokens: true,
   comment: true,
   attachComment: true,
-}
+};
 
 exports.parse = function parse(content, options) {
-  options = Object.assign({}, options, parserOptions)
+  options = Object.assign({}, options, parserOptions);
 
   if (!options.filePath) {
-    throw new Error('no file path provided!')
+    throw new Error('no file path provided!');
   }
 
-  const keyHash = crypto.createHash('sha256')
-  keyHash.update(content)
-  hashObject(options, keyHash)
+  const keyHash = crypto.createHash('sha256');
+  keyHash.update(content);
+  hashObject(options, keyHash);
 
-  const key = keyHash.digest('hex')
+  const key = keyHash.digest('hex');
 
-  let ast = cache.get(key)
-  if (ast != null) return ast
+  let ast = cache.get(key);
+  if (ast != null) return ast;
 
-  const realParser = moduleRequire(options.parser)
+  const realParser = moduleRequire(options.parser);
 
-  ast = realParser.parse(content, options)
-  cache.set(key, ast)
+  ast = realParser.parse(content, options);
+  cache.set(key, ast);
 
-  return ast
-}
+  return ast;
+};
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index bf2aab3820..3d6d85ee7c 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -1,28 +1,28 @@
 var resolve = require('resolve')
-  , path = require('path')
+  , path = require('path');
 
-var log = require('debug')('eslint-plugin-import:resolver:node')
+var log = require('debug')('eslint-plugin-import:resolver:node');
 
-exports.interfaceVersion = 2
+exports.interfaceVersion = 2;
 
 exports.resolve = function (source, file, config) {
-  log('Resolving:', source, 'from:', file)
-  var resolvedPath
+  log('Resolving:', source, 'from:', file);
+  var resolvedPath;
 
   if (resolve.isCore(source)) {
-    log('resolved to core')
-    return { found: true, path: null }
+    log('resolved to core');
+    return { found: true, path: null };
   }
 
   try {
-    resolvedPath = resolve.sync(source, opts(file, config))
-    log('Resolved to:', resolvedPath)
-    return { found: true, path: resolvedPath }
+    resolvedPath = resolve.sync(source, opts(file, config));
+    log('Resolved to:', resolvedPath);
+    return { found: true, path: resolvedPath };
   } catch (err) {
-    log('resolve threw error:', err)
-    return { found: false }
+    log('resolve threw error:', err);
+    return { found: false };
   }
-}
+};
 
 function opts(file, config) {
   return Object.assign({
@@ -36,12 +36,12 @@ function opts(file, config) {
       basedir: path.dirname(path.resolve(file)),
       packageFilter: packageFilter,
 
-    })
+    });
 }
 
 function packageFilter(pkg) {
   if (pkg['jsnext:main']) {
-    pkg['main'] = pkg['jsnext:main']
+    pkg['main'] = pkg['jsnext:main'];
   }
-  return pkg
+  return pkg;
 }
diff --git a/resolvers/node/test/native.js b/resolvers/node/test/native.js
index c2a4339049..4e8441ff0a 100644
--- a/resolvers/node/test/native.js
+++ b/resolvers/node/test/native.js
@@ -1 +1 @@
-exports.natively = function () { return "but where do we feature?" }
+exports.natively = function () { return "but where do we feature?"; };
diff --git a/resolvers/node/test/paths.js b/resolvers/node/test/paths.js
index d50366d13c..ace7cc1ef8 100644
--- a/resolvers/node/test/paths.js
+++ b/resolvers/node/test/paths.js
@@ -1,24 +1,24 @@
-var expect = require('chai').expect
+var expect = require('chai').expect;
 
-var path = require('path')
-var node = require('../index.js')
+var path = require('path');
+var node = require('../index.js');
 
 describe("paths", function () {
   it("handles base path relative to CWD", function () {
     expect(node.resolve('../', './test/file.js'))
       .to.have.property('path')
-      .equal(path.resolve(__dirname, '../index.js'))
-  })
-})
+      .equal(path.resolve(__dirname, '../index.js'));
+  });
+});
 
 
 describe("core", function () {
   it("returns found, but null path, for core Node modules", function () {
-    var resolved = node.resolve('fs', "./test/file.js")
-    expect(resolved).has.property("found", true)
-    expect(resolved).has.property("path", null)
-  })
-})
+    var resolved = node.resolve('fs', "./test/file.js");
+    expect(resolved).has.property("found", true);
+    expect(resolved).has.property("path", null);
+  });
+});
 
 
 describe("default options", function () {
@@ -26,35 +26,35 @@ describe("default options", function () {
   it("finds .json files", function () {
     expect(node.resolve('./data', './test/file.js'))
       .to.have.property('path')
-      .equal(path.resolve(__dirname, './data.json'))
-  })
+      .equal(path.resolve(__dirname, './data.json'));
+  });
 
   it("ignores .json files if 'extensions' is redefined", function () {
     expect(node.resolve('./data', './test/file.js', { extensions: ['.js'] }))
-      .to.have.property('found', false)
-  })
+      .to.have.property('found', false);
+  });
 
   it("finds mjs modules, with precedence over .js", function () {
     expect(node.resolve('./native', './test/file.js'))
       .to.have.property('path')
-      .equal(path.resolve(__dirname, './native.mjs'))
-  })
+      .equal(path.resolve(__dirname, './native.mjs'));
+  });
 
   it("finds .node modules, with lowest precedence", function () {
     expect(node.resolve('./native.node', './test/file.js'))
       .to.have.property('path')
-      .equal(path.resolve(__dirname, './native.node'))
-  })
+      .equal(path.resolve(__dirname, './native.node'));
+  });
 
   it("finds .node modules", function () {
     expect(node.resolve('./dot-node', './test/file.js'))
       .to.have.property('path')
-      .equal(path.resolve(__dirname, './dot-node.node'))
-  })
+      .equal(path.resolve(__dirname, './dot-node.node'));
+  });
 
   it("still finds .js if explicit", function () {
     expect(node.resolve('./native.js', './test/file.js'))
       .to.have.property('path')
-      .equal(path.resolve(__dirname, './native.js'))
-  })
-})
+      .equal(path.resolve(__dirname, './native.js'));
+  });
+});
diff --git a/resolvers/webpack/config.js b/resolvers/webpack/config.js
index d15f082daa..894787d1f3 100644
--- a/resolvers/webpack/config.js
+++ b/resolvers/webpack/config.js
@@ -5,4 +5,4 @@ module.exports = {
   settings: {
     'import/resolver': 'webpack',
   },
-}
+};
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index c15bfafe03..e9bf38a492 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -8,11 +8,11 @@ var findRoot = require('find-root')
   , isCore = require('is-core-module')
   , resolve = require('resolve')
   , semver = require('semver')
-  , has = require('has')
+  , has = require('has');
 
-var log = require('debug')('eslint-plugin-import:resolver:webpack')
+var log = require('debug')('eslint-plugin-import:resolver:webpack');
 
-exports.interfaceVersion = 2
+exports.interfaceVersion = 2;
 
 /**
  * Find the full path to 'source', given 'file' as a full reference path.
@@ -35,18 +35,18 @@ exports.interfaceVersion = 2
 exports.resolve = function (source, file, settings) {
 
   // strip loaders
-  var finalBang = source.lastIndexOf('!')
+  var finalBang = source.lastIndexOf('!');
   if (finalBang >= 0) {
-    source = source.slice(finalBang + 1)
+    source = source.slice(finalBang + 1);
   }
 
   // strip resource query
-  var finalQuestionMark = source.lastIndexOf('?')
+  var finalQuestionMark = source.lastIndexOf('?');
   if (finalQuestionMark >= 0) {
-    source = source.slice(0, finalQuestionMark)
+    source = source.slice(0, finalQuestionMark);
   }
 
-  var webpackConfig
+  var webpackConfig;
 
   var _configPath = get(settings, 'config')
     /**
@@ -57,13 +57,13 @@ exports.resolve = function (source, file, settings) {
     , configIndex = get(settings, 'config-index')
     , env = get(settings, 'env')
     , argv = get(settings, 'argv', {})
-    , packageDir
+    , packageDir;
 
   var configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
     ? path.resolve(_configPath)
-    : _configPath
+    : _configPath;
 
-  log('Config path from settings:', configPath)
+  log('Config path from settings:', configPath);
 
   // see if we've got a config path, a config object, an array of config objects or a config function
   if (!configPath || typeof configPath === 'string') {
@@ -71,146 +71,146 @@ exports.resolve = function (source, file, settings) {
       // see if we've got an absolute path
       if (!configPath || !path.isAbsolute(configPath)) {
         // if not, find ancestral package.json and use its directory as base for the path
-        packageDir = findRoot(path.resolve(file))
-        if (!packageDir) throw new Error('package not found above ' + file)
+        packageDir = findRoot(path.resolve(file));
+        if (!packageDir) throw new Error('package not found above ' + file);
       }
 
-      configPath = findConfigPath(configPath, packageDir)
+      configPath = findConfigPath(configPath, packageDir);
 
-      log('Config path resolved to:', configPath)
+      log('Config path resolved to:', configPath);
       if (configPath) {
         try {
-          webpackConfig = require(configPath)
+          webpackConfig = require(configPath);
         } catch(e) {
-          console.log('Error resolving webpackConfig', e)
-          throw e
+          console.log('Error resolving webpackConfig', e);
+          throw e;
         }
       } else {
-        log('No config path found relative to', file, '; using {}')
-        webpackConfig = {}
+        log('No config path found relative to', file, '; using {}');
+        webpackConfig = {};
       }
 
       if (webpackConfig && webpackConfig.default) {
-        log('Using ES6 module "default" key instead of module.exports.')
-        webpackConfig = webpackConfig.default
+        log('Using ES6 module "default" key instead of module.exports.');
+        webpackConfig = webpackConfig.default;
       }
 
   } else {
-    webpackConfig = configPath
-    configPath = null
+    webpackConfig = configPath;
+    configPath = null;
   }
 
   if (typeof webpackConfig === 'function') {
-    webpackConfig = webpackConfig(env, argv)
+    webpackConfig = webpackConfig(env, argv);
   }
 
   if (Array.isArray(webpackConfig)) {
     webpackConfig = webpackConfig.map(cfg => {
       if (typeof cfg === 'function') {
-        return cfg(env, argv)
+        return cfg(env, argv);
       }
 
-      return cfg
-    })
+      return cfg;
+    });
 
     if (typeof configIndex !== 'undefined' && webpackConfig.length > configIndex) {
-      webpackConfig = webpackConfig[configIndex]
+      webpackConfig = webpackConfig[configIndex];
     }
     else {
       webpackConfig = find(webpackConfig, function findFirstWithResolve(config) {
-        return !!config.resolve
-      })
+        return !!config.resolve;
+      });
     }
   }
 
   if (webpackConfig == null) {
-    webpackConfig = {}
+    webpackConfig = {};
 
-    console.warn('No webpack configuration with a "resolve" field found. Using empty object instead')
+    console.warn('No webpack configuration with a "resolve" field found. Using empty object instead');
   }
 
-  log('Using config: ', webpackConfig)
+  log('Using config: ', webpackConfig);
 
   // externals
   if (findExternal(source, webpackConfig.externals, path.dirname(file))) {
-    return { found: true, path: null }
+    return { found: true, path: null };
   }
 
   // otherwise, resolve "normally"
-  var resolveSync = getResolveSync(configPath, webpackConfig, cwd)
+  var resolveSync = getResolveSync(configPath, webpackConfig, cwd);
 
   try {
-    return { found: true, path: resolveSync(path.dirname(file), source) }
+    return { found: true, path: resolveSync(path.dirname(file), source) };
   } catch (err) {
     if (isCore(source)) {
-      return { found: true, path: null }
+      return { found: true, path: null };
     }
 
-    log('Error during module resolution:', err)
-    return { found: false }
+    log('Error during module resolution:', err);
+    return { found: false };
   }
-}
+};
 
-var MAX_CACHE = 10
-var _cache = []
+var MAX_CACHE = 10;
+var _cache = [];
 function getResolveSync(configPath, webpackConfig, cwd) {
-  var cacheKey = { configPath: configPath, webpackConfig: webpackConfig }
-  var cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey) })
+  var cacheKey = { configPath: configPath, webpackConfig: webpackConfig };
+  var cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
   if (!cached) {
     cached = {
       key: cacheKey,
       value: createResolveSync(configPath, webpackConfig, cwd),
-    }
+    };
     // put in front and pop last item
     if (_cache.unshift(cached) > MAX_CACHE) {
-      _cache.pop()
+      _cache.pop();
     }
   }
-  return cached.value
+  return cached.value;
 }
 
 function createResolveSync(configPath, webpackConfig, cwd) {
   var webpackRequire
-    , basedir = null
+    , basedir = null;
 
   if (typeof configPath === 'string') {
     // This can be changed via the settings passed in when defining the resolver
-    basedir = cwd || configPath
-    log(`Attempting to load webpack path from ${basedir}`)
+    basedir = cwd || configPath;
+    log(`Attempting to load webpack path from ${basedir}`);
   }
 
   try {
     // Attempt to resolve webpack from the given `basedir`
-    var webpackFilename = resolve.sync('webpack', { basedir, preserveSymlinks: false })
-    var webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false }
+    var webpackFilename = resolve.sync('webpack', { basedir, preserveSymlinks: false });
+    var webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false };
 
     webpackRequire = function (id) {
-      return require(resolve.sync(id, webpackResolveOpts))
-    }
+      return require(resolve.sync(id, webpackResolveOpts));
+    };
   } catch (e) {
     // Something has gone wrong (or we're in a test). Use our own bundled
     // enhanced-resolve.
-    log('Using bundled enhanced-resolve.')
-    webpackRequire = require
+    log('Using bundled enhanced-resolve.');
+    webpackRequire = require;
   }
 
-  var enhancedResolvePackage = webpackRequire('enhanced-resolve/package.json')
-  var enhancedResolveVersion = enhancedResolvePackage.version
-  log('enhanced-resolve version:', enhancedResolveVersion)
+  var enhancedResolvePackage = webpackRequire('enhanced-resolve/package.json');
+  var enhancedResolveVersion = enhancedResolvePackage.version;
+  log('enhanced-resolve version:', enhancedResolveVersion);
 
-  var resolveConfig = webpackConfig.resolve || {}
+  var resolveConfig = webpackConfig.resolve || {};
 
   if (semver.major(enhancedResolveVersion) >= 2) {
-    return createWebpack2ResolveSync(webpackRequire, resolveConfig)
+    return createWebpack2ResolveSync(webpackRequire, resolveConfig);
   }
 
-  return createWebpack1ResolveSync(webpackRequire, resolveConfig, webpackConfig.plugins)
+  return createWebpack1ResolveSync(webpackRequire, resolveConfig, webpackConfig.plugins);
 }
 
 function createWebpack2ResolveSync(webpackRequire, resolveConfig) {
-  var EnhancedResolve = webpackRequire('enhanced-resolve')
+  var EnhancedResolve = webpackRequire('enhanced-resolve');
 
-  return EnhancedResolve.create.sync(Object.assign({}, webpack2DefaultResolveConfig, resolveConfig))
+  return EnhancedResolve.create.sync(Object.assign({}, webpack2DefaultResolveConfig, resolveConfig));
 }
 
 /**
@@ -224,30 +224,30 @@ var webpack2DefaultResolveConfig = {
   extensions: ['.js', '.json'],
   aliasFields: ['browser'],
   mainFields: ['browser', 'module', 'main'],
-}
+};
 
 // adapted from tests &
 // https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L322
 function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
-  var Resolver = webpackRequire('enhanced-resolve/lib/Resolver')
-  var SyncNodeJsInputFileSystem = webpackRequire('enhanced-resolve/lib/SyncNodeJsInputFileSystem')
+  var Resolver = webpackRequire('enhanced-resolve/lib/Resolver');
+  var SyncNodeJsInputFileSystem = webpackRequire('enhanced-resolve/lib/SyncNodeJsInputFileSystem');
 
-  var ModuleAliasPlugin = webpackRequire('enhanced-resolve/lib/ModuleAliasPlugin')
+  var ModuleAliasPlugin = webpackRequire('enhanced-resolve/lib/ModuleAliasPlugin');
   var ModulesInDirectoriesPlugin =
-    webpackRequire('enhanced-resolve/lib/ModulesInDirectoriesPlugin')
-  var ModulesInRootPlugin = webpackRequire('enhanced-resolve/lib/ModulesInRootPlugin')
-  var ModuleAsFilePlugin = webpackRequire('enhanced-resolve/lib/ModuleAsFilePlugin')
-  var ModuleAsDirectoryPlugin = webpackRequire('enhanced-resolve/lib/ModuleAsDirectoryPlugin')
+    webpackRequire('enhanced-resolve/lib/ModulesInDirectoriesPlugin');
+  var ModulesInRootPlugin = webpackRequire('enhanced-resolve/lib/ModulesInRootPlugin');
+  var ModuleAsFilePlugin = webpackRequire('enhanced-resolve/lib/ModuleAsFilePlugin');
+  var ModuleAsDirectoryPlugin = webpackRequire('enhanced-resolve/lib/ModuleAsDirectoryPlugin');
   var DirectoryDescriptionFilePlugin =
-    webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFilePlugin')
+    webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFilePlugin');
   var DirectoryDefaultFilePlugin =
-    webpackRequire('enhanced-resolve/lib/DirectoryDefaultFilePlugin')
-  var FileAppendPlugin = webpackRequire('enhanced-resolve/lib/FileAppendPlugin')
-  var ResultSymlinkPlugin = webpackRequire('enhanced-resolve/lib/ResultSymlinkPlugin')
+    webpackRequire('enhanced-resolve/lib/DirectoryDefaultFilePlugin');
+  var FileAppendPlugin = webpackRequire('enhanced-resolve/lib/FileAppendPlugin');
+  var ResultSymlinkPlugin = webpackRequire('enhanced-resolve/lib/ResultSymlinkPlugin');
   var DirectoryDescriptionFileFieldAliasPlugin =
-    webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFileFieldAliasPlugin')
+    webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFileFieldAliasPlugin');
 
-  var resolver = new Resolver(new SyncNodeJsInputFileSystem())
+  var resolver = new Resolver(new SyncNodeJsInputFileSystem());
 
   resolver.apply(
     resolveConfig.packageAlias
@@ -269,10 +269,10 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
     new DirectoryDefaultFilePlugin(['index']),
     new FileAppendPlugin(resolveConfig.extensions || ['', '.webpack.js', '.web.js', '.js']),
     new ResultSymlinkPlugin()
-  )
+  );
 
 
-  var resolvePlugins = []
+  var resolvePlugins = [];
 
   // support webpack.ResolverPlugin
   if (plugins) {
@@ -282,16 +282,16 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
         plugin.constructor.name === 'ResolverPlugin' &&
         Array.isArray(plugin.plugins)
       ) {
-        resolvePlugins.push.apply(resolvePlugins, plugin.plugins)
+        resolvePlugins.push.apply(resolvePlugins, plugin.plugins);
       }
-    })
+    });
   }
 
-  resolver.apply.apply(resolver, resolvePlugins)
+  resolver.apply.apply(resolver, resolvePlugins);
 
   return function() {
-    return resolver.resolveSync.apply(resolver, arguments)
-  }
+    return resolver.resolveSync.apply(resolver, arguments);
+  };
 }
 
 /* eslint-disable */
@@ -311,38 +311,38 @@ function makeRootPlugin(ModulesInRootPlugin, name, root) {
 /* eslint-enable */
 
 function findExternal(source, externals, context) {
-  if (!externals) return false
+  if (!externals) return false;
 
   // string match
-  if (typeof externals === 'string') return (source === externals)
+  if (typeof externals === 'string') return (source === externals);
 
   // array: recurse
   if (externals instanceof Array) {
-    return externals.some(function (e) { return findExternal(source, e, context) })
+    return externals.some(function (e) { return findExternal(source, e, context); });
   }
 
   if (externals instanceof RegExp) {
-    return externals.test(source)
+    return externals.test(source);
   }
 
   if (typeof externals === 'function') {
-    var functionExternalFound = false
+    var functionExternalFound = false;
     externals.call(null, context, source, function(err, value) {
       if (err) {
-        functionExternalFound = false
+        functionExternalFound = false;
       } else {
-        functionExternalFound = findExternal(source, value, context)
+        functionExternalFound = findExternal(source, value, context);
       }
-    })
-    return functionExternalFound
+    });
+    return functionExternalFound;
   }
 
   // else, vanilla object
   for (var key in externals) {
-    if (!has(externals, key)) continue
-    if (source === key) return true
+    if (!has(externals, key)) continue;
+    if (source === key) return true;
   }
-  return false
+  return false;
 }
 
 /**
@@ -351,65 +351,65 @@ function findExternal(source, externals, context) {
  */
 var webpack1DefaultMains = [
   'webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main',
-]
+];
 
 function findConfigPath(configPath, packageDir) {
   var extensions = Object.keys(interpret.extensions).sort(function(a, b) {
-    return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length
+    return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length;
   })
-    , extension
+    , extension;
 
 
   if (configPath) {
     // extensions is not reused below, so safe to mutate it here.
-    extensions.reverse()
+    extensions.reverse();
     extensions.forEach(function (maybeExtension) {
       if (extension) {
-        return
+        return;
       }
 
       if (configPath.substr(-maybeExtension.length) === maybeExtension) {
-        extension = maybeExtension
+        extension = maybeExtension;
       }
-    })
+    });
 
     // see if we've got an absolute path
     if (!path.isAbsolute(configPath)) {
-      configPath = path.join(packageDir, configPath)
+      configPath = path.join(packageDir, configPath);
     }
   } else {
     extensions.forEach(function (maybeExtension) {
       if (extension) {
-        return
+        return;
       }
 
       var maybePath = path.resolve(
         path.join(packageDir, 'webpack.config' + maybeExtension)
-      )
+      );
       if (fs.existsSync(maybePath)) {
-        configPath = maybePath
-        extension = maybeExtension
+        configPath = maybePath;
+        extension = maybeExtension;
       }
-    })
+    });
   }
 
-  registerCompiler(interpret.extensions[extension])
-  return configPath
+  registerCompiler(interpret.extensions[extension]);
+  return configPath;
 }
 
 function registerCompiler(moduleDescriptor) {
   if(moduleDescriptor) {
     if(typeof moduleDescriptor === 'string') {
-      require(moduleDescriptor)
+      require(moduleDescriptor);
     } else if(!Array.isArray(moduleDescriptor)) {
-      moduleDescriptor.register(require(moduleDescriptor.module))
+      moduleDescriptor.register(require(moduleDescriptor.module));
     } else {
       for(var i = 0; i < moduleDescriptor.length; i++) {
         try {
-          registerCompiler(moduleDescriptor[i])
-          break
+          registerCompiler(moduleDescriptor[i]);
+          break;
         } catch(e) {
-          log('Failed to register compiler for moduleDescriptor[]:', i, moduleDescriptor)
+          log('Failed to register compiler for moduleDescriptor[]:', i, moduleDescriptor);
         }
       }
     }
diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js
index f8cd210e42..2cacda9984 100644
--- a/resolvers/webpack/test/alias.js
+++ b/resolvers/webpack/test/alias.js
@@ -1,22 +1,22 @@
 var chai = require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var webpack = require('../index')
+var webpack = require('../index');
 
-var file = path.join(__dirname, 'files', 'dummy.js')
+var file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("resolve.alias", function () {
-  var resolved
-  before(function () { resolved = webpack.resolve('foo', file) })
+  var resolved;
+  before(function () { resolved = webpack.resolve('foo', file); });
 
-  it("is found", function () { expect(resolved).to.have.property('found', true) })
+  it("is found", function () { expect(resolved).to.have.property('found', true); });
 
   it("is correct", function () {
     expect(resolved).to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'))
-  })
-})
+      .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
+  });
+});
 
 // todo: reimplement with resolver function / config
 // describe.skip("webpack alias spec", function () {
diff --git a/resolvers/webpack/test/config-extensions/webpack.config.babel.js b/resolvers/webpack/test/config-extensions/webpack.config.babel.js
index 41dc6c8e89..a63434f9bb 100644
--- a/resolvers/webpack/test/config-extensions/webpack.config.babel.js
+++ b/resolvers/webpack/test/config-extensions/webpack.config.babel.js
@@ -1,4 +1,4 @@
-import path from 'path'
+import path from 'path';
 
 export default {
   resolve: {
@@ -20,4 +20,4 @@ export default {
     { 'jquery': 'jQuery' },
     'bootstrap',
   ],
-}
+};
diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index add282b672..4edb969639 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -1,103 +1,103 @@
 var chai =  require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var resolve = require('../index').resolve
+var resolve = require('../index').resolve;
 
-var file = path.join(__dirname, 'files', 'src', 'jsx', 'dummy.js')
-var extensionFile = path.join(__dirname, 'config-extensions', 'src', 'dummy.js')
+var file = path.join(__dirname, 'files', 'src', 'jsx', 'dummy.js');
+var extensionFile = path.join(__dirname, 'config-extensions', 'src', 'dummy.js');
 
 var absoluteSettings = {
   config: path.join(__dirname, 'files', 'some', 'absolute.path.webpack.config.js'),
-}
+};
 
 describe("config", function () {
   it("finds webpack.config.js in parent directories", function () {
     expect(resolve('main-module', file)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
 
   it("finds absolute webpack.config.js files", function () {
     expect(resolve('foo', file, absoluteSettings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
+  });
 
   it("finds compile-to-js configs", function () {
     var settings = {
       config: path.join(__dirname, './files/webpack.config.babel.js'),
-    }
+    };
 
     expect(resolve('main-module', file, settings))
       .to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
 
   it("finds compile-to-js config in parent directories", function () {
     expect(resolve('main-module', extensionFile))
       .to.have.property('path')
-      .and.equal(path.join(__dirname, 'config-extensions', 'src', 'main-module.js'))
-  })
+      .and.equal(path.join(__dirname, 'config-extensions', 'src', 'main-module.js'));
+  });
 
   it("finds the first config with a resolve section", function () {
     var settings = {
       config: path.join(__dirname, './files/webpack.config.multiple.js'),
-    }
+    };
 
     expect(resolve('main-module', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
 
   it("finds the config at option config-index", function () {
     var settings = {
       config: path.join(__dirname, './files/webpack.config.multiple.js'),
       'config-index': 2,
-    }
+    };
 
     expect(resolve('foo', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
+  });
 
   it("doesn't swallow config load errors (#435)", function () {
     var settings = {
       config: path.join(__dirname, './files/webpack.config.garbage.js'),
-    }
-    expect(function () { resolve('foo', file, settings) }).to.throw(Error)
-  })
+    };
+    expect(function () { resolve('foo', file, settings); }).to.throw(Error);
+  });
 
   it("finds config object when config is an object", function () {
     var settings = {
       config: require(path.join(__dirname, 'files', 'some', 'absolute.path.webpack.config.js')),
-    }
+    };
     expect(resolve('foo', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
+  });
 
   it("finds config object when config uses a path relative to working dir", function () {
     var settings = {
       config: './test/files/some/absolute.path.webpack.config.js',
-    }
+    };
     expect(resolve('foo', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
+  });
 
   it("finds the first config with a resolve section when config is an array of config objects", function () {
     var settings = {
       config: require(path.join(__dirname, './files/webpack.config.multiple.js')),
-    }
+    };
 
     expect(resolve('main-module', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
 
   it("finds the config at option config-index when config is an array of config objects", function () {
     var settings = {
       config: require(path.join(__dirname, './files/webpack.config.multiple.js')),
       'config-index': 2,
-    }
+    };
 
     expect(resolve('foo', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
+  });
 
   it('finds the config at option env when config is a function', function() {
     var settings = {
@@ -105,11 +105,11 @@ describe("config", function () {
       env: {
         dummy: true,
       },
-    }
+    };
 
     expect(resolve('bar', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
+  });
 
   it('finds the config at option env when config is an array of functions', function() {
     var settings = {
@@ -117,11 +117,11 @@ describe("config", function () {
       env: {
         dummy: true,
       },
-    }
+    };
 
     expect(resolve('bar', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
+  });
 
   it('passes argv to config when it is a function', function() {
     var settings = {
@@ -129,18 +129,18 @@ describe("config", function () {
       argv: {
         mode: 'test',
       },
-    }
+    };
 
     expect(resolve('baz', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'))
-  })
+        .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'));
+  });
 
   it('passes a default empty argv object to config when it is a function', function() {
     var settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
       argv: undefined,
-    }
+    };
 
-    expect(function () { resolve('baz', file, settings) }).to.not.throw(Error)
-  })
-})
+    expect(function () { resolve('baz', file, settings); }).to.not.throw(Error);
+  });
+});
diff --git a/resolvers/webpack/test/custom-extensions/webpack.config.js b/resolvers/webpack/test/custom-extensions/webpack.config.js
index ee3444c00f..b8d39ed7c0 100644
--- a/resolvers/webpack/test/custom-extensions/webpack.config.js
+++ b/resolvers/webpack/test/custom-extensions/webpack.config.js
@@ -1,3 +1,3 @@
 module.exports = {
   resolve: { extensions: ['.js', '.coffee'] },
-}
+};
diff --git a/resolvers/webpack/test/example.js b/resolvers/webpack/test/example.js
index 375f6b5a1e..c99ddffa4d 100644
--- a/resolvers/webpack/test/example.js
+++ b/resolvers/webpack/test/example.js
@@ -1,9 +1,9 @@
-var path = require('path')
+var path = require('path');
 
-var resolve = require('../index').resolve
+var resolve = require('../index').resolve;
 
-var file = path.join(__dirname, 'files', 'src', 'dummy.js')
+var file = path.join(__dirname, 'files', 'src', 'dummy.js');
 
-var webpackDir = path.join(__dirname, "different-package-location")
+var webpackDir = path.join(__dirname, "different-package-location");
 
-console.log(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir}))
+console.log(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir}));
diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js
index 94e9bd3942..a62cb3284c 100644
--- a/resolvers/webpack/test/extensions.js
+++ b/resolvers/webpack/test/extensions.js
@@ -1,32 +1,32 @@
 var chai =  require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var resolve = require('../index').resolve
+var resolve = require('../index').resolve;
 
 
 var file = path.join(__dirname, 'files', 'dummy.js')
-  , extensions = path.join(__dirname, 'custom-extensions', 'dummy.js')
+  , extensions = path.join(__dirname, 'custom-extensions', 'dummy.js');
 
 describe("extensions", function () {
   it("respects the defaults", function () {
     expect(resolve('./foo', file)).to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'foo.web.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'foo.web.js'));
+  });
 
   describe("resolve.extensions set", function () {
     it("works", function () {
       expect(resolve('./foo', extensions)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'custom-extensions', 'foo.js'))
-    })
+        .and.equal(path.join(__dirname, 'custom-extensions', 'foo.js'));
+    });
 
     it("replaces defaults", function () {
-      expect(resolve('./baz', extensions)).to.have.property('found', false)
-    })
+      expect(resolve('./baz', extensions)).to.have.property('found', false);
+    });
 
     it("finds .coffee", function () {
       expect(resolve('./bar', extensions)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'custom-extensions', 'bar.coffee'))
-    })
-  })
-})
+        .and.equal(path.join(__dirname, 'custom-extensions', 'bar.coffee'));
+    });
+  });
+});
diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js
index e2e61fbe19..7840a85178 100644
--- a/resolvers/webpack/test/externals.js
+++ b/resolvers/webpack/test/externals.js
@@ -1,33 +1,33 @@
 var chai = require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var webpack = require('../index')
+var webpack = require('../index');
 
-var file = path.join(__dirname, 'files', 'dummy.js')
+var file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("externals", function () {
   it("works on just a string", function () {
-    var resolved = webpack.resolve('bootstrap', file)
-    expect(resolved).to.have.property('found', true)
-    expect(resolved).to.have.property('path', null)
-  })
+    var resolved = webpack.resolve('bootstrap', file);
+    expect(resolved).to.have.property('found', true);
+    expect(resolved).to.have.property('path', null);
+  });
 
   it("works on object-map", function () {
-    var resolved = webpack.resolve('jquery', file)
-    expect(resolved).to.have.property('found', true)
-    expect(resolved).to.have.property('path', null)
-  })
+    var resolved = webpack.resolve('jquery', file);
+    expect(resolved).to.have.property('found', true);
+    expect(resolved).to.have.property('path', null);
+  });
 
   it("works on a function", function () {
-    var resolved = webpack.resolve('underscore', file)
-    expect(resolved).to.have.property('found', true)
-    expect(resolved).to.have.property('path', null)
-  })
+    var resolved = webpack.resolve('underscore', file);
+    expect(resolved).to.have.property('found', true);
+    expect(resolved).to.have.property('path', null);
+  });
 
   it("returns null for core modules", function () {
-    var resolved = webpack.resolve('fs', file)
-    expect(resolved).to.have.property('found', true)
-    expect(resolved).to.have.property('path', null)
-  })
-})
+    var resolved = webpack.resolve('fs', file);
+    expect(resolved).to.have.property('found', true);
+    expect(resolved).to.have.property('path', null);
+  });
+});
diff --git a/resolvers/webpack/test/fallback.js b/resolvers/webpack/test/fallback.js
index ad4b2b4c1d..76976573fd 100644
--- a/resolvers/webpack/test/fallback.js
+++ b/resolvers/webpack/test/fallback.js
@@ -1,28 +1,28 @@
 var chai =  require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var resolve = require('../index').resolve
+var resolve = require('../index').resolve;
 
 
-var file = path.join(__dirname, 'files', 'src', 'dummy.js')
+var file = path.join(__dirname, 'files', 'src', 'dummy.js');
 
 describe("fallback", function () {
   it("works", function () {
     expect(resolve('fb-module', file)).property('path')
-      .to.equal(path.join(__dirname, 'files', 'fallback', 'fb-module.js'))
-  })
+      .to.equal(path.join(__dirname, 'files', 'fallback', 'fb-module.js'));
+  });
   it("really works", function () {
     expect(resolve('jsx/some-fb-file', file)).property('path')
-      .to.equal(path.join(__dirname, 'files', 'fallback', 'jsx', 'some-fb-file.js'))
-  })
+      .to.equal(path.join(__dirname, 'files', 'fallback', 'jsx', 'some-fb-file.js'));
+  });
   it("prefer root", function () {
     expect(resolve('jsx/some-file', file)).property('path')
-      .to.equal(path.join(__dirname, 'files', 'src', 'jsx', 'some-file.js'))
-  })
+      .to.equal(path.join(__dirname, 'files', 'src', 'jsx', 'some-file.js'));
+  });
   it("supports definition as an array", function () {
     expect(resolve('fb-module', file, { config: "webpack.array-root.config.js" }))
       .property('path')
-      .to.equal(path.join(__dirname, 'files', 'fallback', 'fb-module.js'))
-  })
-})
+      .to.equal(path.join(__dirname, 'files', 'fallback', 'fb-module.js'));
+  });
+});
diff --git a/resolvers/webpack/test/loaders.js b/resolvers/webpack/test/loaders.js
index 1d588c77cd..4f7c48ccb5 100644
--- a/resolvers/webpack/test/loaders.js
+++ b/resolvers/webpack/test/loaders.js
@@ -1,35 +1,35 @@
 var chai =  require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var resolve = require('../index').resolve
+var resolve = require('../index').resolve;
 
 
-var file = path.join(__dirname, 'files', 'dummy.js')
+var file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("inline loader syntax", function () {
 
   it("strips bang-loaders", function () {
     expect(resolve('css-loader!./src/main-module', file)).to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
 
   it("strips loader query string", function () {
     expect(resolve('some-loader?param=value!./src/main-module', file)).to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
 
   it("strips resource query string", function () {
     expect(resolve('./src/main-module?otherParam=otherValue', file))
       .to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
 
   it("strips everything", function () {
     expect(resolve('some-loader?param=value!./src/main-module?otherParam=otherValue', file))
       .to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
 
-})
+});
 
diff --git a/resolvers/webpack/test/modules.js b/resolvers/webpack/test/modules.js
index 753ceffc00..ea7d35d1e0 100644
--- a/resolvers/webpack/test/modules.js
+++ b/resolvers/webpack/test/modules.js
@@ -1,21 +1,21 @@
 var chai =  require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var resolve = require('../index').resolve
+var resolve = require('../index').resolve;
 
-var file = path.join(__dirname, 'files', 'dummy.js')
+var file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("resolve.moduleDirectories", function () {
 
   it("finds a node module", function () {
     expect(resolve('some-module', file)).to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'node_modules', 'some-module', 'index.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'node_modules', 'some-module', 'index.js'));
+  });
 
   it("finds a bower module", function () {
     expect(resolve('typeahead.js', file)).to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
+  });
 
-})
+});
diff --git a/resolvers/webpack/test/package-mains/webpack.alt.config.js b/resolvers/webpack/test/package-mains/webpack.alt.config.js
index c31e49a05b..2bb1fc6717 100644
--- a/resolvers/webpack/test/package-mains/webpack.alt.config.js
+++ b/resolvers/webpack/test/package-mains/webpack.alt.config.js
@@ -1,3 +1,3 @@
 exports.resolve = {
   packageMains: ["main"], // override
-}
+};
diff --git a/resolvers/webpack/test/packageMains.js b/resolvers/webpack/test/packageMains.js
index 63f5b68931..50db032d80 100644
--- a/resolvers/webpack/test/packageMains.js
+++ b/resolvers/webpack/test/packageMains.js
@@ -1,47 +1,47 @@
 var chai = require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var webpack = require('../')
+var webpack = require('../');
 
-var file = path.join(__dirname, 'package-mains', 'dummy.js')
+var file = path.join(__dirname, 'package-mains', 'dummy.js');
 
 
 describe("packageMains", function () {
 
   it("captures module", function () {
     expect(webpack.resolve('./module', file)).property('path')
-      .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'))
-  })
+      .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'));
+  });
 
   it("captures jsnext", function () {
     expect(webpack.resolve('./jsnext', file)).property('path')
-      .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'))
-  })
+      .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
+  });
 
   it("captures webpack", function () {
     expect(webpack.resolve('./webpack', file)).property('path')
-      .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'webpack.js'))
-  })
+      .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'webpack.js'));
+  });
 
   it("captures jam (array path)", function () {
     expect(webpack.resolve('./jam', file)).property('path')
-      .to.equal(path.join(__dirname, 'package-mains', 'jam', 'jam.js'))
-  })
+      .to.equal(path.join(__dirname, 'package-mains', 'jam', 'jam.js'));
+  });
 
   it("uses configured packageMains, if provided", function () {
     expect(webpack.resolve('./webpack', file, { config: 'webpack.alt.config.js' })).property('path')
-      .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'index.js'))
-  })
+      .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'index.js'));
+  });
 
   it("always defers to module, regardless of config", function () {
     expect(webpack.resolve('./module', file, { config: 'webpack.alt.config.js' })).property('path')
-      .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'))
-  })
+      .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'));
+  });
 
   it("always defers to jsnext:main, regardless of config", function () {
     expect(webpack.resolve('./jsnext', file, { config: 'webpack.alt.config.js' })).property('path')
-      .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'))
-  })
+      .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
+  });
 
-})
+});
diff --git a/resolvers/webpack/test/plugins.js b/resolvers/webpack/test/plugins.js
index f37b945183..3f11e92efe 100644
--- a/resolvers/webpack/test/plugins.js
+++ b/resolvers/webpack/test/plugins.js
@@ -1,29 +1,29 @@
 var chai = require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var webpack = require('../index')
+var webpack = require('../index');
 
-var file = path.join(__dirname, 'files', 'dummy.js')
+var file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("plugins", function () {
-  var resolved, aliasResolved
+  var resolved, aliasResolved;
 
   before(function () {
-    resolved = webpack.resolve('./some/bar', file)
-    aliasResolved = webpack.resolve('some-alias/bar', file)
-  })
+    resolved = webpack.resolve('./some/bar', file);
+    aliasResolved = webpack.resolve('some-alias/bar', file);
+  });
 
   it("work", function () {
-    expect(resolved).to.have.property('found', true)
-  })
+    expect(resolved).to.have.property('found', true);
+  });
 
   it("is correct", function () {
     expect(resolved).to.have.property('path')
-      .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'))
-  })
+      .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'));
+  });
 
   it("work with alias", function () {
-    expect(aliasResolved).to.have.property('found', true)
-  })
-})
+    expect(aliasResolved).to.have.property('found', true);
+  });
+});
diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js
index 4365720091..48d918498a 100644
--- a/resolvers/webpack/test/root.js
+++ b/resolvers/webpack/test/root.js
@@ -1,45 +1,45 @@
 var chai =  require('chai')
   , expect = chai.expect
-  , path = require('path')
+  , path = require('path');
 
-var resolve = require('../index').resolve
+var resolve = require('../index').resolve;
 
 
-var file = path.join(__dirname, 'files', 'src', 'dummy.js')
-var webpackDir = path.join(__dirname, "different-package-location")
+var file = path.join(__dirname, 'files', 'src', 'dummy.js');
+var webpackDir = path.join(__dirname, "different-package-location");
 
 describe("root", function () {
   it("works", function () {
     expect(resolve('main-module', file)).property('path')
-      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
-  })
+      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+  });
   it("really works", function () {
     expect(resolve('jsx/some-file', file)).property('path')
-      .to.equal(path.join(__dirname, 'files', 'src', 'jsx', 'some-file.js'))
-  })
+      .to.equal(path.join(__dirname, 'files', 'src', 'jsx', 'some-file.js'));
+  });
   it("supports definition as an array", function () {
     expect(resolve('main-module', file, { config: "webpack.array-root.config.js" }))
       .property('path')
-      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
+      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
     expect(resolve('typeahead', file, { config: "webpack.array-root.config.js" }))
       .property('path')
-      .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'))
-  })
+      .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
+  });
   it("supports definition as a function", function () {
     expect(resolve('main-module', file, { config: "webpack.function.config.js" }))
       .property('path')
-      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
+      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
     expect(resolve('typeahead', file, { config: "webpack.function.config.js" }))
       .property('path')
-      .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'))
-  })
+      .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
+  });
   it("supports passing a different directory to load webpack from", function () {
     // Webpack should still be able to resolve the config here
     expect(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir}))
       .property('path')
-      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'))
+      .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
     expect(resolve('typeahead', file, { config: "webpack.config.js", cwd: webpackDir}))
       .property('path')
-      .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'))
-  })
-})
+      .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
+  });
+});
diff --git a/scripts/copyMetafiles.js b/scripts/copyMetafiles.js
index 441e421e8d..a58c8e10ac 100644
--- a/scripts/copyMetafiles.js
+++ b/scripts/copyMetafiles.js
@@ -1,22 +1,22 @@
-import path from 'path'
-import copyFileSync from 'fs-copy-file-sync'
-import resolverDirectories from './resolverDirectories'
+import path from 'path';
+import copyFileSync from 'fs-copy-file-sync';
+import resolverDirectories from './resolverDirectories';
 
 let files = [
     'LICENSE',
     '.npmrc',
-]
+];
 
 let directories = [
     'memo-parser',
     ...resolverDirectories,
     'utils',
-]
+];
 
 for (let directory of directories) {
     for (let file of files) {
-        let destination = path.join(directory, file)
-        copyFileSync(file, destination)
-        console.log(`${file} -> ${destination}`)
+        let destination = path.join(directory, file);
+        copyFileSync(file, destination);
+        console.log(`${file} -> ${destination}`);
     }
 }
diff --git a/scripts/resolverDirectories.js b/scripts/resolverDirectories.js
index eea0620d36..f0c03a3ccf 100644
--- a/scripts/resolverDirectories.js
+++ b/scripts/resolverDirectories.js
@@ -1,3 +1,3 @@
-import glob from 'glob'
+import glob from 'glob';
 
-export default glob.sync('./resolvers/*/')
+export default glob.sync('./resolvers/*/');
diff --git a/scripts/testAll.js b/scripts/testAll.js
index 358ef3e89e..843ffa5778 100644
--- a/scripts/testAll.js
+++ b/scripts/testAll.js
@@ -1,20 +1,20 @@
-import { spawnSync } from 'child_process'
-import npmWhich from 'npm-which'
-import resolverDirectories from './resolverDirectories'
+import { spawnSync } from 'child_process';
+import npmWhich from 'npm-which';
+import resolverDirectories from './resolverDirectories';
 
-let npmPath = npmWhich(__dirname).sync('npm')
+let npmPath = npmWhich(__dirname).sync('npm');
 let spawnOptions = {
     stdio: 'inherit',
-}
+};
 
 spawnSync(
     npmPath,
     ['test'],
-    Object.assign({ cwd: __dirname }, spawnOptions))
+    Object.assign({ cwd: __dirname }, spawnOptions));
 
 for (let resolverDir of resolverDirectories) {
     spawnSync(
         npmPath,
         ['test'],
-        Object.assign({ cwd: resolverDir }, spawnOptions))
+        Object.assign({ cwd: resolverDir }, spawnOptions));
 }
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 837546aeb4..1d35ded187 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -1,58 +1,58 @@
-import fs from 'fs'
+import fs from 'fs';
 
-import doctrine from 'doctrine'
+import doctrine from 'doctrine';
 
-import debug from 'debug'
+import debug from 'debug';
 
-import { SourceCode } from 'eslint'
+import { SourceCode } from 'eslint';
 
-import parse from 'eslint-module-utils/parse'
-import resolve from 'eslint-module-utils/resolve'
-import isIgnored, { hasValidExtension } from 'eslint-module-utils/ignore'
+import parse from 'eslint-module-utils/parse';
+import resolve from 'eslint-module-utils/resolve';
+import isIgnored, { hasValidExtension } from 'eslint-module-utils/ignore';
 
-import { hashObject } from 'eslint-module-utils/hash'
-import * as unambiguous from 'eslint-module-utils/unambiguous'
+import { hashObject } from 'eslint-module-utils/hash';
+import * as unambiguous from 'eslint-module-utils/unambiguous';
 
-import { tsConfigLoader } from 'tsconfig-paths/lib/tsconfig-loader'
+import { tsConfigLoader } from 'tsconfig-paths/lib/tsconfig-loader';
 
-import includes from 'array-includes'
+import includes from 'array-includes';
 
-let parseConfigFileTextToJson
+let parseConfigFileTextToJson;
 
-const log = debug('eslint-plugin-import:ExportMap')
+const log = debug('eslint-plugin-import:ExportMap');
 
-const exportCache = new Map()
+const exportCache = new Map();
 
 export default class ExportMap {
   constructor(path) {
-    this.path = path
-    this.namespace = new Map()
+    this.path = path;
+    this.namespace = new Map();
     // todo: restructure to key on path, value is resolver + map of names
-    this.reexports = new Map()
+    this.reexports = new Map();
     /**
      * star-exports
      * @type {Set} of () => ExportMap
      */
-    this.dependencies = new Set()
+    this.dependencies = new Set();
     /**
      * dependencies of this module that are not explicitly re-exported
      * @type {Map} from path = () => ExportMap
      */
-    this.imports = new Map()
-    this.errors = []
+    this.imports = new Map();
+    this.errors = [];
   }
 
-  get hasDefault() { return this.get('default') != null } // stronger than this.has
+  get hasDefault() { return this.get('default') != null; } // stronger than this.has
 
   get size() {
-    let size = this.namespace.size + this.reexports.size
+    let size = this.namespace.size + this.reexports.size;
     this.dependencies.forEach(dep => {
-      const d = dep()
+      const d = dep();
       // CJS / ignored dependencies won't exist (#717)
-      if (d == null) return
-      size += d.size
-    })
-    return size
+      if (d == null) return;
+      size += d.size;
+    });
+    return size;
   }
 
   /**
@@ -63,22 +63,22 @@ export default class ExportMap {
    * @return {Boolean} true if `name` is exported by this module.
    */
   has(name) {
-    if (this.namespace.has(name)) return true
-    if (this.reexports.has(name)) return true
+    if (this.namespace.has(name)) return true;
+    if (this.reexports.has(name)) return true;
 
     // default exports must be explicitly re-exported (#328)
     if (name !== 'default') {
       for (let dep of this.dependencies) {
-        let innerMap = dep()
+        let innerMap = dep();
 
         // todo: report as unresolved?
-        if (!innerMap) continue
+        if (!innerMap) continue;
 
-        if (innerMap.has(name)) return true
+        if (innerMap.has(name)) return true;
       }
     }
 
-    return false
+    return false;
   }
 
   /**
@@ -87,101 +87,101 @@ export default class ExportMap {
    * @return {Boolean}      [description]
    */
   hasDeep(name) {
-    if (this.namespace.has(name)) return { found: true, path: [this] }
+    if (this.namespace.has(name)) return { found: true, path: [this] };
 
     if (this.reexports.has(name)) {
       const reexports = this.reexports.get(name)
-          , imported = reexports.getImport()
+          , imported = reexports.getImport();
 
       // if import is ignored, return explicit 'null'
-      if (imported == null) return { found: true, path: [this] }
+      if (imported == null) return { found: true, path: [this] };
 
       // safeguard against cycles, only if name matches
       if (imported.path === this.path && reexports.local === name) {
-        return { found: false, path: [this] }
+        return { found: false, path: [this] };
       }
 
-      const deep = imported.hasDeep(reexports.local)
-      deep.path.unshift(this)
+      const deep = imported.hasDeep(reexports.local);
+      deep.path.unshift(this);
 
-      return deep
+      return deep;
     }
 
 
     // default exports must be explicitly re-exported (#328)
     if (name !== 'default') {
       for (let dep of this.dependencies) {
-        let innerMap = dep()
-        if (innerMap == null) return { found: true, path: [this] }
+        let innerMap = dep();
+        if (innerMap == null) return { found: true, path: [this] };
         // todo: report as unresolved?
-        if (!innerMap) continue
+        if (!innerMap) continue;
 
         // safeguard against cycles
-        if (innerMap.path === this.path) continue
+        if (innerMap.path === this.path) continue;
 
-        let innerValue = innerMap.hasDeep(name)
+        let innerValue = innerMap.hasDeep(name);
         if (innerValue.found) {
-          innerValue.path.unshift(this)
-          return innerValue
+          innerValue.path.unshift(this);
+          return innerValue;
         }
       }
     }
 
-    return { found: false, path: [this] }
+    return { found: false, path: [this] };
   }
 
   get(name) {
-    if (this.namespace.has(name)) return this.namespace.get(name)
+    if (this.namespace.has(name)) return this.namespace.get(name);
 
     if (this.reexports.has(name)) {
       const reexports = this.reexports.get(name)
-          , imported = reexports.getImport()
+          , imported = reexports.getImport();
 
       // if import is ignored, return explicit 'null'
-      if (imported == null) return null
+      if (imported == null) return null;
 
       // safeguard against cycles, only if name matches
-      if (imported.path === this.path && reexports.local === name) return undefined
+      if (imported.path === this.path && reexports.local === name) return undefined;
 
-      return imported.get(reexports.local)
+      return imported.get(reexports.local);
     }
 
     // default exports must be explicitly re-exported (#328)
     if (name !== 'default') {
       for (let dep of this.dependencies) {
-        let innerMap = dep()
+        let innerMap = dep();
         // todo: report as unresolved?
-        if (!innerMap) continue
+        if (!innerMap) continue;
 
         // safeguard against cycles
-        if (innerMap.path === this.path) continue
+        if (innerMap.path === this.path) continue;
 
-        let innerValue = innerMap.get(name)
-        if (innerValue !== undefined) return innerValue
+        let innerValue = innerMap.get(name);
+        if (innerValue !== undefined) return innerValue;
       }
     }
 
-    return undefined
+    return undefined;
   }
 
   forEach(callback, thisArg) {
     this.namespace.forEach((v, n) =>
-      callback.call(thisArg, v, n, this))
+      callback.call(thisArg, v, n, this));
 
     this.reexports.forEach((reexports, name) => {
-      const reexported = reexports.getImport()
+      const reexported = reexports.getImport();
       // can't look up meta for ignored re-exports (#348)
-      callback.call(thisArg, reexported && reexported.get(reexports.local), name, this)
-    })
+      callback.call(thisArg, reexported && reexported.get(reexports.local), name, this);
+    });
 
     this.dependencies.forEach(dep => {
-      const d = dep()
+      const d = dep();
       // CJS / ignored dependencies won't exist (#717)
-      if (d == null) return
+      if (d == null) return;
 
       d.forEach((v, n) =>
-        n !== 'default' && callback.call(thisArg, v, n, this))
-    })
+        n !== 'default' && callback.call(thisArg, v, n, this));
+    });
   }
 
   // todo: keys, values, entries?
@@ -193,7 +193,7 @@ export default class ExportMap {
                   `${this.errors
                         .map(e => `${e.message} (${e.lineNumber}:${e.column})`)
                         .join(', ')}`,
-    })
+    });
   }
 }
 
@@ -201,43 +201,43 @@ export default class ExportMap {
  * parse docs from the first node that has leading comments
  */
 function captureDoc(source, docStyleParsers, ...nodes) {
-  const metadata = {}
+  const metadata = {};
 
   // 'some' short-circuits on first 'true'
   nodes.some(n => {
     try {
 
-      let leadingComments
+      let leadingComments;
 
       // n.leadingComments is legacy `attachComments` behavior
       if ('leadingComments' in n) {
-        leadingComments = n.leadingComments
+        leadingComments = n.leadingComments;
       } else if (n.range) {
-        leadingComments = source.getCommentsBefore(n)
+        leadingComments = source.getCommentsBefore(n);
       }
 
-      if (!leadingComments || leadingComments.length === 0) return false
+      if (!leadingComments || leadingComments.length === 0) return false;
 
       for (let name in docStyleParsers) {
-        const doc = docStyleParsers[name](leadingComments)
+        const doc = docStyleParsers[name](leadingComments);
         if (doc) {
-          metadata.doc = doc
+          metadata.doc = doc;
         }
       }
 
-      return true
+      return true;
     } catch (err) {
-      return false
+      return false;
     }
-  })
+  });
 
-  return metadata
+  return metadata;
 }
 
 const availableDocStyleParsers = {
   jsdoc: captureJsDoc,
   tomdoc: captureTomDoc,
-}
+};
 
 /**
  * parse JSDoc from leading comments
@@ -245,20 +245,20 @@ const availableDocStyleParsers = {
  * @return {{doc: object}}
  */
 function captureJsDoc(comments) {
-  let doc
+  let doc;
 
   // capture XSDoc
   comments.forEach(comment => {
     // skip non-block comments
-    if (comment.type !== 'Block') return
+    if (comment.type !== 'Block') return;
     try {
-      doc = doctrine.parse(comment.value, { unwrap: true })
+      doc = doctrine.parse(comment.value, { unwrap: true });
     } catch (err) {
       /* don't care, for now? maybe add to `errors?` */
     }
-  })
+  });
 
-  return doc
+  return doc;
 }
 
 /**
@@ -266,15 +266,15 @@ function captureJsDoc(comments) {
   */
 function captureTomDoc(comments) {
   // collect lines up to first paragraph break
-  const lines = []
+  const lines = [];
   for (let i = 0; i < comments.length; i++) {
-    const comment = comments[i]
-    if (comment.value.match(/^\s*$/)) break
-    lines.push(comment.value.trim())
+    const comment = comments[i];
+    if (comment.value.match(/^\s*$/)) break;
+    lines.push(comment.value.trim());
   }
 
   // return doctrine-like object
-  const statusMatch = lines.join(' ').match(/^(Public|Internal|Deprecated):\s*(.+)/)
+  const statusMatch = lines.join(' ').match(/^(Public|Internal|Deprecated):\s*(.+)/);
   if (statusMatch) {
     return {
       description: statusMatch[2],
@@ -282,162 +282,162 @@ function captureTomDoc(comments) {
         title: statusMatch[1].toLowerCase(),
         description: statusMatch[2],
       }],
-    }
+    };
   }
 }
 
 ExportMap.get = function (source, context) {
-  const path = resolve(source, context)
-  if (path == null) return null
+  const path = resolve(source, context);
+  if (path == null) return null;
 
-  return ExportMap.for(childContext(path, context))
-}
+  return ExportMap.for(childContext(path, context));
+};
 
 ExportMap.for = function (context) {
-  const { path } = context
+  const { path } = context;
 
-  const cacheKey = hashObject(context).digest('hex')
-  let exportMap = exportCache.get(cacheKey)
+  const cacheKey = hashObject(context).digest('hex');
+  let exportMap = exportCache.get(cacheKey);
 
   // return cached ignore
-  if (exportMap === null) return null
+  if (exportMap === null) return null;
 
-  const stats = fs.statSync(path)
+  const stats = fs.statSync(path);
   if (exportMap != null) {
     // date equality check
     if (exportMap.mtime - stats.mtime === 0) {
-      return exportMap
+      return exportMap;
     }
     // future: check content equality?
   }
 
   // check valid extensions first
   if (!hasValidExtension(path, context)) {
-    exportCache.set(cacheKey, null)
-    return null
+    exportCache.set(cacheKey, null);
+    return null;
   }
 
   // check for and cache ignore
   if (isIgnored(path, context)) {
-    log('ignored path due to ignore settings:', path)
-    exportCache.set(cacheKey, null)
-    return null
+    log('ignored path due to ignore settings:', path);
+    exportCache.set(cacheKey, null);
+    return null;
   }
 
-  const content = fs.readFileSync(path, { encoding: 'utf8' })
+  const content = fs.readFileSync(path, { encoding: 'utf8' });
 
   // check for and cache unambiguous modules
   if (!unambiguous.test(content)) {
-    log('ignored path due to unambiguous regex:', path)
-    exportCache.set(cacheKey, null)
-    return null
+    log('ignored path due to unambiguous regex:', path);
+    exportCache.set(cacheKey, null);
+    return null;
   }
 
-  log('cache miss', cacheKey, 'for path', path)
-  exportMap = ExportMap.parse(path, content, context)
+  log('cache miss', cacheKey, 'for path', path);
+  exportMap = ExportMap.parse(path, content, context);
 
   // ambiguous modules return null
-  if (exportMap == null) return null
+  if (exportMap == null) return null;
 
-  exportMap.mtime = stats.mtime
+  exportMap.mtime = stats.mtime;
 
-  exportCache.set(cacheKey, exportMap)
-  return exportMap
-}
+  exportCache.set(cacheKey, exportMap);
+  return exportMap;
+};
 
 
 ExportMap.parse = function (path, content, context) {
-  var m = new ExportMap(path)
+  var m = new ExportMap(path);
 
   try {
-    var ast = parse(path, content, context)
+    var ast = parse(path, content, context);
   } catch (err) {
-    log('parse error:', path, err)
-    m.errors.push(err)
-    return m // can't continue
+    log('parse error:', path, err);
+    m.errors.push(err);
+    return m; // can't continue
   }
 
-  if (!unambiguous.isModule(ast)) return null
+  if (!unambiguous.isModule(ast)) return null;
 
-  const docstyle = (context.settings && context.settings['import/docstyle']) || ['jsdoc']
-  const docStyleParsers = {}
+  const docstyle = (context.settings && context.settings['import/docstyle']) || ['jsdoc'];
+  const docStyleParsers = {};
   docstyle.forEach(style => {
-    docStyleParsers[style] = availableDocStyleParsers[style]
-  })
+    docStyleParsers[style] = availableDocStyleParsers[style];
+  });
 
   // attempt to collect module doc
   if (ast.comments) {
     ast.comments.some(c => {
-      if (c.type !== 'Block') return false
+      if (c.type !== 'Block') return false;
       try {
-        const doc = doctrine.parse(c.value, { unwrap: true })
+        const doc = doctrine.parse(c.value, { unwrap: true });
         if (doc.tags.some(t => t.title === 'module')) {
-          m.doc = doc
-          return true
+          m.doc = doc;
+          return true;
         }
       } catch (err) { /* ignore */ }
-      return false
-    })
+      return false;
+    });
   }
 
-  const namespaces = new Map()
+  const namespaces = new Map();
 
   function remotePath(value) {
-    return resolve.relative(value, path, context.settings)
+    return resolve.relative(value, path, context.settings);
   }
 
   function resolveImport(value) {
-    const rp = remotePath(value)
-    if (rp == null) return null
-    return ExportMap.for(childContext(rp, context))
+    const rp = remotePath(value);
+    if (rp == null) return null;
+    return ExportMap.for(childContext(rp, context));
   }
 
   function getNamespace(identifier) {
-    if (!namespaces.has(identifier.name)) return
+    if (!namespaces.has(identifier.name)) return;
 
     return function () {
-      return resolveImport(namespaces.get(identifier.name))
-    }
+      return resolveImport(namespaces.get(identifier.name));
+    };
   }
 
   function addNamespace(object, identifier) {
-    const nsfn = getNamespace(identifier)
+    const nsfn = getNamespace(identifier);
     if (nsfn) {
-      Object.defineProperty(object, 'namespace', { get: nsfn })
+      Object.defineProperty(object, 'namespace', { get: nsfn });
     }
 
-    return object
+    return object;
   }
 
   function captureDependency(declaration) {
-    if (declaration.source == null) return null
-    if (declaration.importKind === 'type') return null // skip Flow type imports
-    const importedSpecifiers = new Set()
-    const supportedTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier'])
-    let hasImportedType = false
+    if (declaration.source == null) return null;
+    if (declaration.importKind === 'type') return null; // skip Flow type imports
+    const importedSpecifiers = new Set();
+    const supportedTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
+    let hasImportedType = false;
     if (declaration.specifiers) {
       declaration.specifiers.forEach(specifier => {
-        const isType = specifier.importKind === 'type'
-        hasImportedType = hasImportedType || isType
+        const isType = specifier.importKind === 'type';
+        hasImportedType = hasImportedType || isType;
 
         if (supportedTypes.has(specifier.type) && !isType) {
-          importedSpecifiers.add(specifier.type)
+          importedSpecifiers.add(specifier.type);
         }
         if (specifier.type === 'ImportSpecifier' && !isType) {
-          importedSpecifiers.add(specifier.imported.name)
+          importedSpecifiers.add(specifier.imported.name);
         }
-      })
+      });
     }
 
     // only Flow types were imported
-    if (hasImportedType && importedSpecifiers.size === 0) return null
+    if (hasImportedType && importedSpecifiers.size === 0) return null;
 
-    const p = remotePath(declaration.source.value)
-    if (p == null) return null
-    const existing = m.imports.get(p)
-    if (existing != null) return existing.getter
+    const p = remotePath(declaration.source.value);
+    if (p == null) return null;
+    const existing = m.imports.get(p);
+    if (existing != null) return existing.getter;
 
-    const getter = thunkFor(p, context)
+    const getter = thunkFor(p, context);
     m.imports.set(p, {
       getter,
       source: {  // capturing actual node reference holds full AST in memory!
@@ -445,56 +445,56 @@ ExportMap.parse = function (path, content, context) {
         loc: declaration.source.loc,
       },
       importedSpecifiers,
-    })
-    return getter
+    });
+    return getter;
   }
 
-  const source = makeSourceCode(content, ast)
+  const source = makeSourceCode(content, ast);
 
   function isEsModuleInterop() {
     const tsConfigInfo = tsConfigLoader({
       cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
       getEnv: (key) => process.env[key],
-    })
+    });
     try {
       if (tsConfigInfo.tsConfigPath !== undefined) {
-        const jsonText = fs.readFileSync(tsConfigInfo.tsConfigPath).toString()
+        const jsonText = fs.readFileSync(tsConfigInfo.tsConfigPath).toString();
         if (!parseConfigFileTextToJson) {
           // this is because projects not using TypeScript won't have typescript installed
-          ({parseConfigFileTextToJson} = require('typescript'))
+          ({parseConfigFileTextToJson} = require('typescript'));
         }
-        const tsConfig = parseConfigFileTextToJson(tsConfigInfo.tsConfigPath, jsonText).config
-        return tsConfig.compilerOptions.esModuleInterop
+        const tsConfig = parseConfigFileTextToJson(tsConfigInfo.tsConfigPath, jsonText).config;
+        return tsConfig.compilerOptions.esModuleInterop;
       }
     } catch (e) {
-      return false
+      return false;
     }
   }
 
   ast.body.forEach(function (n) {
     if (n.type === 'ExportDefaultDeclaration') {
-      const exportMeta = captureDoc(source, docStyleParsers, n)
+      const exportMeta = captureDoc(source, docStyleParsers, n);
       if (n.declaration.type === 'Identifier') {
-        addNamespace(exportMeta, n.declaration)
+        addNamespace(exportMeta, n.declaration);
       }
-      m.namespace.set('default', exportMeta)
-      return
+      m.namespace.set('default', exportMeta);
+      return;
     }
 
     if (n.type === 'ExportAllDeclaration') {
-      const getter = captureDependency(n)
-      if (getter) m.dependencies.add(getter)
-      return
+      const getter = captureDependency(n);
+      if (getter) m.dependencies.add(getter);
+      return;
     }
 
     // capture namespaces in case of later export
     if (n.type === 'ImportDeclaration') {
-      captureDependency(n)
-      let ns
+      captureDependency(n);
+      let ns;
       if (n.specifiers.some(s => s.type === 'ImportNamespaceSpecifier' && (ns = s))) {
-        namespaces.set(ns.local.name, n.source.value)
+        namespaces.set(ns.local.name, n.source.value);
       }
-      return
+      return;
     }
 
     if (n.type === 'ExportNamedDeclaration') {
@@ -512,59 +512,59 @@ ExportMap.parse = function (path, content, context) {
           case 'TSInterfaceDeclaration':
           case 'TSAbstractClassDeclaration':
           case 'TSModuleDeclaration':
-            m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n))
-            break
+            m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n));
+            break;
           case 'VariableDeclaration':
             n.declaration.declarations.forEach((d) =>
               recursivePatternCapture(d.id,
-                id => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n))))
-            break
+                id => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n))));
+            break;
         }
       }
 
-      const nsource = n.source && n.source.value
+      const nsource = n.source && n.source.value;
       n.specifiers.forEach((s) => {
-        const exportMeta = {}
-        let local
+        const exportMeta = {};
+        let local;
 
         switch (s.type) {
           case 'ExportDefaultSpecifier':
-            if (!n.source) return
-            local = 'default'
-            break
+            if (!n.source) return;
+            local = 'default';
+            break;
           case 'ExportNamespaceSpecifier':
             m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
-              get() { return resolveImport(nsource) },
-            }))
-            return
+              get() { return resolveImport(nsource); },
+            }));
+            return;
           case 'ExportSpecifier':
             if (!n.source) {
-              m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local))
-              return
+              m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local));
+              return;
             }
             // else falls through
           default:
-            local = s.local.name
-            break
+            local = s.local.name;
+            break;
         }
 
         // todo: JSDoc
-        m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) })
-      })
+        m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) });
+      });
     }
 
-    const isEsModuleInteropTrue = isEsModuleInterop()
+    const isEsModuleInteropTrue = isEsModuleInterop();
 
-    const exports = ['TSExportAssignment']
+    const exports = ['TSExportAssignment'];
     if (isEsModuleInteropTrue) {
-      exports.push('TSNamespaceExportDeclaration')
+      exports.push('TSNamespaceExportDeclaration');
     }
 
     // This doesn't declare anything, but changes what's being exported.
     if (includes(exports, n.type)) {
       const exportedName = n.type === 'TSNamespaceExportDeclaration'
         ? n.id.name
-        : (n.expression && n.expression.name || (n.expression.id && n.expression.id.name) || null)
+        : (n.expression && n.expression.name || (n.expression.id && n.expression.id.name) || null);
       const declTypes = [
         'VariableDeclaration',
         'ClassDeclaration',
@@ -574,29 +574,29 @@ ExportMap.parse = function (path, content, context) {
         'TSInterfaceDeclaration',
         'TSAbstractClassDeclaration',
         'TSModuleDeclaration',
-      ]
+      ];
       const exportedDecls = ast.body.filter(({ type, id, declarations }) => includes(declTypes, type) && (
         (id && id.name === exportedName) || (declarations && declarations.find((d) => d.id.name === exportedName))
-      ))
+      ));
       if (exportedDecls.length === 0) {
         // Export is not referencing any local declaration, must be re-exporting
-        m.namespace.set('default', captureDoc(source, docStyleParsers, n))
-        return
+        m.namespace.set('default', captureDoc(source, docStyleParsers, n));
+        return;
       }
       if (isEsModuleInteropTrue) {
-        m.namespace.set('default', {})
+        m.namespace.set('default', {});
       }
       exportedDecls.forEach((decl) => {
         if (decl.type === 'TSModuleDeclaration') {
           if (decl.body && decl.body.type === 'TSModuleDeclaration') {
-            m.namespace.set(decl.body.id.name, captureDoc(source, docStyleParsers, decl.body))
+            m.namespace.set(decl.body.id.name, captureDoc(source, docStyleParsers, decl.body));
           } else if (decl.body && decl.body.body) {
             decl.body.body.forEach((moduleBlockNode) => {
               // Export-assignment exports all members in the namespace,
               // explicitly exported or not.
               const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
                 moduleBlockNode.declaration :
-                moduleBlockNode
+                moduleBlockNode;
 
               if (!namespaceDecl) {
                 // TypeScript can check this for us; we needn't
@@ -606,24 +606,24 @@ ExportMap.parse = function (path, content, context) {
                     id.name,
                     captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode)
                   ))
-                )
+                );
               } else {
                 m.namespace.set(
                   namespaceDecl.id.name,
-                  captureDoc(source, docStyleParsers, moduleBlockNode))
+                  captureDoc(source, docStyleParsers, moduleBlockNode));
               }
-            })
+            });
           }
         } else {
           // Export as default
-          m.namespace.set('default', captureDoc(source, docStyleParsers, decl))
+          m.namespace.set('default', captureDoc(source, docStyleParsers, decl));
         }
-      })
+      });
     }
-  })
+  });
 
-  return m
-}
+  return m;
+};
 
 /**
  * The creation of this closure is isolated from other scopes
@@ -631,7 +631,7 @@ ExportMap.parse = function (path, content, context) {
  * caused memory leaks. See #1266.
  */
 function thunkFor(p, context) {
-  return () => ExportMap.for(childContext(p, context))
+  return () => ExportMap.for(childContext(p, context));
 }
 
 
@@ -645,33 +645,33 @@ function thunkFor(p, context) {
 export function recursivePatternCapture(pattern, callback) {
   switch (pattern.type) {
     case 'Identifier': // base case
-      callback(pattern)
-      break
+      callback(pattern);
+      break;
 
     case 'ObjectPattern':
       pattern.properties.forEach(p => {
         if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
-          callback(p.argument)
-          return
+          callback(p.argument);
+          return;
         }
-        recursivePatternCapture(p.value, callback)
-      })
-      break
+        recursivePatternCapture(p.value, callback);
+      });
+      break;
 
     case 'ArrayPattern':
       pattern.elements.forEach((element) => {
-        if (element == null) return
+        if (element == null) return;
         if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
-          callback(element.argument)
-          return
+          callback(element.argument);
+          return;
         }
-        recursivePatternCapture(element, callback)
-      })
-      break
+        recursivePatternCapture(element, callback);
+      });
+      break;
 
     case 'AssignmentPattern':
-      callback(pattern.left)
-      break
+      callback(pattern.left);
+      break;
   }
 }
 
@@ -679,13 +679,13 @@ export function recursivePatternCapture(pattern, callback) {
  * don't hold full context object in memory, just grab what we need.
  */
 function childContext(path, context) {
-  const { settings, parserOptions, parserPath } = context
+  const { settings, parserOptions, parserPath } = context;
   return {
     settings,
     parserOptions,
     parserPath,
     path,
-  }
+  };
 }
 
 
@@ -695,9 +695,9 @@ function childContext(path, context) {
 function makeSourceCode(text, ast) {
   if (SourceCode.length > 1) {
     // ESLint 3
-    return new SourceCode(text, ast)
+    return new SourceCode(text, ast);
   } else {
     // ESLint 4, 5
-    return new SourceCode({ text, ast })
+    return new SourceCode({ text, ast });
   }
 }
diff --git a/src/core/importType.js b/src/core/importType.js
index dc7f889df7..b1273124de 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -1,101 +1,101 @@
-import isCoreModule from 'is-core-module'
+import isCoreModule from 'is-core-module';
 
-import resolve from 'eslint-module-utils/resolve'
+import resolve from 'eslint-module-utils/resolve';
 
 function baseModule(name) {
   if (isScoped(name)) {
-    const [scope, pkg] = name.split('/')
-    return `${scope}/${pkg}`
+    const [scope, pkg] = name.split('/');
+    return `${scope}/${pkg}`;
   }
-  const [pkg] = name.split('/')
-  return pkg
+  const [pkg] = name.split('/');
+  return pkg;
 }
 
 export function isAbsolute(name) {
-  return name && name.startsWith('/')
+  return name && name.startsWith('/');
 }
 
 // path is defined only when a resolver resolves to a non-standard path
 export function isBuiltIn(name, settings, path) {
-  if (path || !name) return false
-  const base = baseModule(name)
-  const extras = (settings && settings['import/core-modules']) || []
-  return isCoreModule(base) || extras.indexOf(base) > -1
+  if (path || !name) return false;
+  const base = baseModule(name);
+  const extras = (settings && settings['import/core-modules']) || [];
+  return isCoreModule(base) || extras.indexOf(base) > -1;
 }
 
 function isExternalPath(path, name, settings) {
-  const folders = (settings && settings['import/external-module-folders']) || ['node_modules']
-  return !path || folders.some(folder => isSubpath(folder, path))
+  const folders = (settings && settings['import/external-module-folders']) || ['node_modules'];
+  return !path || folders.some(folder => isSubpath(folder, path));
 }
 
 function isSubpath(subpath, path) {
-  const normPath = path.replace(/\\/g, '/')
-  const normSubpath = subpath.replace(/\\/g, '/').replace(/\/$/, '')
+  const normPath = path.replace(/\\/g, '/');
+  const normSubpath = subpath.replace(/\\/g, '/').replace(/\/$/, '');
   if (normSubpath.length === 0) {
-    return false
+    return false;
   }
-  const left = normPath.indexOf(normSubpath)
-  const right = left + normSubpath.length
+  const left = normPath.indexOf(normSubpath);
+  const right = left + normSubpath.length;
   return left !== -1 &&
         (left === 0 || normSubpath[0] !== '/' && normPath[left - 1] === '/') &&
-        (right >= normPath.length || normPath[right] === '/')
+        (right >= normPath.length || normPath[right] === '/');
 }
 
-const externalModuleRegExp = /^\w/
+const externalModuleRegExp = /^\w/;
 export function isExternalModule(name, settings, path) {
-  return externalModuleRegExp.test(name) && isExternalPath(path, name, settings)
+  return externalModuleRegExp.test(name) && isExternalPath(path, name, settings);
 }
 
-const externalModuleMainRegExp = /^[\w]((?!\/).)*$/
+const externalModuleMainRegExp = /^[\w]((?!\/).)*$/;
 export function isExternalModuleMain(name, settings, path) {
-  return externalModuleMainRegExp.test(name) && isExternalPath(path, name, settings)
+  return externalModuleMainRegExp.test(name) && isExternalPath(path, name, settings);
 }
 
-const scopedRegExp = /^@[^/]*\/?[^/]+/
+const scopedRegExp = /^@[^/]*\/?[^/]+/;
 export function isScoped(name) {
-  return name && scopedRegExp.test(name)
+  return name && scopedRegExp.test(name);
 }
 
-const scopedMainRegExp = /^@[^/]+\/?[^/]+$/
+const scopedMainRegExp = /^@[^/]+\/?[^/]+$/;
 export function isScopedMain(name) {
-  return name && scopedMainRegExp.test(name)
+  return name && scopedMainRegExp.test(name);
 }
 
 function isInternalModule(name, settings, path) {
-  const internalScope = (settings && settings['import/internal-regex'])
-  const matchesScopedOrExternalRegExp = scopedRegExp.test(name) || externalModuleRegExp.test(name)
-  return (matchesScopedOrExternalRegExp && (internalScope && new RegExp(internalScope).test(name) || !isExternalPath(path, name, settings)))
+  const internalScope = (settings && settings['import/internal-regex']);
+  const matchesScopedOrExternalRegExp = scopedRegExp.test(name) || externalModuleRegExp.test(name);
+  return (matchesScopedOrExternalRegExp && (internalScope && new RegExp(internalScope).test(name) || !isExternalPath(path, name, settings)));
 }
 
 function isRelativeToParent(name) {
-  return/^\.\.$|^\.\.[\\/]/.test(name)
+  return/^\.\.$|^\.\.[\\/]/.test(name);
 }
 
-const indexFiles = ['.', './', './index', './index.js']
+const indexFiles = ['.', './', './index', './index.js'];
 function isIndex(name) {
-  return indexFiles.indexOf(name) !== -1
+  return indexFiles.indexOf(name) !== -1;
 }
 
 function isRelativeToSibling(name) {
-  return /^\.[\\/]/.test(name)
+  return /^\.[\\/]/.test(name);
 }
 
 function typeTest(name, settings, path) {
-  if (isAbsolute(name, settings, path)) { return 'absolute' }
-  if (isBuiltIn(name, settings, path)) { return 'builtin' }
-  if (isInternalModule(name, settings, path)) { return 'internal' }
-  if (isExternalModule(name, settings, path)) { return 'external' }
-  if (isScoped(name, settings, path)) { return 'external' }
-  if (isRelativeToParent(name, settings, path)) { return 'parent' }
-  if (isIndex(name, settings, path)) { return 'index' }
-  if (isRelativeToSibling(name, settings, path)) { return 'sibling' }
-  return 'unknown'
+  if (isAbsolute(name, settings, path)) { return 'absolute'; }
+  if (isBuiltIn(name, settings, path)) { return 'builtin'; }
+  if (isInternalModule(name, settings, path)) { return 'internal'; }
+  if (isExternalModule(name, settings, path)) { return 'external'; }
+  if (isScoped(name, settings, path)) { return 'external'; }
+  if (isRelativeToParent(name, settings, path)) { return 'parent'; }
+  if (isIndex(name, settings, path)) { return 'index'; }
+  if (isRelativeToSibling(name, settings, path)) { return 'sibling'; }
+  return 'unknown';
 }
 
 export function isScopedModule(name) {
-  return name.indexOf('@') === 0 && !name.startsWith('@/')
+  return name.indexOf('@') === 0 && !name.startsWith('@/');
 }
 
 export default function resolveImportType(name, context) {
-  return typeTest(name, context.settings, resolve(name, context))
+  return typeTest(name, context.settings, resolve(name, context));
 }
diff --git a/src/core/staticRequire.js b/src/core/staticRequire.js
index 45ed79d79b..502d39317d 100644
--- a/src/core/staticRequire.js
+++ b/src/core/staticRequire.js
@@ -6,5 +6,5 @@ export default function isStaticRequire(node) {
     node.callee.name === 'require' &&
     node.arguments.length === 1 &&
     node.arguments[0].type === 'Literal' &&
-    typeof node.arguments[0].value === 'string'
+    typeof node.arguments[0].value === 'string';
 }
diff --git a/src/docsUrl.js b/src/docsUrl.js
index 3c01c49adf..ff277251b4 100644
--- a/src/docsUrl.js
+++ b/src/docsUrl.js
@@ -1,7 +1,7 @@
-import pkg from '../package.json'
+import pkg from '../package.json';
 
-const repoUrl = 'https://github.com/benmosher/eslint-plugin-import'
+const repoUrl = 'https://github.com/benmosher/eslint-plugin-import';
 
 export default function docsUrl(ruleName, commitish = `v${pkg.version}`) {
-  return `${repoUrl}/blob/${commitish}/docs/rules/${ruleName}.md`
+  return `${repoUrl}/blob/${commitish}/docs/rules/${ruleName}.md`;
 }
diff --git a/src/importDeclaration.js b/src/importDeclaration.js
index 69af65d978..fd3a73253c 100644
--- a/src/importDeclaration.js
+++ b/src/importDeclaration.js
@@ -1,4 +1,4 @@
 export default function importDeclaration(context) {
-  var ancestors = context.getAncestors()
-  return ancestors[ancestors.length - 1]
+  var ancestors = context.getAncestors();
+  return ancestors[ancestors.length - 1];
 }
diff --git a/src/index.js b/src/index.js
index d0a98b7cb9..dbddba8c01 100644
--- a/src/index.js
+++ b/src/index.js
@@ -48,7 +48,7 @@ export const rules = {
 
   // deprecated aliases to rules
   'imports-first': require('./rules/imports-first'),
-}
+};
 
 export const configs = {
   'recommended': require('../config/recommended'),
@@ -64,4 +64,4 @@ export const configs = {
   'react-native': require('../config/react-native'),
   'electron': require('../config/electron'),
   'typescript': require('../config/typescript'),
-}
+};
diff --git a/src/rules/default.js b/src/rules/default.js
index 09efa0d880..b686974a86 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -1,5 +1,5 @@
-import Exports from '../ExportMap'
-import docsUrl from '../docsUrl'
+import Exports from '../ExportMap';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -16,25 +16,25 @@ module.exports = {
 
       const defaultSpecifier = node.specifiers.find(
         specifier => specifier.type === specifierType
-      )
+      );
 
-      if (!defaultSpecifier) return
-      var imports = Exports.get(node.source.value, context)
-      if (imports == null) return
+      if (!defaultSpecifier) return;
+      var imports = Exports.get(node.source.value, context);
+      if (imports == null) return;
 
       if (imports.errors.length) {
-        imports.reportErrors(context, node)
+        imports.reportErrors(context, node);
       } else if (imports.get('default') === undefined) {
         context.report({
           node: defaultSpecifier,
           message: `No default export found in imported module "${node.source.value}".`,
-        })
+        });
       }
     }
 
     return {
       'ImportDeclaration': checkDefault.bind(null, 'ImportDefaultSpecifier'),
       'ExportNamedDeclaration': checkDefault.bind(null, 'ExportDefaultSpecifier'),
-    }
+    };
   },
-}
+};
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 5ac89e1e64..7a21ec62d9 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -1,5 +1,5 @@
-import vm from 'vm'
-import docsUrl from '../docsUrl'
+import vm from 'vm';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -25,58 +25,58 @@ module.exports = {
   },
 
   create: function (context) {
-    const config = context.options[0]
-    const { importFunctions = [] } = config || {}
-    const { webpackChunknameFormat = '[0-9a-zA-Z-_/.]+' } = config || {}
+    const config = context.options[0];
+    const { importFunctions = [] } = config || {};
+    const { webpackChunknameFormat = '[0-9a-zA-Z-_/.]+' } = config || {};
 
-    const paddedCommentRegex = /^ (\S[\s\S]+\S) $/
-    const commentStyleRegex = /^( \w+: (["'][^"']*["']|\d+|false|true),?)+ $/
-    const chunkSubstrFormat = ` webpackChunkName: ["']${webpackChunknameFormat}["'],? `
-    const chunkSubstrRegex = new RegExp(chunkSubstrFormat)
+    const paddedCommentRegex = /^ (\S[\s\S]+\S) $/;
+    const commentStyleRegex = /^( \w+: (["'][^"']*["']|\d+|false|true),?)+ $/;
+    const chunkSubstrFormat = ` webpackChunkName: ["']${webpackChunknameFormat}["'],? `;
+    const chunkSubstrRegex = new RegExp(chunkSubstrFormat);
 
     function run(node, arg) {
-      const sourceCode = context.getSourceCode()
+      const sourceCode = context.getSourceCode();
       const leadingComments = sourceCode.getCommentsBefore
         ? sourceCode.getCommentsBefore(arg) // This method is available in ESLint >= 4.
-        : sourceCode.getComments(arg).leading // This method is deprecated in ESLint 7.
+        : sourceCode.getComments(arg).leading; // This method is deprecated in ESLint 7.
 
       if (!leadingComments || leadingComments.length === 0) {
         context.report({
           node,
           message: 'dynamic imports require a leading comment with the webpack chunkname',
-        })
-        return
+        });
+        return;
       }
 
-      let isChunknamePresent = false
+      let isChunknamePresent = false;
 
       for (const comment of leadingComments) {
         if (comment.type !== 'Block') {
           context.report({
             node,
             message: 'dynamic imports require a /* foo */ style comment, not a // foo comment',
-          })
-          return
+          });
+          return;
         }
 
         if (!paddedCommentRegex.test(comment.value)) {
           context.report({
             node,
             message: `dynamic imports require a block comment padded with spaces - /* foo */`,
-          })
-          return
+          });
+          return;
         }
 
         try {
           // just like webpack itself does
-          vm.runInNewContext(`(function(){return {${comment.value}}})()`)
+          vm.runInNewContext(`(function(){return {${comment.value}}})()`);
         }
         catch (error) {
           context.report({
             node,
             message: `dynamic imports require a "webpack" comment with valid syntax`,
-          })
-          return
+          });
+          return;
         }
 
         if (!commentStyleRegex.test(comment.value)) {
@@ -84,12 +84,12 @@ module.exports = {
             node,
             message:
               `dynamic imports require a leading comment in the form /*${chunkSubstrFormat}*/`,
-          })
-          return
+          });
+          return;
         }
 
         if (chunkSubstrRegex.test(comment.value)) {
-          isChunknamePresent = true
+          isChunknamePresent = true;
         }
       }
 
@@ -98,22 +98,22 @@ module.exports = {
           node,
           message:
             `dynamic imports require a leading comment in the form /*${chunkSubstrFormat}*/`,
-        })
+        });
       }
     }
 
     return {
       ImportExpression(node) {
-        run(node, node.source)
+        run(node, node.source);
       },
 
       CallExpression(node) {
         if (node.callee.type !== 'Import' && importFunctions.indexOf(node.callee.name) < 0) {
-          return
+          return;
         }
 
-        run(node, node.arguments[0])
+        run(node, node.arguments[0]);
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/export.js b/src/rules/export.js
index 212a60f6e6..fcc649fcdc 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -1,6 +1,6 @@
-import ExportMap, { recursivePatternCapture } from '../ExportMap'
-import docsUrl from '../docsUrl'
-import includes from 'array-includes'
+import ExportMap, { recursivePatternCapture } from '../ExportMap';
+import docsUrl from '../docsUrl';
+import includes from 'array-includes';
 
 /*
 Notes on TypeScript namespaces aka TSModuleDeclaration:
@@ -21,8 +21,8 @@ ambient namespaces:
 - have no other restrictions
 */
 
-const rootProgram = 'root'
-const tsTypePrefix = 'type:'
+const rootProgram = 'root';
+const tsTypePrefix = 'type:';
 
 /**
  * Detect function overloads like:
@@ -35,14 +35,14 @@ const tsTypePrefix = 'type:'
  * @returns {boolean}
  */
 function isTypescriptFunctionOverloads(nodes) {
-  const types = new Set(Array.from(nodes, node => node.parent.type))
+  const types = new Set(Array.from(nodes, node => node.parent.type));
   return (
     types.has('TSDeclareFunction') &&
     (
       types.size === 1 ||
       (types.size === 2 && types.has('FunctionDeclaration'))
     )
-  )
+  );
 }
 
 module.exports = {
@@ -55,33 +55,33 @@ module.exports = {
   },
 
   create: function (context) {
-    const namespace = new Map([[rootProgram, new Map()]])
+    const namespace = new Map([[rootProgram, new Map()]]);
 
     function addNamed(name, node, parent, isType) {
       if (!namespace.has(parent)) {
-        namespace.set(parent, new Map())
+        namespace.set(parent, new Map());
       }
-      const named = namespace.get(parent)
+      const named = namespace.get(parent);
 
-      const key = isType ? `${tsTypePrefix}${name}` : name
-      let nodes = named.get(key)
+      const key = isType ? `${tsTypePrefix}${name}` : name;
+      let nodes = named.get(key);
 
       if (nodes == null) {
-        nodes = new Set()
-        named.set(key, nodes)
+        nodes = new Set();
+        named.set(key, nodes);
       }
 
-      nodes.add(node)
+      nodes.add(node);
     }
 
     function getParent(node) {
       if (node.parent && node.parent.type === 'TSModuleBlock') {
-        return node.parent.parent
+        return node.parent.parent;
       }
 
       // just in case somehow a non-ts namespace export declaration isn't directly
       // parented to the root Program node
-      return rootProgram
+      return rootProgram;
     }
 
     return {
@@ -94,81 +94,81 @@ module.exports = {
       ),
 
       'ExportNamedDeclaration': function (node) {
-        if (node.declaration == null) return
+        if (node.declaration == null) return;
 
-        const parent = getParent(node)
+        const parent = getParent(node);
         // support for old TypeScript versions
-        const isTypeVariableDecl = node.declaration.kind === 'type'
+        const isTypeVariableDecl = node.declaration.kind === 'type';
 
         if (node.declaration.id != null) {
           if (includes([
             'TSTypeAliasDeclaration',
             'TSInterfaceDeclaration',
           ], node.declaration.type)) {
-            addNamed(node.declaration.id.name, node.declaration.id, parent, true)
+            addNamed(node.declaration.id.name, node.declaration.id, parent, true);
           } else {
-            addNamed(node.declaration.id.name, node.declaration.id, parent, isTypeVariableDecl)
+            addNamed(node.declaration.id.name, node.declaration.id, parent, isTypeVariableDecl);
           }
         }
 
         if (node.declaration.declarations != null) {
           for (let declaration of node.declaration.declarations) {
             recursivePatternCapture(declaration.id, v =>
-              addNamed(v.name, v, parent, isTypeVariableDecl))
+              addNamed(v.name, v, parent, isTypeVariableDecl));
           }
         }
       },
 
       'ExportAllDeclaration': function (node) {
-        if (node.source == null) return // not sure if this is ever true
+        if (node.source == null) return; // not sure if this is ever true
 
         // `export * as X from 'path'` does not conflict
-        if (node.exported && node.exported.name) return
+        if (node.exported && node.exported.name) return;
 
-        const remoteExports = ExportMap.get(node.source.value, context)
-        if (remoteExports == null) return
+        const remoteExports = ExportMap.get(node.source.value, context);
+        if (remoteExports == null) return;
 
         if (remoteExports.errors.length) {
-          remoteExports.reportErrors(context, node)
-          return
+          remoteExports.reportErrors(context, node);
+          return;
         }
 
-        const parent = getParent(node)
+        const parent = getParent(node);
 
-        let any = false
+        let any = false;
         remoteExports.forEach((v, name) =>
           name !== 'default' &&
           (any = true) && // poor man's filter
-          addNamed(name, node, parent))
+          addNamed(name, node, parent));
 
         if (!any) {
           context.report(
             node.source,
             `No named exports found in module '${node.source.value}'.`
-          )
+          );
         }
       },
 
       'Program:exit': function () {
         for (let [, named] of namespace) {
           for (let [name, nodes] of named) {
-            if (nodes.size <= 1) continue
+            if (nodes.size <= 1) continue;
 
-            if (isTypescriptFunctionOverloads(nodes)) continue
+            if (isTypescriptFunctionOverloads(nodes)) continue;
 
             for (let node of nodes) {
               if (name === 'default') {
-                context.report(node, 'Multiple default exports.')
+                context.report(node, 'Multiple default exports.');
               } else {
                 context.report(
                   node,
                   `Multiple exports of name '${name.replace(tsTypePrefix, '')}'.`
-                )
+                );
               }
             }
           }
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/exports-last.js b/src/rules/exports-last.js
index 65dd8a30fa..ea044f32b6 100644
--- a/src/rules/exports-last.js
+++ b/src/rules/exports-last.js
@@ -1,9 +1,9 @@
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 function isNonExportStatement({ type }) {
   return type !== 'ExportDefaultDeclaration' &&
     type !== 'ExportNamedDeclaration' &&
-    type !== 'ExportAllDeclaration'
+    type !== 'ExportAllDeclaration';
 }
 
 module.exports = {
@@ -20,10 +20,10 @@ module.exports = {
       Program: function ({ body }) {
         const lastNonExportStatementIndex = body.reduce(function findLastIndex(acc, item, index) {
           if (isNonExportStatement(item)) {
-            return index
+            return index;
           }
-          return acc
-        }, -1)
+          return acc;
+        }, -1);
 
         if (lastNonExportStatementIndex !== -1) {
           body.slice(0, lastNonExportStatementIndex).forEach(function checkNonExport(node) {
@@ -31,11 +31,11 @@ module.exports = {
               context.report({
                 node,
                 message: 'Export statements should appear at the end of the file',
-              })
+              });
             }
-          })
+          });
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index fd9d177adf..473d8b603a 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -1,21 +1,21 @@
-import path from 'path'
+import path from 'path';
 
-import resolve from 'eslint-module-utils/resolve'
-import { isBuiltIn, isExternalModule, isScoped, isScopedModule } from '../core/importType'
-import docsUrl from '../docsUrl'
+import resolve from 'eslint-module-utils/resolve';
+import { isBuiltIn, isExternalModule, isScoped, isScopedModule } from '../core/importType';
+import docsUrl from '../docsUrl';
 
-const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] }
+const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] };
 const patternProperties = {
   type: 'object',
   patternProperties: { '.*': enumValues },
-}
+};
 const properties = {
   type: 'object',
   properties: {
     'pattern': patternProperties,
     'ignorePackages': { type: 'boolean' },
   },
-}
+};
 
 function buildProperties(context) {
 
@@ -23,39 +23,39 @@ function buildProperties(context) {
       defaultConfig: 'never',
       pattern: {},
       ignorePackages: false,
-    }
+    };
 
     context.options.forEach(obj => {
 
       // If this is a string, set defaultConfig to its value
       if (typeof obj === 'string') {
-        result.defaultConfig = obj
-        return
+        result.defaultConfig = obj;
+        return;
       }
 
       // If this is not the new structure, transfer all props to result.pattern
       if (obj.pattern === undefined && obj.ignorePackages === undefined) {
-        Object.assign(result.pattern, obj)
-        return
+        Object.assign(result.pattern, obj);
+        return;
       }
 
       // If pattern is provided, transfer all props
       if (obj.pattern !== undefined) {
-        Object.assign(result.pattern, obj.pattern)
+        Object.assign(result.pattern, obj.pattern);
       }
 
       // If ignorePackages is provided, transfer it to result
       if (obj.ignorePackages !== undefined) {
-        result.ignorePackages = obj.ignorePackages
+        result.ignorePackages = obj.ignorePackages;
       }
-    })
+    });
 
     if (result.defaultConfig === 'ignorePackages') {
-      result.defaultConfig = 'always'
-      result.ignorePackages = true
+      result.defaultConfig = 'always';
+      result.ignorePackages = true;
     }
 
-    return result
+    return result;
 }
 
 module.exports = {
@@ -104,79 +104,79 @@ module.exports = {
 
   create: function (context) {
 
-    const props = buildProperties(context)
+    const props = buildProperties(context);
 
     function getModifier(extension) {
-      return props.pattern[extension] || props.defaultConfig
+      return props.pattern[extension] || props.defaultConfig;
     }
 
     function isUseOfExtensionRequired(extension, isPackage) {
-      return getModifier(extension) === 'always' && (!props.ignorePackages || !isPackage)
+      return getModifier(extension) === 'always' && (!props.ignorePackages || !isPackage);
     }
 
     function isUseOfExtensionForbidden(extension) {
-      return getModifier(extension) === 'never'
+      return getModifier(extension) === 'never';
     }
 
     function isResolvableWithoutExtension(file) {
-      const extension = path.extname(file)
-      const fileWithoutExtension = file.slice(0, -extension.length)
-      const resolvedFileWithoutExtension = resolve(fileWithoutExtension, context)
+      const extension = path.extname(file);
+      const fileWithoutExtension = file.slice(0, -extension.length);
+      const resolvedFileWithoutExtension = resolve(fileWithoutExtension, context);
 
-      return resolvedFileWithoutExtension === resolve(file, context)
+      return resolvedFileWithoutExtension === resolve(file, context);
     }
 
     function isExternalRootModule(file) {
-      const slashCount = file.split('/').length - 1
+      const slashCount = file.split('/').length - 1;
 
-      if (isScopedModule(file) && slashCount <= 1) return true
-      if (isExternalModule(file, context, resolve(file, context)) && !slashCount) return true
-      return false
+      if (isScopedModule(file) && slashCount <= 1) return true;
+      if (isExternalModule(file, context, resolve(file, context)) && !slashCount) return true;
+      return false;
     }
 
     function checkFileExtension(node) {
-      const { source } = node
+      const { source } = node;
 
       // bail if the declaration doesn't have a source, e.g. "export { foo };"
-      if (!source) return
+      if (!source) return;
 
-      const importPathWithQueryString = source.value
+      const importPathWithQueryString = source.value;
 
       // don't enforce anything on builtins
-      if (isBuiltIn(importPathWithQueryString, context.settings)) return
+      if (isBuiltIn(importPathWithQueryString, context.settings)) return;
 
-      const importPath = importPathWithQueryString.replace(/\?(.*)$/, '')
+      const importPath = importPathWithQueryString.replace(/\?(.*)$/, '');
 
       // don't enforce in root external packages as they may have names with `.js`.
       // Like `import Decimal from decimal.js`)
-      if (isExternalRootModule(importPath)) return
+      if (isExternalRootModule(importPath)) return;
 
-      const resolvedPath = resolve(importPath, context)
+      const resolvedPath = resolve(importPath, context);
 
       // get extension from resolved path, if possible.
       // for unresolved, use source value.
-      const extension = path.extname(resolvedPath || importPath).substring(1)
+      const extension = path.extname(resolvedPath || importPath).substring(1);
 
       // determine if this is a module
       const isPackage = isExternalModule(importPath, context.settings)
-        || isScoped(importPath)
+        || isScoped(importPath);
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
-        const extensionRequired = isUseOfExtensionRequired(extension, isPackage)
-        const extensionForbidden = isUseOfExtensionForbidden(extension)
+        const extensionRequired = isUseOfExtensionRequired(extension, isPackage);
+        const extensionForbidden = isUseOfExtensionForbidden(extension);
         if (extensionRequired && !extensionForbidden) {
           context.report({
             node: source,
             message:
               `Missing file extension ${extension ? `"${extension}" ` : ''}for "${importPathWithQueryString}"`,
-          })
+          });
         }
       } else if (extension) {
         if (isUseOfExtensionForbidden(extension) && isResolvableWithoutExtension(importPath)) {
           context.report({
             node: source,
             message: `Unexpected use of file extension "${extension}" for "${importPathWithQueryString}"`,
-          })
+          });
         }
       }
     }
@@ -184,6 +184,6 @@ module.exports = {
     return {
       ImportDeclaration: checkFileExtension,
       ExportNamedDeclaration: checkFileExtension,
-    }
+    };
   },
-}
+};
diff --git a/src/rules/first.js b/src/rules/first.js
index c1422cdb0b..eea9d9e138 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -1,4 +1,4 @@
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -19,7 +19,7 @@ module.exports = {
     function isPossibleDirective (node) {
       return node.type === 'ExpressionStatement' &&
         node.expression.type === 'Literal' &&
-        typeof node.expression.value === 'string'
+        typeof node.expression.value === 'string';
     }
 
     return {
@@ -28,105 +28,105 @@ module.exports = {
             , absoluteFirst = context.options[0] === 'absolute-first'
             , message = 'Import in body of module; reorder to top.'
             , sourceCode = context.getSourceCode()
-            , originSourceCode = sourceCode.getText()
+            , originSourceCode = sourceCode.getText();
         let nonImportCount = 0
           , anyExpressions = false
           , anyRelative = false
           , lastLegalImp = null
           , errorInfos = []
           , shouldSort = true
-          , lastSortNodesIndex = 0
+          , lastSortNodesIndex = 0;
         body.forEach(function (node, index){
           if (!anyExpressions && isPossibleDirective(node)) {
-            return
+            return;
           }
 
-          anyExpressions = true
+          anyExpressions = true;
 
           if (node.type === 'ImportDeclaration') {
             if (absoluteFirst) {
               if (/^\./.test(node.source.value)) {
-                anyRelative = true
+                anyRelative = true;
               } else if (anyRelative) {
                 context.report({
                   node: node.source,
                   message: 'Absolute imports should come before relative imports.',
-                })
+                });
               }
             }
             if (nonImportCount > 0) {
               for (let variable of context.getDeclaredVariables(node)) {
-                if (!shouldSort) break
-                const references = variable.references
+                if (!shouldSort) break;
+                const references = variable.references;
                 if (references.length) {
                   for (let reference of references) {
                     if (reference.identifier.range[0] < node.range[1]) {
-                      shouldSort = false
-                      break
+                      shouldSort = false;
+                      break;
                     }
                   }
                 }
               }
-              shouldSort && (lastSortNodesIndex = errorInfos.length)
+              shouldSort && (lastSortNodesIndex = errorInfos.length);
               errorInfos.push({
                 node,
                 range: [body[index - 1].range[1], node.range[1]],
-              })
+              });
             } else {
-              lastLegalImp = node
+              lastLegalImp = node;
             }
           } else {
-            nonImportCount++
+            nonImportCount++;
           }
-        })
-        if (!errorInfos.length) return
+        });
+        if (!errorInfos.length) return;
         errorInfos.forEach(function (errorInfo, index) {
           const node = errorInfo.node
               , infos = {
                 node,
                 message,
-              }
+              };
           if (index < lastSortNodesIndex) {
             infos.fix = function (fixer) {
-              return fixer.insertTextAfter(node, '')
-            }
+              return fixer.insertTextAfter(node, '');
+            };
           } else if (index === lastSortNodesIndex) {
-            const sortNodes = errorInfos.slice(0, lastSortNodesIndex + 1)
+            const sortNodes = errorInfos.slice(0, lastSortNodesIndex + 1);
             infos.fix = function (fixer) {
               const removeFixers = sortNodes.map(function (_errorInfo) {
-                    return fixer.removeRange(_errorInfo.range)
+                    return fixer.removeRange(_errorInfo.range);
                   })
-                  , range = [0, removeFixers[removeFixers.length - 1].range[1]]
+                  , range = [0, removeFixers[removeFixers.length - 1].range[1]];
               let insertSourceCode = sortNodes.map(function (_errorInfo) {
                     const nodeSourceCode = String.prototype.slice.apply(
                       originSourceCode, _errorInfo.range
-                    )
+                    );
                     if (/\S/.test(nodeSourceCode[0])) {
-                      return '\n' + nodeSourceCode
+                      return '\n' + nodeSourceCode;
                     }
-                    return nodeSourceCode
+                    return nodeSourceCode;
                   }).join('')
                 , insertFixer = null
-                , replaceSourceCode = ''
+                , replaceSourceCode = '';
               if (!lastLegalImp) {
                   insertSourceCode =
-                    insertSourceCode.trim() + insertSourceCode.match(/^(\s+)/)[0]
+                    insertSourceCode.trim() + insertSourceCode.match(/^(\s+)/)[0];
               }
               insertFixer = lastLegalImp ?
                             fixer.insertTextAfter(lastLegalImp, insertSourceCode) :
-                            fixer.insertTextBefore(body[0], insertSourceCode)
-              const fixers = [insertFixer].concat(removeFixers)
+                            fixer.insertTextBefore(body[0], insertSourceCode);
+              const fixers = [insertFixer].concat(removeFixers);
               fixers.forEach(function (computedFixer, i) {
                 replaceSourceCode += (originSourceCode.slice(
                   fixers[i - 1] ? fixers[i - 1].range[1] : 0, computedFixer.range[0]
-                ) + computedFixer.text)
-              })
-              return fixer.replaceTextRange(range, replaceSourceCode)
-            }
+                ) + computedFixer.text);
+              });
+              return fixer.replaceTextRange(range, replaceSourceCode);
+            };
           }
-          context.report(infos)
-        })
+          context.report(infos);
+        });
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/group-exports.js b/src/rules/group-exports.js
index 8abeb3d231..a022eb6447 100644
--- a/src/rules/group-exports.js
+++ b/src/rules/group-exports.js
@@ -1,18 +1,18 @@
-import docsUrl from '../docsUrl'
-import values from 'object.values'
-import flat from 'array.prototype.flat'
+import docsUrl from '../docsUrl';
+import values from 'object.values';
+import flat from 'array.prototype.flat';
 
 const meta = {
   type: 'suggestion',
   docs: {
     url: docsUrl('group-exports'),
   },
-}
+};
 /* eslint-disable max-len */
 const errors = {
   ExportNamedDeclaration: 'Multiple named export declarations; consolidate all named exports into a single export declaration',
   AssignmentExpression: 'Multiple CommonJS exports; consolidate all exports into a single assignment to `module.exports`',
-}
+};
 /* eslint-enable max-len */
 
 /**
@@ -28,20 +28,20 @@ const errors = {
  * @private
  */
 function accessorChain(node) {
-  const chain = []
+  const chain = [];
 
   do {
-    chain.unshift(node.property.name)
+    chain.unshift(node.property.name);
 
     if (node.object.type === 'Identifier') {
-      chain.unshift(node.object.name)
-      break
+      chain.unshift(node.object.name);
+      break;
     }
 
-    node = node.object
-  } while (node.type === 'MemberExpression')
+    node = node.object;
+  } while (node.type === 'MemberExpression');
 
-  return chain
+  return chain;
 }
 
 function create(context) {
@@ -57,39 +57,39 @@ function create(context) {
     commonjs: {
       set: new Set(),
     },
-  }
+  };
 
   return {
     ExportNamedDeclaration(node) {
-      let target = node.exportKind === 'type' ? nodes.types : nodes.modules
+      let target = node.exportKind === 'type' ? nodes.types : nodes.modules;
       if (!node.source) {
-        target.set.add(node)
+        target.set.add(node);
       } else if (Array.isArray(target.sources[node.source.value])) {
-        target.sources[node.source.value].push(node)
+        target.sources[node.source.value].push(node);
       } else {
-        target.sources[node.source.value] = [node]
+        target.sources[node.source.value] = [node];
       }
     },
 
     AssignmentExpression(node) {
       if (node.left.type !== 'MemberExpression') {
-        return
+        return;
       }
 
-      const chain = accessorChain(node.left)
+      const chain = accessorChain(node.left);
 
       // Assignments to module.exports
       // Deeper assignments are ignored since they just modify what's already being exported
       // (ie. module.exports.exported.prop = true is ignored)
       if (chain[0] === 'module' && chain[1] === 'exports' && chain.length <= 3) {
-        nodes.commonjs.set.add(node)
-        return
+        nodes.commonjs.set.add(node);
+        return;
       }
 
       // Assignments to exports (exports.* = *)
       if (chain[0] === 'exports' && chain.length === 2) {
-        nodes.commonjs.set.add(node)
-        return
+        nodes.commonjs.set.add(node);
+        return;
       }
     },
 
@@ -100,8 +100,8 @@ function create(context) {
           context.report({
             node,
             message: errors[node.type],
-          })
-        })
+          });
+        });
       }
 
       // Report multiple `aggregated exports` from the same module (ES2015 modules)
@@ -111,8 +111,8 @@ function create(context) {
           context.report({
             node,
             message: errors[node.type],
-          })
-        })
+          });
+        });
 
       // Report multiple `export type` declarations (FLOW ES2015 modules)
       if (nodes.types.set.size > 1) {
@@ -120,8 +120,8 @@ function create(context) {
           context.report({
             node,
             message: errors[node.type],
-          })
-        })
+          });
+        });
       }
 
       // Report multiple `aggregated type exports` from the same module (FLOW ES2015 modules)
@@ -131,8 +131,8 @@ function create(context) {
           context.report({
             node,
             message: errors[node.type],
-          })
-        })
+          });
+        });
 
       // Report multiple `module.exports` assignments (CommonJS)
       if (nodes.commonjs.set.size > 1) {
@@ -140,14 +140,14 @@ function create(context) {
           context.report({
             node,
             message: errors[node.type],
-          })
-        })
+          });
+        });
       }
     },
-  }
+  };
 }
 
 module.exports = {
   meta,
   create,
-}
+};
diff --git a/src/rules/imports-first.js b/src/rules/imports-first.js
index 7ed9accc46..ba8af48f00 100644
--- a/src/rules/imports-first.js
+++ b/src/rules/imports-first.js
@@ -1,12 +1,12 @@
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
-const first = require('./first')
+const first = require('./first');
 
 const newMeta = Object.assign({}, first.meta, {
   deprecated: true,
   docs: {
     url: docsUrl('imports-first', '7b25c1cb95ee18acc1531002fd343e1e6031f9ed'),
   },
-})
+});
 
-module.exports = Object.assign({}, first, { meta: newMeta })
+module.exports = Object.assign({}, first, { meta: newMeta });
diff --git a/src/rules/max-dependencies.js b/src/rules/max-dependencies.js
index 7e1fdb1011..74b125ec5c 100644
--- a/src/rules/max-dependencies.js
+++ b/src/rules/max-dependencies.js
@@ -1,18 +1,18 @@
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
 
-const DEFAULT_MAX = 10
+const DEFAULT_MAX = 10;
 
 const countDependencies = (dependencies, lastNode, context) => {
-  const {max} = context.options[0] || { max: DEFAULT_MAX }
+  const {max} = context.options[0] || { max: DEFAULT_MAX };
 
   if (dependencies.size > max) {
     context.report(
       lastNode,
       `Maximum number of dependencies (${max}) exceeded.`
-    )
+    );
   }
-}
+};
 
 module.exports = {
   meta: {
@@ -33,26 +33,26 @@ module.exports = {
   },
 
   create: context => {
-    const dependencies = new Set() // keep track of dependencies
-    let lastNode // keep track of the last node to report on
+    const dependencies = new Set(); // keep track of dependencies
+    let lastNode; // keep track of the last node to report on
 
     return {
       ImportDeclaration(node) {
-        dependencies.add(node.source.value)
-        lastNode = node.source
+        dependencies.add(node.source.value);
+        lastNode = node.source;
       },
 
       CallExpression(node) {
         if (isStaticRequire(node)) {
-          const [ requirePath ] = node.arguments
-          dependencies.add(requirePath.value)
-          lastNode = node
+          const [ requirePath ] = node.arguments;
+          dependencies.add(requirePath.value);
+          lastNode = node;
         }
       },
 
       'Program:exit': function () {
-        countDependencies(dependencies, lastNode, context)
+        countDependencies(dependencies, lastNode, context);
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/named.js b/src/rules/named.js
index 6853229b45..b1c2699c1a 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -1,6 +1,6 @@
-import * as path from 'path'
-import Exports from '../ExportMap'
-import docsUrl from '../docsUrl'
+import * as path from 'path';
+import Exports from '../ExportMap';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -16,44 +16,44 @@ module.exports = {
       // ignore local exports and type imports/exports
       if (node.source == null || node.importKind === 'type' ||
           node.importKind === 'typeof'  || node.exportKind === 'type') {
-        return
+        return;
       }
 
       if (!node.specifiers
-            .some(function (im) { return im.type === type })) {
-        return // no named imports/exports
+            .some(function (im) { return im.type === type; })) {
+        return; // no named imports/exports
       }
 
-      const imports = Exports.get(node.source.value, context)
-      if (imports == null) return
+      const imports = Exports.get(node.source.value, context);
+      if (imports == null) return;
 
       if (imports.errors.length) {
-        imports.reportErrors(context, node)
-        return
+        imports.reportErrors(context, node);
+        return;
       }
 
       node.specifiers.forEach(function (im) {
-        if (im.type !== type) return
+        if (im.type !== type) return;
 
         // ignore type imports
-        if (im.importKind === 'type' || im.importKind === 'typeof') return
+        if (im.importKind === 'type' || im.importKind === 'typeof') return;
 
-        const deepLookup = imports.hasDeep(im[key].name)
+        const deepLookup = imports.hasDeep(im[key].name);
 
         if (!deepLookup.found) {
           if (deepLookup.path.length > 1) {
             const deepPath = deepLookup.path
               .map(i => path.relative(path.dirname(context.getFilename()), i.path))
-              .join(' -> ')
+              .join(' -> ');
 
             context.report(im[key],
-              `${im[key].name} not found via ${deepPath}`)
+              `${im[key].name} not found via ${deepPath}`);
           } else {
             context.report(im[key],
-              im[key].name + ' not found in \'' + node.source.value + '\'')
+              im[key].name + ' not found in \'' + node.source.value + '\'');
           }
         }
-      })
+      });
     }
 
     return {
@@ -66,7 +66,7 @@ module.exports = {
                                                     , 'local'
                                                     , 'ExportSpecifier'
                                                     ),
-    }
+    };
 
   },
-}
+};
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 90784c076e..6d0c367e77 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -1,7 +1,7 @@
-import declaredScope from 'eslint-module-utils/declaredScope'
-import Exports from '../ExportMap'
-import importDeclaration from '../importDeclaration'
-import docsUrl from '../docsUrl'
+import declaredScope from 'eslint-module-utils/declaredScope';
+import Exports from '../ExportMap';
+import importDeclaration from '../importDeclaration';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -30,28 +30,28 @@ module.exports = {
     // read options
     const {
       allowComputed = false,
-    } = context.options[0] || {}
+    } = context.options[0] || {};
 
-    const namespaces = new Map()
+    const namespaces = new Map();
 
     function makeMessage(last, namepath) {
-      return `'${last.name}' not found in ${namepath.length > 1 ? 'deeply ' : ''}imported namespace '${namepath.join('.')}'.`
+      return `'${last.name}' not found in ${namepath.length > 1 ? 'deeply ' : ''}imported namespace '${namepath.join('.')}'.`;
     }
 
     return {
       // pick up all imports at body entry time, to properly respect hoisting
       Program({ body }) {
         function processBodyStatement(declaration) {
-          if (declaration.type !== 'ImportDeclaration') return
+          if (declaration.type !== 'ImportDeclaration') return;
 
-          if (declaration.specifiers.length === 0) return
+          if (declaration.specifiers.length === 0) return;
 
-          const imports = Exports.get(declaration.source.value, context)
-          if (imports == null) return null
+          const imports = Exports.get(declaration.source.value, context);
+          if (imports == null) return null;
 
           if (imports.errors.length) {
-            imports.reportErrors(context, declaration)
-            return
+            imports.reportErrors(context, declaration);
+            return;
           }
 
           for (const specifier of declaration.specifiers) {
@@ -61,63 +61,63 @@ module.exports = {
                   context.report(
                     specifier,
                     `No exported names found in module '${declaration.source.value}'.`
-                  )
+                  );
                 }
-                namespaces.set(specifier.local.name, imports)
-                break
+                namespaces.set(specifier.local.name, imports);
+                break;
               case 'ImportDefaultSpecifier':
               case 'ImportSpecifier': {
                 const meta = imports.get(
                   // default to 'default' for default http://i.imgur.com/nj6qAWy.jpg
                   specifier.imported ? specifier.imported.name : 'default'
-                )
-                if (!meta || !meta.namespace) { break }
-                namespaces.set(specifier.local.name, meta.namespace)
-                break
+                );
+                if (!meta || !meta.namespace) { break; }
+                namespaces.set(specifier.local.name, meta.namespace);
+                break;
               }
             }
           }
         }
-        body.forEach(processBodyStatement)
+        body.forEach(processBodyStatement);
       },
 
       // same as above, but does not add names to local map
       ExportNamespaceSpecifier(namespace) {
-        var declaration = importDeclaration(context)
+        var declaration = importDeclaration(context);
 
-        var imports = Exports.get(declaration.source.value, context)
-        if (imports == null) return null
+        var imports = Exports.get(declaration.source.value, context);
+        if (imports == null) return null;
 
         if (imports.errors.length) {
-          imports.reportErrors(context, declaration)
-          return
+          imports.reportErrors(context, declaration);
+          return;
         }
 
         if (!imports.size) {
           context.report(
             namespace,
             `No exported names found in module '${declaration.source.value}'.`
-          )
+          );
         }
       },
 
       // todo: check for possible redefinition
 
       MemberExpression(dereference) {
-        if (dereference.object.type !== 'Identifier') return
-        if (!namespaces.has(dereference.object.name)) return
-        if (declaredScope(context, dereference.object.name) !== 'module') return
+        if (dereference.object.type !== 'Identifier') return;
+        if (!namespaces.has(dereference.object.name)) return;
+        if (declaredScope(context, dereference.object.name) !== 'module') return;
 
         if (dereference.parent.type === 'AssignmentExpression' && dereference.parent.left === dereference) {
             context.report(
               dereference.parent,
               `Assignment to member of namespace '${dereference.object.name}'.`
-            )
+            );
         }
 
         // go deep
-        var namespace = namespaces.get(dereference.object.name)
-        var namepath = [dereference.object.name]
+        var namespace = namespaces.get(dereference.object.name);
+        var namepath = [dereference.object.name];
         // while property is namespace and parent is member expression, keep validating
         while (namespace instanceof Exports && dereference.type === 'MemberExpression') {
 
@@ -126,43 +126,43 @@ module.exports = {
               context.report(
                 dereference.property,
                 `Unable to validate computed reference to imported namespace '${dereference.object.name}'.`
-              )
+              );
             }
-            return
+            return;
           }
 
           if (!namespace.has(dereference.property.name)) {
             context.report(
               dereference.property,
               makeMessage(dereference.property, namepath)
-            )
-            break
+            );
+            break;
           }
 
-          const exported = namespace.get(dereference.property.name)
-          if (exported == null) return
+          const exported = namespace.get(dereference.property.name);
+          if (exported == null) return;
 
           // stash and pop
-          namepath.push(dereference.property.name)
-          namespace = exported.namespace
-          dereference = dereference.parent
+          namepath.push(dereference.property.name);
+          namespace = exported.namespace;
+          dereference = dereference.parent;
         }
 
       },
 
       VariableDeclarator({ id, init }) {
-        if (init == null) return
-        if (init.type !== 'Identifier') return
-        if (!namespaces.has(init.name)) return
+        if (init == null) return;
+        if (init.type !== 'Identifier') return;
+        if (!namespaces.has(init.name)) return;
 
         // check for redefinition in intermediate scopes
-        if (declaredScope(context, init.name) !== 'module') return
+        if (declaredScope(context, init.name) !== 'module') return;
 
         // DFS traverse child namespaces
         function testKey(pattern, namespace, path = [init.name]) {
-          if (!(namespace instanceof Exports)) return
+          if (!(namespace instanceof Exports)) return;
 
-          if (pattern.type !== 'ObjectPattern') return
+          if (pattern.type !== 'ObjectPattern') return;
 
           for (const property of pattern.properties) {
             if (
@@ -170,48 +170,48 @@ module.exports = {
               || property.type === 'RestElement'
               || !property.key
             ) {
-              continue
+              continue;
             }
 
             if (property.key.type !== 'Identifier') {
               context.report({
                 node: property,
                 message: 'Only destructure top-level names.',
-              })
-              continue
+              });
+              continue;
             }
 
             if (!namespace.has(property.key.name)) {
               context.report({
                 node: property,
                 message: makeMessage(property.key, path),
-              })
-              continue
+              });
+              continue;
             }
 
-            path.push(property.key.name)
-            const dependencyExportMap = namespace.get(property.key.name)
+            path.push(property.key.name);
+            const dependencyExportMap = namespace.get(property.key.name);
             // could be null when ignored or ambiguous
             if (dependencyExportMap !== null) {
-              testKey(property.value, dependencyExportMap.namespace, path)
+              testKey(property.value, dependencyExportMap.namespace, path);
             }
-            path.pop()
+            path.pop();
           }
         }
 
-        testKey(id, namespaces.get(init.name))
+        testKey(id, namespaces.get(init.name));
       },
 
       JSXMemberExpression({object, property}) {
-         if (!namespaces.has(object.name)) return
-         var namespace = namespaces.get(object.name)
+         if (!namespaces.has(object.name)) return;
+         var namespace = namespaces.get(object.name);
          if (!namespace.has(property.name)) {
            context.report({
              node: property,
              message: makeMessage(property, [object.name]),
-           })
+           });
          }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 0336b0dc25..c1fc363b1a 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -3,48 +3,48 @@
  * @author Radek Benkel
  */
 
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
 
-import debug from 'debug'
-const log = debug('eslint-plugin-import:rules:newline-after-import')
+import debug from 'debug';
+const log = debug('eslint-plugin-import:rules:newline-after-import');
 
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
 
 function containsNodeOrEqual(outerNode, innerNode) {
-    return outerNode.range[0] <= innerNode.range[0] && outerNode.range[1] >= innerNode.range[1]
+    return outerNode.range[0] <= innerNode.range[0] && outerNode.range[1] >= innerNode.range[1];
 }
 
 function getScopeBody(scope) {
     if (scope.block.type === 'SwitchStatement') {
-      log('SwitchStatement scopes not supported')
-      return null
+      log('SwitchStatement scopes not supported');
+      return null;
     }
 
-    const { body } = scope.block
+    const { body } = scope.block;
     if (body && body.type === 'BlockStatement') {
-        return body.body
+        return body.body;
     }
 
-    return body
+    return body;
 }
 
 function findNodeIndexInScopeBody(body, nodeToFind) {
-    return body.findIndex((node) => containsNodeOrEqual(node, nodeToFind))
+    return body.findIndex((node) => containsNodeOrEqual(node, nodeToFind));
 }
 
 function getLineDifference(node, nextNode) {
-  return nextNode.loc.start.line - node.loc.end.line
+  return nextNode.loc.start.line - node.loc.end.line;
 }
 
 function isClassWithDecorator(node) {
-  return node.type === 'ClassDeclaration' && node.decorators && node.decorators.length
+  return node.type === 'ClassDeclaration' && node.decorators && node.decorators.length;
 }
 
 function isExportDefaultClass(node) {
-  return node.type === 'ExportDefaultDeclaration' && node.declaration.type === 'ClassDeclaration'
+  return node.type === 'ExportDefaultDeclaration' && node.declaration.type === 'ClassDeclaration';
 }
 
 module.exports = {
@@ -68,29 +68,29 @@ module.exports = {
     ],
   },
   create: function (context) {
-    let level = 0
-    const requireCalls = []
+    let level = 0;
+    const requireCalls = [];
 
     function checkForNewLine(node, nextNode, type) {
       if (isExportDefaultClass(nextNode)) {
-        let classNode = nextNode.declaration
+        let classNode = nextNode.declaration;
 
         if (isClassWithDecorator(classNode)) {
-          nextNode = classNode.decorators[0]
+          nextNode = classNode.decorators[0];
         }
       } else if (isClassWithDecorator(nextNode)) {
-        nextNode = nextNode.decorators[0]
+        nextNode = nextNode.decorators[0];
       }
 
-      const options = context.options[0] || { count: 1 }
-      const lineDifference = getLineDifference(node, nextNode)
-      const EXPECTED_LINE_DIFFERENCE = options.count + 1
+      const options = context.options[0] || { count: 1 };
+      const lineDifference = getLineDifference(node, nextNode);
+      const EXPECTED_LINE_DIFFERENCE = options.count + 1;
 
       if (lineDifference < EXPECTED_LINE_DIFFERENCE) {
-        let column = node.loc.start.column
+        let column = node.loc.start.column;
 
         if (node.loc.start.line !== node.loc.end.line) {
-          column = 0
+          column = 0;
         }
 
         context.report({
@@ -104,29 +104,29 @@ after ${type} statement not followed by another ${type}.`,
             node,
             '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference)
           ),
-        })
+        });
       }
     }
 
     function incrementLevel() {
-      level++
+      level++;
     }
     function decrementLevel() {
-      level--
+      level--;
     }
 
     function checkImport(node) {
-        const { parent } = node
-        const nodePosition = parent.body.indexOf(node)
-        const nextNode = parent.body[nodePosition + 1]
+        const { parent } = node;
+        const nodePosition = parent.body.indexOf(node);
+        const nextNode = parent.body[nodePosition + 1];
         
         // skip "export import"s
         if (node.type === 'TSImportEqualsDeclaration' && node.isExport) {
-          return
+          return;
         }
 
         if (nextNode && nextNode.type !== 'ImportDeclaration' && (nextNode.type !== 'TSImportEqualsDeclaration' || nextNode.isExport)) {
-          checkForNewLine(node, nextNode, 'import')
+          checkForNewLine(node, nextNode, 'import');
         }
     }
 
@@ -135,32 +135,32 @@ after ${type} statement not followed by another ${type}.`,
       TSImportEqualsDeclaration: checkImport,
       CallExpression: function(node) {
         if (isStaticRequire(node) && level === 0) {
-          requireCalls.push(node)
+          requireCalls.push(node);
         }
       },
       'Program:exit': function () {
-        log('exit processing for', context.getFilename())
-        const scopeBody = getScopeBody(context.getScope())
-        log('got scope:', scopeBody)
+        log('exit processing for', context.getFilename());
+        const scopeBody = getScopeBody(context.getScope());
+        log('got scope:', scopeBody);
 
         requireCalls.forEach(function (node, index) {
-          const nodePosition = findNodeIndexInScopeBody(scopeBody, node)
-          log('node position in scope:', nodePosition)
+          const nodePosition = findNodeIndexInScopeBody(scopeBody, node);
+          log('node position in scope:', nodePosition);
 
-          const statementWithRequireCall = scopeBody[nodePosition]
-          const nextStatement = scopeBody[nodePosition + 1]
-          const nextRequireCall = requireCalls[index + 1]
+          const statementWithRequireCall = scopeBody[nodePosition];
+          const nextStatement = scopeBody[nodePosition + 1];
+          const nextRequireCall = requireCalls[index + 1];
 
           if (nextRequireCall && containsNodeOrEqual(statementWithRequireCall, nextRequireCall)) {
-            return
+            return;
           }
 
           if (nextStatement &&
              (!nextRequireCall || !containsNodeOrEqual(nextStatement, nextRequireCall))) {
 
-            checkForNewLine(statementWithRequireCall, nextStatement, 'require')
+            checkForNewLine(statementWithRequireCall, nextStatement, 'require');
           }
-        })
+        });
       },
       FunctionDeclaration: incrementLevel,
       FunctionExpression: incrementLevel,
@@ -174,6 +174,6 @@ after ${type} statement not followed by another ${type}.`,
       'BlockStatement:exit': decrementLevel,
       'ObjectExpression:exit': decrementLevel,
       'Decorator:exit': decrementLevel,
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index 2cc0f6ae0f..cc81c5c4be 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -1,6 +1,6 @@
-import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor'
-import { isAbsolute } from '../core/importType'
-import docsUrl from '../docsUrl'
+import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
+import { isAbsolute } from '../core/importType';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -14,11 +14,11 @@ module.exports = {
   create: function (context) {
     function reportIfAbsolute(source) {
       if (typeof source.value === 'string' && isAbsolute(source.value)) {
-        context.report(source, 'Do not import modules using an absolute path')
+        context.report(source, 'Do not import modules using an absolute path');
       }
     }
 
-    const options = Object.assign({ esmodule: true, commonjs: true }, context.options[0])
-    return moduleVisitor(reportIfAbsolute, options)
+    const options = Object.assign({ esmodule: true, commonjs: true }, context.options[0]);
+    return moduleVisitor(reportIfAbsolute, options);
   },
-}
+};
diff --git a/src/rules/no-amd.js b/src/rules/no-amd.js
index a6a460bcf8..7a0771bd57 100644
--- a/src/rules/no-amd.js
+++ b/src/rules/no-amd.js
@@ -3,7 +3,7 @@
  * @author Jamund Ferguson
  */
 
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 //------------------------------------------------------------------------------
 // Rule Definition
@@ -21,23 +21,23 @@ module.exports = {
   create: function (context) {
     return {
       'CallExpression': function (node) {
-        if (context.getScope().type !== 'module') return
+        if (context.getScope().type !== 'module') return;
 
-        if (node.callee.type !== 'Identifier') return
+        if (node.callee.type !== 'Identifier') return;
         if (node.callee.name !== 'require' &&
-            node.callee.name !== 'define') return
+            node.callee.name !== 'define') return;
 
         // todo: capture define((require, module, exports) => {}) form?
-        if (node.arguments.length !== 2) return
+        if (node.arguments.length !== 2) return;
 
-        const modules = node.arguments[0]
-        if (modules.type !== 'ArrayExpression') return
+        const modules = node.arguments[0];
+        if (modules.type !== 'ArrayExpression') return;
 
         // todo: check second arg type? (identifier or callback)
 
-        context.report(node, `Expected imports instead of AMD ${node.callee.name}().`)
+        context.report(node, `Expected imports instead of AMD ${node.callee.name}().`);
       },
-    }
+    };
 
   },
-}
+};
diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js
index 1557404507..8ea3365861 100644
--- a/src/rules/no-anonymous-default-export.js
+++ b/src/rules/no-anonymous-default-export.js
@@ -3,8 +3,8 @@
  * @author Duncan Beevers
  */
 
-import docsUrl from '../docsUrl'
-import has from 'has'
+import docsUrl from '../docsUrl';
+import has from 'has';
 
 const defs = {
   ArrayExpression: {
@@ -50,7 +50,7 @@ const defs = {
     description: 'If `false`, will report default export of a literal',
     message: 'Assign literal to a variable before exporting as module default',
   },
-}
+};
 
 const schemaProperties = Object.keys(defs)
   .map((key) => defs[key])
@@ -58,17 +58,17 @@ const schemaProperties = Object.keys(defs)
     acc[def.option] = {
       description: def.description,
       type: 'boolean',
-    }
+    };
 
-    return acc
-  }, {})
+    return acc;
+  }, {});
 
 const defaults = Object.keys(defs)
   .map((key) => defs[key])
   .reduce((acc, def) => {
-    acc[def.option] = has(def, 'default') ? def.default : false
-    return acc
-  }, {})
+    acc[def.option] = has(def, 'default') ? def.default : false;
+    return acc;
+  }, {});
 
 module.exports = {
   meta: {
@@ -87,18 +87,18 @@ module.exports = {
   },
 
   create: function (context) {
-    const options = Object.assign({}, defaults, context.options[0])
+    const options = Object.assign({}, defaults, context.options[0]);
 
     return {
       'ExportDefaultDeclaration': (node) => {
-        const def = defs[node.declaration.type]
+        const def = defs[node.declaration.type];
 
         // Recognized node type and allowed by configuration,
         //   and has no forbid check, or forbid check return value is truthy
         if (def && !options[def.option] && (!def.forbid || def.forbid(node))) {
-          context.report({ node, message: def.message })
+          context.report({ node, message: def.message });
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index 456f030f42..7c40f47cb6 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -3,34 +3,34 @@
  * @author Jamund Ferguson
  */
 
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 const EXPORT_MESSAGE = 'Expected "export" or "export default"'
-    , IMPORT_MESSAGE = 'Expected "import" instead of "require()"'
+    , IMPORT_MESSAGE = 'Expected "import" instead of "require()"';
 
 function normalizeLegacyOptions(options) {
   if (options.indexOf('allow-primitive-modules') >= 0) {
-    return { allowPrimitiveModules: true }
+    return { allowPrimitiveModules: true };
   }
-  return options[0] || {}
+  return options[0] || {};
 }
 
 function allowPrimitive(node, options) {
-  if (!options.allowPrimitiveModules) return false
-  if (node.parent.type !== 'AssignmentExpression') return false
-  return (node.parent.right.type !== 'ObjectExpression')
+  if (!options.allowPrimitiveModules) return false;
+  if (node.parent.type !== 'AssignmentExpression') return false;
+  return (node.parent.right.type !== 'ObjectExpression');
 }
 
 function allowRequire(node, options) {
-  return options.allowRequire
+  return options.allowRequire;
 }
 
 function allowConditionalRequire(node, options) {
-  return options.allowConditionalRequire !== false
+  return options.allowConditionalRequire !== false;
 }
 
 function validateScope(scope) {
-  return scope.variableScope.type === 'module'
+  return scope.variableScope.type === 'module';
 }
 
 // https://github.com/estree/estree/blob/master/es5.md
@@ -40,16 +40,16 @@ function isConditional(node) {
     || node.type === 'TryStatement'
     || node.type === 'LogicalExpression'
     || node.type === 'ConditionalExpression'
-  ) return true
-  if (node.parent) return isConditional(node.parent)
-  return false
+  ) return true;
+  if (node.parent) return isConditional(node.parent);
+  return false;
 }
 
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
 
-const schemaString = { enum: ['allow-primitive-modules'] }
+const schemaString = { enum: ['allow-primitive-modules'] };
 const schemaObject = {
   type: 'object',
   properties: {
@@ -58,7 +58,7 @@ const schemaObject = {
     allowConditionalRequire: { 'type': 'boolean' },
   },
   additionalProperties: false,
-}
+};
 
 module.exports = {
   meta: {
@@ -84,7 +84,7 @@ module.exports = {
   },
 
   create: function (context) {
-    const options = normalizeLegacyOptions(context.options)
+    const options = normalizeLegacyOptions(context.options);
 
     return {
 
@@ -92,44 +92,44 @@ module.exports = {
 
         // module.exports
         if (node.object.name === 'module' && node.property.name === 'exports') {
-          if (allowPrimitive(node, options)) return
-          context.report({ node, message: EXPORT_MESSAGE })
+          if (allowPrimitive(node, options)) return;
+          context.report({ node, message: EXPORT_MESSAGE });
         }
 
         // exports.
         if (node.object.name === 'exports') {
           const isInScope = context.getScope()
             .variables
-            .some(variable => variable.name === 'exports')
+            .some(variable => variable.name === 'exports');
           if (! isInScope) {
-            context.report({ node, message: EXPORT_MESSAGE })
+            context.report({ node, message: EXPORT_MESSAGE });
           }
         }
 
       },
       'CallExpression': function (call) {
-        if (!validateScope(context.getScope())) return
+        if (!validateScope(context.getScope())) return;
 
-        if (call.callee.type !== 'Identifier') return
-        if (call.callee.name !== 'require') return
+        if (call.callee.type !== 'Identifier') return;
+        if (call.callee.name !== 'require') return;
 
-        if (call.arguments.length !== 1) return
-        var module = call.arguments[0]
+        if (call.arguments.length !== 1) return;
+        var module = call.arguments[0];
 
-        if (module.type !== 'Literal') return
-        if (typeof module.value !== 'string') return
+        if (module.type !== 'Literal') return;
+        if (typeof module.value !== 'string') return;
 
-        if (allowRequire(call, options)) return
+        if (allowRequire(call, options)) return;
 
-        if (allowConditionalRequire(call, options) && isConditional(call.parent)) return
+        if (allowConditionalRequire(call, options) && isConditional(call.parent)) return;
 
         // keeping it simple: all 1-string-arg `require` calls are reported
         context.report({
           node: call.callee,
           message: IMPORT_MESSAGE,
-        })
+        });
       },
-    }
+    };
 
   },
-}
+};
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 2ad381e91a..5c11e26259 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -3,10 +3,10 @@
  * @author Ben Mosher
  */
 
-import Exports from '../ExportMap'
-import { isExternalModule } from '../core/importType'
-import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor'
-import docsUrl from '../docsUrl'
+import Exports from '../ExportMap';
+import { isExternalModule } from '../core/importType';
+import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
+import docsUrl from '../docsUrl';
 
 // todo: cache cycles / deep relationships for faster repeat evaluation
 module.exports = {
@@ -36,69 +36,69 @@ module.exports = {
   },
 
   create: function (context) {
-    const myPath = context.getFilename()
-    if (myPath === '<text>') return {} // can't cycle-check a non-file
+    const myPath = context.getFilename();
+    if (myPath === '<text>') return {}; // can't cycle-check a non-file
 
-    const options = context.options[0] || {}
-    const maxDepth = typeof options.maxDepth === 'number' ? options.maxDepth : Infinity
-    const ignoreModule = (name) => options.ignoreExternal ? isExternalModule(name) : false
+    const options = context.options[0] || {};
+    const maxDepth = typeof options.maxDepth === 'number' ? options.maxDepth : Infinity;
+    const ignoreModule = (name) => options.ignoreExternal ? isExternalModule(name) : false;
 
     function checkSourceValue(sourceNode, importer) {
       if (ignoreModule(sourceNode.value)) {
-        return // ignore external modules
+        return; // ignore external modules
       }
 
-      const imported = Exports.get(sourceNode.value, context)
+      const imported = Exports.get(sourceNode.value, context);
 
       if (importer.importKind === 'type') {
-        return // no Flow import resolution
+        return; // no Flow import resolution
       }
 
       if (imported == null) {
-        return  // no-unresolved territory
+        return;  // no-unresolved territory
       }
 
       if (imported.path === myPath) {
-        return  // no-self-import territory
+        return;  // no-self-import territory
       }
 
-      const untraversed = [{mget: () => imported, route:[]}]
-      const traversed = new Set()
+      const untraversed = [{mget: () => imported, route:[]}];
+      const traversed = new Set();
       function detectCycle({mget, route}) {
-        const m = mget()
-        if (m == null) return
-        if (traversed.has(m.path)) return
-        traversed.add(m.path)
+        const m = mget();
+        if (m == null) return;
+        if (traversed.has(m.path)) return;
+        traversed.add(m.path);
 
         for (let [path, { getter, source }] of m.imports) {
-          if (path === myPath) return true
-          if (traversed.has(path)) continue
-          if (ignoreModule(source.value)) continue
+          if (path === myPath) return true;
+          if (traversed.has(path)) continue;
+          if (ignoreModule(source.value)) continue;
           if (route.length + 1 < maxDepth) {
             untraversed.push({
               mget: getter,
               route: route.concat(source),
-            })
+            });
           }
         }
       }
 
       while (untraversed.length > 0) {
-        const next = untraversed.shift() // bfs!
+        const next = untraversed.shift(); // bfs!
         if (detectCycle(next)) {
           const message = (next.route.length > 0
             ? `Dependency cycle via ${routeString(next.route)}`
-            : 'Dependency cycle detected.')
-          context.report(importer, message)
-          return
+            : 'Dependency cycle detected.');
+          context.report(importer, message);
+          return;
         }
       }
     }
 
-    return moduleVisitor(checkSourceValue, context.options[0])
+    return moduleVisitor(checkSourceValue, context.options[0]);
   },
-}
+};
 
 function routeString(route) {
-  return route.map(s => `${s.value}:${s.loc.start.line}`).join('=>')
+  return route.map(s => `${s.value}:${s.loc.start.line}`).join('=>');
 }
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index fdc709696d..b597c320f6 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -1,4 +1,4 @@
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -12,30 +12,30 @@ module.exports = {
   create(context) {
     // ignore non-modules
     if (context.parserOptions.sourceType !== 'module') {
-      return {}
+      return {};
     }
 
-    const preferNamed = 'Prefer named exports.'
+    const preferNamed = 'Prefer named exports.';
     const noAliasDefault = ({local}) =>
       `Do not alias \`${local.name}\` as \`default\`. Just export ` +
-      `\`${local.name}\` itself instead.`
+      `\`${local.name}\` itself instead.`;
 
     return {
       ExportDefaultDeclaration(node) {
-        context.report({node, message: preferNamed})
+        context.report({node, message: preferNamed});
       },
 
       ExportNamedDeclaration(node) {
         node.specifiers.forEach(specifier => {
           if (specifier.type === 'ExportDefaultSpecifier' &&
               specifier.exported.name === 'default') {
-            context.report({node, message: preferNamed})
+            context.report({node, message: preferNamed});
           } else if (specifier.type === 'ExportSpecifier' &&
               specifier.exported.name === 'default') {
-            context.report({node, message: noAliasDefault(specifier)})
+            context.report({node, message: noAliasDefault(specifier)});
           }
-        })
+        });
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index fc01d9dd10..38c0253c5d 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -1,17 +1,17 @@
-import declaredScope from 'eslint-module-utils/declaredScope'
-import Exports from '../ExportMap'
-import docsUrl from '../docsUrl'
+import declaredScope from 'eslint-module-utils/declaredScope';
+import Exports from '../ExportMap';
+import docsUrl from '../docsUrl';
 
 function message(deprecation) {
-  return 'Deprecated' + (deprecation.description ? ': ' + deprecation.description : '.')
+  return 'Deprecated' + (deprecation.description ? ': ' + deprecation.description : '.');
 }
 
 function getDeprecation(metadata) {
-  if (!metadata || !metadata.doc) return
+  if (!metadata || !metadata.doc) return;
 
-  let deprecation
+  let deprecation;
   if (metadata.doc.tags.some(t => t.title === 'deprecated' && (deprecation = t))) {
-    return deprecation
+    return deprecation;
   }
 }
 
@@ -26,65 +26,65 @@ module.exports = {
 
   create: function (context) {
     const deprecated = new Map()
-        , namespaces = new Map()
+        , namespaces = new Map();
 
     function checkSpecifiers(node) {
-      if (node.type !== 'ImportDeclaration') return
-      if (node.source == null) return // local export, ignore
+      if (node.type !== 'ImportDeclaration') return;
+      if (node.source == null) return; // local export, ignore
 
-      const imports = Exports.get(node.source.value, context)
-      if (imports == null) return
+      const imports = Exports.get(node.source.value, context);
+      if (imports == null) return;
 
-      let moduleDeprecation
+      let moduleDeprecation;
       if (imports.doc &&
           imports.doc.tags.some(t => t.title === 'deprecated' && (moduleDeprecation = t))) {
-        context.report({ node, message: message(moduleDeprecation) })
+        context.report({ node, message: message(moduleDeprecation) });
       }
 
       if (imports.errors.length) {
-        imports.reportErrors(context, node)
-        return
+        imports.reportErrors(context, node);
+        return;
       }
 
       node.specifiers.forEach(function (im) {
-        let imported, local
+        let imported, local;
         switch (im.type) {
 
 
           case 'ImportNamespaceSpecifier':{
-            if (!imports.size) return
-            namespaces.set(im.local.name, imports)
-            return
+            if (!imports.size) return;
+            namespaces.set(im.local.name, imports);
+            return;
           }
 
           case 'ImportDefaultSpecifier':
-            imported = 'default'
-            local = im.local.name
-            break
+            imported = 'default';
+            local = im.local.name;
+            break;
 
           case 'ImportSpecifier':
-            imported = im.imported.name
-            local = im.local.name
-            break
+            imported = im.imported.name;
+            local = im.local.name;
+            break;
 
-          default: return // can't handle this one
+          default: return; // can't handle this one
         }
 
         // unknown thing can't be deprecated
-        const exported = imports.get(imported)
-        if (exported == null) return
+        const exported = imports.get(imported);
+        if (exported == null) return;
 
         // capture import of deep namespace
-        if (exported.namespace) namespaces.set(local, exported.namespace)
+        if (exported.namespace) namespaces.set(local, exported.namespace);
 
-        const deprecation = getDeprecation(imports.get(imported))
-        if (!deprecation) return
+        const deprecation = getDeprecation(imports.get(imported));
+        if (!deprecation) return;
 
-        context.report({ node: im, message: message(deprecation) })
+        context.report({ node: im, message: message(deprecation) });
 
-        deprecated.set(local, deprecation)
+        deprecated.set(local, deprecation);
 
-      })
+      });
     }
 
     return {
@@ -92,52 +92,52 @@ module.exports = {
 
       'Identifier': function (node) {
         if (node.parent.type === 'MemberExpression' && node.parent.property === node) {
-          return // handled by MemberExpression
+          return; // handled by MemberExpression
         }
 
         // ignore specifier identifiers
-        if (node.parent.type.slice(0, 6) === 'Import') return
+        if (node.parent.type.slice(0, 6) === 'Import') return;
 
-        if (!deprecated.has(node.name)) return
+        if (!deprecated.has(node.name)) return;
 
-        if (declaredScope(context, node.name) !== 'module') return
+        if (declaredScope(context, node.name) !== 'module') return;
         context.report({
           node,
           message: message(deprecated.get(node.name)),
-        })
+        });
       },
 
       'MemberExpression': function (dereference) {
-        if (dereference.object.type !== 'Identifier') return
-        if (!namespaces.has(dereference.object.name)) return
+        if (dereference.object.type !== 'Identifier') return;
+        if (!namespaces.has(dereference.object.name)) return;
 
-        if (declaredScope(context, dereference.object.name) !== 'module') return
+        if (declaredScope(context, dereference.object.name) !== 'module') return;
 
         // go deep
-        var namespace = namespaces.get(dereference.object.name)
-        var namepath = [dereference.object.name]
+        var namespace = namespaces.get(dereference.object.name);
+        var namepath = [dereference.object.name];
         // while property is namespace and parent is member expression, keep validating
         while (namespace instanceof Exports &&
                dereference.type === 'MemberExpression') {
 
           // ignore computed parts for now
-          if (dereference.computed) return
+          if (dereference.computed) return;
 
-          const metadata = namespace.get(dereference.property.name)
+          const metadata = namespace.get(dereference.property.name);
 
-          if (!metadata) break
-          const deprecation = getDeprecation(metadata)
+          if (!metadata) break;
+          const deprecation = getDeprecation(metadata);
 
           if (deprecation) {
-            context.report({ node: dereference.property, message: message(deprecation) })
+            context.report({ node: dereference.property, message: message(deprecation) });
           }
 
           // stash and pop
-          namepath.push(dereference.property.name)
-          namespace = metadata.namespace
-          dereference = dereference.parent
+          namepath.push(dereference.property.name);
+          namespace = metadata.namespace;
+          dereference = dereference.parent;
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index ce586cd674..1bf6f38245 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -1,25 +1,25 @@
-import resolve from 'eslint-module-utils/resolve'
-import docsUrl from '../docsUrl'
+import resolve from 'eslint-module-utils/resolve';
+import docsUrl from '../docsUrl';
 
 function checkImports(imported, context) {
   for (const [module, nodes] of imported.entries()) {
     if (nodes.length > 1) {
-      const message = `'${module}' imported multiple times.`
-      const [first, ...rest] = nodes
-      const sourceCode = context.getSourceCode()
-      const fix = getFix(first, rest, sourceCode)
+      const message = `'${module}' imported multiple times.`;
+      const [first, ...rest] = nodes;
+      const sourceCode = context.getSourceCode();
+      const fix = getFix(first, rest, sourceCode);
 
       context.report({
         node: first.source,
         message,
         fix, // Attach the autofix (if any) to the first import.
-      })
+      });
 
       for (const node of rest) {
         context.report({
           node: node.source,
           message,
-        })
+        });
       }
     }
   }
@@ -33,7 +33,7 @@ function getFix(first, rest, sourceCode) {
   // `sourceCode.getCommentsBefore` was added in 4.0, so that's an easy thing to
   // check for.
   if (typeof sourceCode.getCommentsBefore !== 'function') {
-    return undefined
+    return undefined;
   }
 
   // Adjusting the first import might make it multiline, which could break
@@ -41,17 +41,17 @@ function getFix(first, rest, sourceCode) {
   // import has comments. Also, if the first import is `import * as ns from
   // './foo'` there's nothing we can do.
   if (hasProblematicComments(first, sourceCode) || hasNamespace(first)) {
-    return undefined
+    return undefined;
   }
 
   const defaultImportNames = new Set(
     [first, ...rest].map(getDefaultImportName).filter(Boolean)
-  )
+  );
 
   // Bail if there are multiple different default import names – it's up to the
   // user to choose which one to keep.
   if (defaultImportNames.size > 1) {
-    return undefined
+    return undefined;
   }
 
   // Leave it to the user to handle comments. Also skip `import * as ns from
@@ -59,16 +59,16 @@ function getFix(first, rest, sourceCode) {
   const restWithoutComments = rest.filter(node => !(
     hasProblematicComments(node, sourceCode) ||
     hasNamespace(node)
-  ))
+  ));
 
   const specifiers = restWithoutComments
     .map(node => {
-      const tokens = sourceCode.getTokens(node)
-      const openBrace = tokens.find(token => isPunctuator(token, '{'))
-      const closeBrace = tokens.find(token => isPunctuator(token, '}'))
+      const tokens = sourceCode.getTokens(node);
+      const openBrace = tokens.find(token => isPunctuator(token, '{'));
+      const closeBrace = tokens.find(token => isPunctuator(token, '}'));
 
       if (openBrace == null || closeBrace == null) {
-        return undefined
+        return undefined;
       }
 
       return {
@@ -76,35 +76,35 @@ function getFix(first, rest, sourceCode) {
         text: sourceCode.text.slice(openBrace.range[1], closeBrace.range[0]),
         hasTrailingComma: isPunctuator(sourceCode.getTokenBefore(closeBrace), ','),
         isEmpty: !hasSpecifiers(node),
-      }
+      };
     })
-    .filter(Boolean)
+    .filter(Boolean);
 
   const unnecessaryImports = restWithoutComments.filter(node =>
     !hasSpecifiers(node) &&
     !hasNamespace(node) &&
     !specifiers.some(specifier => specifier.importNode === node)
-  )
+  );
 
-  const shouldAddDefault = getDefaultImportName(first) == null && defaultImportNames.size === 1
-  const shouldAddSpecifiers = specifiers.length > 0
-  const shouldRemoveUnnecessary = unnecessaryImports.length > 0
+  const shouldAddDefault = getDefaultImportName(first) == null && defaultImportNames.size === 1;
+  const shouldAddSpecifiers = specifiers.length > 0;
+  const shouldRemoveUnnecessary = unnecessaryImports.length > 0;
 
   if (!(shouldAddDefault || shouldAddSpecifiers || shouldRemoveUnnecessary)) {
-    return undefined
+    return undefined;
   }
 
   return fixer => {
-    const tokens = sourceCode.getTokens(first)
-    const openBrace = tokens.find(token => isPunctuator(token, '{'))
-    const closeBrace = tokens.find(token => isPunctuator(token, '}'))
-    const firstToken = sourceCode.getFirstToken(first)
-    const [defaultImportName] = defaultImportNames
+    const tokens = sourceCode.getTokens(first);
+    const openBrace = tokens.find(token => isPunctuator(token, '{'));
+    const closeBrace = tokens.find(token => isPunctuator(token, '}'));
+    const firstToken = sourceCode.getFirstToken(first);
+    const [defaultImportName] = defaultImportNames;
 
     const firstHasTrailingComma =
       closeBrace != null &&
-      isPunctuator(sourceCode.getTokenBefore(closeBrace), ',')
-    const firstIsEmpty = !hasSpecifiers(first)
+      isPunctuator(sourceCode.getTokenBefore(closeBrace), ',');
+    const firstIsEmpty = !hasSpecifiers(first);
 
     const [specifiersText] = specifiers.reduce(
       ([result, needsComma], specifier) => {
@@ -113,80 +113,80 @@ function getFix(first, rest, sourceCode) {
             ? `${result},${specifier.text}`
             : `${result}${specifier.text}`,
           specifier.isEmpty ? needsComma : true,
-        ]
+        ];
       },
       ['', !firstHasTrailingComma && !firstIsEmpty]
-    )
+    );
 
-    const fixes = []
+    const fixes = [];
 
     if (shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
       // `import './foo'` → `import def, {...} from './foo'`
       fixes.push(
         fixer.insertTextAfter(firstToken, ` ${defaultImportName}, {${specifiersText}} from`)
-      )
+      );
     } else if (shouldAddDefault && openBrace == null && !shouldAddSpecifiers) {
       // `import './foo'` → `import def from './foo'`
-      fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName} from`))
+      fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName} from`));
     } else if (shouldAddDefault && openBrace != null && closeBrace != null) {
       // `import {...} from './foo'` → `import def, {...} from './foo'`
-      fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName},`))
+      fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName},`));
       if (shouldAddSpecifiers) {
         // `import def, {...} from './foo'` → `import def, {..., ...} from './foo'`
-        fixes.push(fixer.insertTextBefore(closeBrace, specifiersText))
+        fixes.push(fixer.insertTextBefore(closeBrace, specifiersText));
       }
     } else if (!shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
       if (first.specifiers.length === 0) {
         // `import './foo'` → `import {...} from './foo'`
-        fixes.push(fixer.insertTextAfter(firstToken, ` {${specifiersText}} from`))
+        fixes.push(fixer.insertTextAfter(firstToken, ` {${specifiersText}} from`));
       } else {
         // `import def from './foo'` → `import def, {...} from './foo'`
-        fixes.push(fixer.insertTextAfter(first.specifiers[0], `, {${specifiersText}}`))
+        fixes.push(fixer.insertTextAfter(first.specifiers[0], `, {${specifiersText}}`));
       }
     } else if (!shouldAddDefault && openBrace != null && closeBrace != null) {
       // `import {...} './foo'` → `import {..., ...} from './foo'`
-      fixes.push(fixer.insertTextBefore(closeBrace, specifiersText))
+      fixes.push(fixer.insertTextBefore(closeBrace, specifiersText));
     }
 
     // Remove imports whose specifiers have been moved into the first import.
     for (const specifier of specifiers) {
-      fixes.push(fixer.remove(specifier.importNode))
+      fixes.push(fixer.remove(specifier.importNode));
     }
 
     // Remove imports whose default import has been moved to the first import,
     // and side-effect-only imports that are unnecessary due to the first
     // import.
     for (const node of unnecessaryImports) {
-      fixes.push(fixer.remove(node))
+      fixes.push(fixer.remove(node));
     }
 
-    return fixes
-  }
+    return fixes;
+  };
 }
 
 function isPunctuator(node, value) {
-  return node.type === 'Punctuator' && node.value === value
+  return node.type === 'Punctuator' && node.value === value;
 }
 
 // Get the name of the default import of `node`, if any.
 function getDefaultImportName(node) {
   const defaultSpecifier = node.specifiers
-    .find(specifier => specifier.type === 'ImportDefaultSpecifier')
-  return defaultSpecifier != null ? defaultSpecifier.local.name : undefined
+    .find(specifier => specifier.type === 'ImportDefaultSpecifier');
+  return defaultSpecifier != null ? defaultSpecifier.local.name : undefined;
 }
 
 // Checks whether `node` has a namespace import.
 function hasNamespace(node) {
   const specifiers = node.specifiers
-    .filter(specifier => specifier.type === 'ImportNamespaceSpecifier')
-  return specifiers.length > 0
+    .filter(specifier => specifier.type === 'ImportNamespaceSpecifier');
+  return specifiers.length > 0;
 }
 
 // Checks whether `node` has any non-default specifiers.
 function hasSpecifiers(node) {
   const specifiers = node.specifiers
-    .filter(specifier => specifier.type === 'ImportSpecifier')
-  return specifiers.length > 0
+    .filter(specifier => specifier.type === 'ImportSpecifier');
+  return specifiers.length > 0;
 }
 
 // It's not obvious what the user wants to do with comments associated with
@@ -196,36 +196,36 @@ function hasProblematicComments(node, sourceCode) {
     hasCommentBefore(node, sourceCode) ||
     hasCommentAfter(node, sourceCode) ||
     hasCommentInsideNonSpecifiers(node, sourceCode)
-  )
+  );
 }
 
 // Checks whether `node` has a comment (that ends) on the previous line or on
 // the same line as `node` (starts).
 function hasCommentBefore(node, sourceCode) {
   return sourceCode.getCommentsBefore(node)
-    .some(comment => comment.loc.end.line >= node.loc.start.line - 1)
+    .some(comment => comment.loc.end.line >= node.loc.start.line - 1);
 }
 
 // Checks whether `node` has a comment (that starts) on the same line as `node`
 // (ends).
 function hasCommentAfter(node, sourceCode) {
   return sourceCode.getCommentsAfter(node)
-    .some(comment => comment.loc.start.line === node.loc.end.line)
+    .some(comment => comment.loc.start.line === node.loc.end.line);
 }
 
 // Checks whether `node` has any comments _inside,_ except inside the `{...}`
 // part (if any).
 function hasCommentInsideNonSpecifiers(node, sourceCode) {
-  const tokens = sourceCode.getTokens(node)
-  const openBraceIndex = tokens.findIndex(token => isPunctuator(token, '{'))
-  const closeBraceIndex = tokens.findIndex(token => isPunctuator(token, '}'))
+  const tokens = sourceCode.getTokens(node);
+  const openBraceIndex = tokens.findIndex(token => isPunctuator(token, '{'));
+  const closeBraceIndex = tokens.findIndex(token => isPunctuator(token, '}'));
   // Slice away the first token, since we're no looking for comments _before_
   // `node` (only inside). If there's a `{...}` part, look for comments before
   // the `{`, but not before the `}` (hence the `+1`s).
   const someTokens = openBraceIndex >= 0 && closeBraceIndex >= 0
     ? tokens.slice(1, openBraceIndex + 1).concat(tokens.slice(closeBraceIndex + 1))
-    : tokens.slice(1)
-  return someTokens.some(token => sourceCode.getCommentsBefore(token).length > 0)
+    : tokens.slice(1);
+  return someTokens.some(token => sourceCode.getCommentsBefore(token).length > 0);
 }
 
 module.exports = {
@@ -251,38 +251,38 @@ module.exports = {
   create: function (context) {
     // Prepare the resolver from options.
     const considerQueryStringOption = context.options[0] &&
-      context.options[0]['considerQueryString']
-    const defaultResolver = sourcePath => resolve(sourcePath, context) || sourcePath
+      context.options[0]['considerQueryString'];
+    const defaultResolver = sourcePath => resolve(sourcePath, context) || sourcePath;
     const resolver = considerQueryStringOption ? (sourcePath => {
-      const parts = sourcePath.match(/^([^?]*)\?(.*)$/)
+      const parts = sourcePath.match(/^([^?]*)\?(.*)$/);
       if (!parts) {
-        return defaultResolver(sourcePath)
+        return defaultResolver(sourcePath);
       }
-      return defaultResolver(parts[1]) + '?' + parts[2]
-    }) : defaultResolver
+      return defaultResolver(parts[1]) + '?' + parts[2];
+    }) : defaultResolver;
 
-    const imported = new Map()
-    const nsImported = new Map()
-    const typesImported = new Map()
+    const imported = new Map();
+    const nsImported = new Map();
+    const typesImported = new Map();
     return {
       'ImportDeclaration': function (n) {
         // resolved path will cover aliased duplicates
-        const resolvedPath = resolver(n.source.value)
+        const resolvedPath = resolver(n.source.value);
         const importMap = n.importKind === 'type' ? typesImported :
-          (hasNamespace(n) ? nsImported : imported)
+          (hasNamespace(n) ? nsImported : imported);
 
         if (importMap.has(resolvedPath)) {
-          importMap.get(resolvedPath).push(n)
+          importMap.get(resolvedPath).push(n);
         } else {
-          importMap.set(resolvedPath, [n])
+          importMap.set(resolvedPath, [n]);
         }
       },
 
       'Program:exit': function () {
-        checkImports(imported, context)
-        checkImports(nsImported, context)
-        checkImports(typesImported, context)
+        checkImports(imported, context);
+        checkImports(nsImported, context);
+        checkImports(typesImported, context);
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-dynamic-require.js b/src/rules/no-dynamic-require.js
index 9e7af8e283..0c14df0893 100644
--- a/src/rules/no-dynamic-require.js
+++ b/src/rules/no-dynamic-require.js
@@ -1,16 +1,16 @@
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 function isRequire(node) {
   return node &&
     node.callee &&
     node.callee.type === 'Identifier' &&
     node.callee.name === 'require' &&
-    node.arguments.length >= 1
+    node.arguments.length >= 1;
 }
 
 function isStaticValue(arg) {
   return arg.type === 'Literal' ||
-    (arg.type === 'TemplateLiteral' && arg.expressions.length === 0)
+    (arg.type === 'TemplateLiteral' && arg.expressions.length === 0);
 }
 
 module.exports = {
@@ -29,9 +29,9 @@ module.exports = {
           context.report({
             node,
             message: 'Calls to require() should use string literals',
-          })
+          });
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 56bda2cb3a..7777596718 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -1,20 +1,20 @@
-import path from 'path'
-import fs from 'fs'
-import readPkgUp from 'read-pkg-up'
-import minimatch from 'minimatch'
-import resolve from 'eslint-module-utils/resolve'
-import moduleVisitor from 'eslint-module-utils/moduleVisitor'
-import importType from '../core/importType'
-import docsUrl from '../docsUrl'
+import path from 'path';
+import fs from 'fs';
+import readPkgUp from 'read-pkg-up';
+import minimatch from 'minimatch';
+import resolve from 'eslint-module-utils/resolve';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
+import importType from '../core/importType';
+import docsUrl from '../docsUrl';
 
-const depFieldCache = new Map()
+const depFieldCache = new Map();
 
 function hasKeys(obj = {}) {
-  return Object.keys(obj).length > 0
+  return Object.keys(obj).length > 0;
 }
 
 function arrayOrKeys(arrayOrObject) {
-  return Array.isArray(arrayOrObject) ? arrayOrObject : Object.keys(arrayOrObject)
+  return Array.isArray(arrayOrObject) ? arrayOrObject : Object.keys(arrayOrObject);
 }
 
 function extractDepFields(pkg) {
@@ -26,11 +26,11 @@ function extractDepFields(pkg) {
     // BundledDeps should be in the form of an array, but object notation is also supported by
     // `npm`, so we convert it to an array if it is an object
     bundledDependencies: arrayOrKeys(pkg.bundleDependencies || pkg.bundledDependencies || []),
-  }
+  };
 }
 
 function getDependencies(context, packageDir) {
-  let paths = []
+  let paths = [];
   try {
     const packageContent = {
       dependencies: {},
@@ -38,31 +38,31 @@ function getDependencies(context, packageDir) {
       optionalDependencies: {},
       peerDependencies: {},
       bundledDependencies: [],
-    }
+    };
 
     if (packageDir && packageDir.length > 0) {
       if (!Array.isArray(packageDir)) {
-        paths = [path.resolve(packageDir)]
+        paths = [path.resolve(packageDir)];
       } else {
-        paths = packageDir.map(dir => path.resolve(dir))
+        paths = packageDir.map(dir => path.resolve(dir));
       }
     }
 
     if (paths.length > 0) {
       // use rule config to find package.json
       paths.forEach(dir => {
-        const packageJsonPath = path.join(dir, 'package.json')
+        const packageJsonPath = path.join(dir, 'package.json');
         if (!depFieldCache.has(packageJsonPath)) {
           const depFields = extractDepFields(
             JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
-          )
-          depFieldCache.set(packageJsonPath, depFields)
+          );
+          depFieldCache.set(packageJsonPath, depFields);
         }
-        const _packageContent = depFieldCache.get(packageJsonPath)
+        const _packageContent = depFieldCache.get(packageJsonPath);
         Object.keys(packageContent).forEach(depsKey =>
           Object.assign(packageContent[depsKey], _packageContent[depsKey])
-        )
-      })
+        );
+      });
     } else {
       // use closest package.json
       Object.assign(
@@ -70,7 +70,7 @@ function getDependencies(context, packageDir) {
         extractDepFields(
           readPkgUp.sync({cwd: context.getFilename(), normalize: false}).pkg
         )
-      )
+      );
     }
 
     if (![
@@ -80,64 +80,64 @@ function getDependencies(context, packageDir) {
       packageContent.peerDependencies,
       packageContent.bundledDependencies,
     ].some(hasKeys)) {
-      return null
+      return null;
     }
 
-    return packageContent
+    return packageContent;
   } catch (e) {
     if (paths.length > 0 && e.code === 'ENOENT') {
       context.report({
         message: 'The package.json file could not be found.',
         loc: { line: 0, column: 0 },
-      })
+      });
     }
     if (e.name === 'JSONError' || e instanceof SyntaxError) {
       context.report({
         message: 'The package.json file could not be parsed: ' + e.message,
         loc: { line: 0, column: 0 },
-      })
+      });
     }
 
-    return null
+    return null;
   }
 }
 
 function missingErrorMessage(packageName) {
   return `'${packageName}' should be listed in the project's dependencies. ` +
-    `Run 'npm i -S ${packageName}' to add it`
+    `Run 'npm i -S ${packageName}' to add it`;
 }
 
 function devDepErrorMessage(packageName) {
-  return `'${packageName}' should be listed in the project's dependencies, not devDependencies.`
+  return `'${packageName}' should be listed in the project's dependencies, not devDependencies.`;
 }
 
 function optDepErrorMessage(packageName) {
   return `'${packageName}' should be listed in the project's dependencies, ` +
-    `not optionalDependencies.`
+    `not optionalDependencies.`;
 }
 
 function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types
   if (node.importKind === 'type' || (node.parent && node.parent.importKind === 'type')) {
-    return
+    return;
   }
 
   if (importType(name, context) !== 'external') {
-    return
+    return;
   }
 
-  const resolved = resolve(name, context)
-  if (!resolved) { return }
+  const resolved = resolve(name, context);
+  if (!resolved) { return; }
 
-  const splitName = name.split('/')
+  const splitName = name.split('/');
   const packageName = splitName[0][0] === '@'
     ? splitName.slice(0, 2).join('/')
-    : splitName[0]
-  const isInDeps = deps.dependencies[packageName] !== undefined
-  const isInDevDeps = deps.devDependencies[packageName] !== undefined
-  const isInOptDeps = deps.optionalDependencies[packageName] !== undefined
-  const isInPeerDeps = deps.peerDependencies[packageName] !== undefined
-  const isInBundledDeps = deps.bundledDependencies.indexOf(packageName) !== -1
+    : splitName[0];
+  const isInDeps = deps.dependencies[packageName] !== undefined;
+  const isInDevDeps = deps.devDependencies[packageName] !== undefined;
+  const isInOptDeps = deps.optionalDependencies[packageName] !== undefined;
+  const isInPeerDeps = deps.peerDependencies[packageName] !== undefined;
+  const isInBundledDeps = deps.bundledDependencies.indexOf(packageName) !== -1;
 
   if (isInDeps ||
     (depsOptions.allowDevDeps && isInDevDeps) ||
@@ -145,32 +145,32 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
     (depsOptions.allowOptDeps && isInOptDeps) ||
     (depsOptions.allowBundledDeps && isInBundledDeps)
   ) {
-    return
+    return;
   }
 
   if (isInDevDeps && !depsOptions.allowDevDeps) {
-    context.report(node, devDepErrorMessage(packageName))
-    return
+    context.report(node, devDepErrorMessage(packageName));
+    return;
   }
 
   if (isInOptDeps && !depsOptions.allowOptDeps) {
-    context.report(node, optDepErrorMessage(packageName))
-    return
+    context.report(node, optDepErrorMessage(packageName));
+    return;
   }
 
-  context.report(node, missingErrorMessage(packageName))
+  context.report(node, missingErrorMessage(packageName));
 }
 
 function testConfig(config, filename) {
   // Simplest configuration first, either a boolean or nothing.
   if (typeof config === 'boolean' || typeof config === 'undefined') {
-    return config
+    return config;
   }
   // Array of globs.
   return config.some(c => (
     minimatch(filename, c) ||
     minimatch(filename, path.join(process.cwd(), c))
-  ))
+  ));
 }
 
 module.exports = {
@@ -196,19 +196,19 @@ module.exports = {
   },
 
   create: function (context) {
-    const options = context.options[0] || {}
-    const filename = context.getFilename()
-    const deps = getDependencies(context, options.packageDir) || extractDepFields({})
+    const options = context.options[0] || {};
+    const filename = context.getFilename();
+    const deps = getDependencies(context, options.packageDir) || extractDepFields({});
 
     const depsOptions = {
       allowDevDeps: testConfig(options.devDependencies, filename) !== false,
       allowOptDeps: testConfig(options.optionalDependencies, filename) !== false,
       allowPeerDeps: testConfig(options.peerDependencies, filename) !== false,
       allowBundledDeps: testConfig(options.bundledDependencies, filename) !== false,
-    }
+    };
 
     return moduleVisitor(node => {
-      reportIfMissing(context, deps, depsOptions, node, node.value)
-    }, {commonjs: true})
+      reportIfMissing(context, deps, depsOptions, node, node.value);
+    }, {commonjs: true});
   },
-}
+};
diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index bd13ab07d0..a234d3b7a8 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -1,9 +1,9 @@
-import minimatch from 'minimatch'
+import minimatch from 'minimatch';
 
-import resolve from 'eslint-module-utils/resolve'
-import importType from '../core/importType'
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
+import resolve from 'eslint-module-utils/resolve';
+import importType from '../core/importType';
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -29,18 +29,18 @@ module.exports = {
   },
 
   create: function noReachingInside(context) {
-    const options = context.options[0] || {}
-    const allowRegexps = (options.allow || []).map(p => minimatch.makeRe(p))
+    const options = context.options[0] || {};
+    const allowRegexps = (options.allow || []).map(p => minimatch.makeRe(p));
 
     // test if reaching to this destination is allowed
     function reachingAllowed(importPath) {
-      return allowRegexps.some(re => re.test(importPath))
+      return allowRegexps.some(re => re.test(importPath));
     }
 
     // minimatch patterns are expected to use / path separators, like import
     // statements, so normalize paths to use the same
     function normalizeSep(somePath) {
-      return somePath.split('\\').join('/')
+      return somePath.split('\\').join('/');
     }
 
     // find a directory that is being reached into, but which shouldn't be
@@ -49,62 +49,62 @@ module.exports = {
         .split('/')
         .reduce((acc, step) => {
           if (!step || step === '.') {
-            return acc
+            return acc;
           } else if (step === '..') {
-            return acc.slice(0, -1)
+            return acc.slice(0, -1);
           } else {
-            return acc.concat(step)
+            return acc.concat(step);
           }
-        }, [])
+        }, []);
 
-      const nonScopeSteps = steps.filter(step => step.indexOf('@') !== 0)
-      if (nonScopeSteps.length <= 1) return false
+      const nonScopeSteps = steps.filter(step => step.indexOf('@') !== 0);
+      if (nonScopeSteps.length <= 1) return false;
 
       // before trying to resolve, see if the raw import (with relative
       // segments resolved) matches an allowed pattern
-      const justSteps = steps.join('/')
-      if (reachingAllowed(justSteps) || reachingAllowed(`/${justSteps}`)) return false
+      const justSteps = steps.join('/');
+      if (reachingAllowed(justSteps) || reachingAllowed(`/${justSteps}`)) return false;
 
       // if the import statement doesn't match directly, try to match the
       // resolved path if the import is resolvable
-      const resolved = resolve(importPath, context)
-      if (!resolved || reachingAllowed(normalizeSep(resolved))) return false
+      const resolved = resolve(importPath, context);
+      if (!resolved || reachingAllowed(normalizeSep(resolved))) return false;
 
       // this import was not allowed by the allowed paths, and reaches
       // so it is a violation
-      return true
+      return true;
     }
 
     function checkImportForReaching(importPath, node) {
-      const potentialViolationTypes = ['parent', 'index', 'sibling', 'external', 'internal']
+      const potentialViolationTypes = ['parent', 'index', 'sibling', 'external', 'internal'];
       if (potentialViolationTypes.indexOf(importType(importPath, context)) !== -1 &&
         isReachViolation(importPath)
       ) {
         context.report({
           node,
           message: `Reaching to "${importPath}" is not allowed.`,
-        })
+        });
       }
     }
 
     return {
       ImportDeclaration(node) {
-        checkImportForReaching(node.source.value, node.source)
+        checkImportForReaching(node.source.value, node.source);
       },
       ExportAllDeclaration(node) {
-        checkImportForReaching(node.source.value, node.source)
+        checkImportForReaching(node.source.value, node.source);
       },
       ExportNamedDeclaration(node) {
         if (node.source) {
-          checkImportForReaching(node.source.value, node.source)
+          checkImportForReaching(node.source.value, node.source);
         }
       },
       CallExpression(node) {
         if (isStaticRequire(node)) {
-          const [ firstArgument ] = node.arguments
-          checkImportForReaching(firstArgument.value, firstArgument)
+          const [ firstArgument ] = node.arguments;
+          checkImportForReaching(firstArgument.value, firstArgument);
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index 7e94bfbe9b..ae334783ca 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -1,4 +1,4 @@
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -11,9 +11,9 @@ module.exports = {
 
   create: function (context) {
     function checkDeclaration(node) {
-      const {kind} = node
+      const {kind} = node;
       if (kind === 'var' || kind === 'let') {
-        context.report(node, `Exporting mutable '${kind}' binding, use 'const' instead.`)
+        context.report(node, `Exporting mutable '${kind}' binding, use 'const' instead.`);
       }
     }
 
@@ -22,7 +22,7 @@ module.exports = {
         if (variable.name === name) {
           for (let def of variable.defs) {
             if (def.type === 'Variable' && def.parent) {
-              checkDeclaration(def.parent)
+              checkDeclaration(def.parent);
             }
           }
         }
@@ -30,21 +30,21 @@ module.exports = {
     }
 
     function handleExportDefault(node) {
-      const scope = context.getScope()
+      const scope = context.getScope();
 
       if (node.declaration.name) {
-        checkDeclarationsInScope(scope, node.declaration.name)
+        checkDeclarationsInScope(scope, node.declaration.name);
       }
     }
 
     function handleExportNamed(node) {
-      const scope = context.getScope()
+      const scope = context.getScope();
 
       if (node.declaration)  {
-        checkDeclaration(node.declaration)
+        checkDeclaration(node.declaration);
       } else if (!node.source) {
         for (let specifier of node.specifiers) {
-          checkDeclarationsInScope(scope, specifier.local.name)
+          checkDeclarationsInScope(scope, specifier.local.name);
         }
       }
     }
@@ -52,6 +52,6 @@ module.exports = {
     return {
       'ExportDefaultDeclaration': handleExportDefault,
       'ExportNamedDeclaration': handleExportNamed,
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index b6e50cd713..754359a124 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -4,9 +4,9 @@
  * @copyright 2016 Desmond Brand. All rights reserved.
  * See LICENSE in root directory for full license.
  */
-import Exports from '../ExportMap'
-import importDeclaration from '../importDeclaration'
-import docsUrl from '../docsUrl'
+import Exports from '../ExportMap';
+import importDeclaration from '../importDeclaration';
+import docsUrl from '../docsUrl';
 
 //------------------------------------------------------------------------------
 // Rule Definition
@@ -23,35 +23,35 @@ module.exports = {
 
   create: function(context) {
 
-    const fileImports = new Map()
-    const allPropertyLookups = new Map()
+    const fileImports = new Map();
+    const allPropertyLookups = new Map();
 
     function handleImportDefault(node) {
-      const declaration = importDeclaration(context)
-      const exportMap = Exports.get(declaration.source.value, context)
-      if (exportMap == null) return
+      const declaration = importDeclaration(context);
+      const exportMap = Exports.get(declaration.source.value, context);
+      if (exportMap == null) return;
 
       if (exportMap.errors.length) {
-        exportMap.reportErrors(context, declaration)
-        return
+        exportMap.reportErrors(context, declaration);
+        return;
       }
 
       fileImports.set(node.local.name, {
         exportMap,
         sourcePath: declaration.source.value,
-      })
+      });
     }
 
     function storePropertyLookup(objectName, propName, node) {
-      const lookups = allPropertyLookups.get(objectName) || []
-      lookups.push({node, propName})
-      allPropertyLookups.set(objectName, lookups)
+      const lookups = allPropertyLookups.get(objectName) || [];
+      lookups.push({node, propName});
+      allPropertyLookups.set(objectName, lookups);
     }
 
     function handlePropLookup(node) {
-      const objectName = node.object.name
-      const propName = node.property.name
-      storePropertyLookup(objectName, propName, node)
+      const objectName = node.object.name;
+      const propName = node.property.name;
+      storePropertyLookup(objectName, propName, node);
     }
 
     function handleDestructuringAssignment(node) {
@@ -59,25 +59,25 @@ module.exports = {
         node.id.type === 'ObjectPattern' &&
         node.init != null &&
         node.init.type === 'Identifier'
-      )
-      if (!isDestructure) return
+      );
+      if (!isDestructure) return;
 
-      const objectName = node.init.name
+      const objectName = node.init.name;
       for (const { key } of node.id.properties) {
-        if (key == null) continue  // true for rest properties
-        storePropertyLookup(objectName, key.name, key)
+        if (key == null) continue;  // true for rest properties
+        storePropertyLookup(objectName, key.name, key);
       }
     }
 
     function handleProgramExit() {
       allPropertyLookups.forEach((lookups, objectName) => {
-        const fileImport = fileImports.get(objectName)
-        if (fileImport == null) return
+        const fileImport = fileImports.get(objectName);
+        if (fileImport == null) return;
 
         for (const {propName, node} of lookups) {
           // the default import can have a "default" property
-          if (propName === 'default') continue
-          if (!fileImport.exportMap.namespace.has(propName)) continue
+          if (propName === 'default') continue;
+          if (!fileImport.exportMap.namespace.has(propName)) continue;
 
           context.report({
             node,
@@ -87,9 +87,9 @@ module.exports = {
               `\`import {${propName}} from '${fileImport.sourcePath}'\` ` +
               'instead.'
             ),
-          })
+          });
         }
-      })
+      });
     }
 
     return {
@@ -97,6 +97,6 @@ module.exports = {
       'MemberExpression': handlePropLookup,
       'VariableDeclarator': handleDestructuringAssignment,
       'Program:exit': handleProgramExit,
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index b4c64a34c9..cbc85952b4 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -1,6 +1,6 @@
-import Exports from '../ExportMap'
-import importDeclaration from '../importDeclaration'
-import docsUrl from '../docsUrl'
+import Exports from '../ExportMap';
+import importDeclaration from '../importDeclaration';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -14,16 +14,16 @@ module.exports = {
   create: function (context) {
     function checkDefault(nameKey, defaultSpecifier) {
       // #566: default is a valid specifier
-      if (defaultSpecifier[nameKey].name === 'default') return
+      if (defaultSpecifier[nameKey].name === 'default') return;
 
-      var declaration = importDeclaration(context)
+      var declaration = importDeclaration(context);
 
-      var imports = Exports.get(declaration.source.value, context)
-      if (imports == null) return
+      var imports = Exports.get(declaration.source.value, context);
+      if (imports == null) return;
 
       if (imports.errors.length) {
-        imports.reportErrors(context, declaration)
-        return
+        imports.reportErrors(context, declaration);
+        return;
       }
 
       if (imports.has('default') &&
@@ -31,13 +31,13 @@ module.exports = {
 
         context.report(defaultSpecifier,
           'Using exported name \'' + defaultSpecifier[nameKey].name +
-          '\' as identifier for default export.')
+          '\' as identifier for default export.');
 
       }
     }
     return {
       'ImportDefaultSpecifier': checkDefault.bind(null, 'local'),
       'ExportDefaultSpecifier': checkDefault.bind(null, 'exported'),
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-named-default.js b/src/rules/no-named-default.js
index f0b74a2ffb..db046f0aee 100644
--- a/src/rules/no-named-default.js
+++ b/src/rules/no-named-default.js
@@ -1,4 +1,4 @@
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -16,10 +16,10 @@ module.exports = {
           if (im.type === 'ImportSpecifier' && im.imported.name === 'default') {
             context.report({
               node: im.local,
-              message: `Use default import syntax to import '${im.local.name}'.` })
+              message: `Use default import syntax to import '${im.local.name}'.` });
           }
-        })
+        });
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-named-export.js b/src/rules/no-named-export.js
index e7d4b08351..c6e3ca57e3 100644
--- a/src/rules/no-named-export.js
+++ b/src/rules/no-named-export.js
@@ -1,4 +1,4 @@
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -10,26 +10,26 @@ module.exports = {
   create(context) {
     // ignore non-modules
     if (context.parserOptions.sourceType !== 'module') {
-      return {}
+      return {};
     }
 
-    const message = 'Named exports are not allowed.'
+    const message = 'Named exports are not allowed.';
 
     return {
       ExportAllDeclaration(node) {
-        context.report({node, message})
+        context.report({node, message});
       },
 
       ExportNamedDeclaration(node) {
         if (node.specifiers.length === 0) {
-          return context.report({node, message})
+          return context.report({node, message});
         }
 
-        const someNamed = node.specifiers.some(specifier => specifier.exported.name !== 'default')
+        const someNamed = node.specifiers.some(specifier => specifier.exported.name !== 'default');
         if (someNamed) {
-          context.report({node, message})
+          context.report({node, message});
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index 0b63132508..ca51823a0b 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -3,7 +3,7 @@
  * @author Radek Benkel
  */
 
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 //------------------------------------------------------------------------------
 // Rule Definition
@@ -23,69 +23,69 @@ module.exports = {
   create: function (context) {
     return {
       'ImportNamespaceSpecifier': function (node) {
-        const scopeVariables = context.getScope().variables
+        const scopeVariables = context.getScope().variables;
         const namespaceVariable = scopeVariables.find((variable) =>
           variable.defs[0].node === node
-        )
-        const namespaceReferences = namespaceVariable.references
-        const namespaceIdentifiers = namespaceReferences.map(reference => reference.identifier)
-        const canFix = namespaceIdentifiers.length > 0 && !usesNamespaceAsObject(namespaceIdentifiers)
+        );
+        const namespaceReferences = namespaceVariable.references;
+        const namespaceIdentifiers = namespaceReferences.map(reference => reference.identifier);
+        const canFix = namespaceIdentifiers.length > 0 && !usesNamespaceAsObject(namespaceIdentifiers);
 
         context.report({
           node,
           message: `Unexpected namespace import.`,
           fix: canFix && (fixer => {
-            const scopeManager = context.getSourceCode().scopeManager
-            const fixes = []
+            const scopeManager = context.getSourceCode().scopeManager;
+            const fixes = [];
 
             // Pass 1: Collect variable names that are already in scope for each reference we want
             // to transform, so that we can be sure that we choose non-conflicting import names
-            const importNameConflicts = {}
+            const importNameConflicts = {};
             namespaceIdentifiers.forEach((identifier) => {
-              const parent = identifier.parent
+              const parent = identifier.parent;
               if (parent && parent.type === 'MemberExpression') {
-                const importName = getMemberPropertyName(parent)
-                const localConflicts = getVariableNamesInScope(scopeManager, parent)
+                const importName = getMemberPropertyName(parent);
+                const localConflicts = getVariableNamesInScope(scopeManager, parent);
                 if (!importNameConflicts[importName]) {
-                  importNameConflicts[importName] = localConflicts
+                  importNameConflicts[importName] = localConflicts;
                 } else {
-                  localConflicts.forEach((c) => importNameConflicts[importName].add(c))
+                  localConflicts.forEach((c) => importNameConflicts[importName].add(c));
                 }
               }
-            })
+            });
 
             // Choose new names for each import
-            const importNames = Object.keys(importNameConflicts)
+            const importNames = Object.keys(importNameConflicts);
             const importLocalNames = generateLocalNames(
               importNames,
               importNameConflicts,
               namespaceVariable.name
-            )
+            );
 
             // Replace the ImportNamespaceSpecifier with a list of ImportSpecifiers
             const namedImportSpecifiers = importNames.map((importName) =>
               importName === importLocalNames[importName]
                 ? importName
                 : `${importName} as ${importLocalNames[importName]}`
-            )
-            fixes.push(fixer.replaceText(node, `{ ${namedImportSpecifiers.join(', ')} }`))
+            );
+            fixes.push(fixer.replaceText(node, `{ ${namedImportSpecifiers.join(', ')} }`));
 
             // Pass 2: Replace references to the namespace with references to the named imports
             namespaceIdentifiers.forEach((identifier) => {
-              const parent = identifier.parent
+              const parent = identifier.parent;
               if (parent && parent.type === 'MemberExpression') {
-                const importName = getMemberPropertyName(parent)
-                fixes.push(fixer.replaceText(parent, importLocalNames[importName]))
+                const importName = getMemberPropertyName(parent);
+                fixes.push(fixer.replaceText(parent, importLocalNames[importName]));
               }
-            })
+            });
 
-            return fixes
+            return fixes;
           }),
-        })
+        });
       },
-    }
+    };
   },
-}
+};
 
 /**
  * @param {Identifier[]} namespaceIdentifiers
@@ -93,14 +93,14 @@ module.exports = {
  */
 function usesNamespaceAsObject(namespaceIdentifiers) {
   return !namespaceIdentifiers.every((identifier) => {
-    const parent = identifier.parent
+    const parent = identifier.parent;
 
     // `namespace.x` or `namespace['x']`
     return (
       parent && parent.type === 'MemberExpression' &&
       (parent.property.type === 'Identifier' || parent.property.type === 'Literal')
-    )
-  })
+    );
+  });
 }
 
 /**
@@ -110,7 +110,7 @@ function usesNamespaceAsObject(namespaceIdentifiers) {
 function getMemberPropertyName(memberExpression) {
   return memberExpression.property.type === 'Identifier'
     ? memberExpression.property.name
-    : memberExpression.property.value
+    : memberExpression.property.value;
 }
 
 /**
@@ -119,16 +119,16 @@ function getMemberPropertyName(memberExpression) {
  * @return {Set<string>}
  */
 function getVariableNamesInScope(scopeManager, node) {
-  let currentNode = node
-  let scope = scopeManager.acquire(currentNode)
+  let currentNode = node;
+  let scope = scopeManager.acquire(currentNode);
   while (scope == null) {
-    currentNode = currentNode.parent
-    scope = scopeManager.acquire(currentNode, true)
+    currentNode = currentNode.parent;
+    scope = scopeManager.acquire(currentNode, true);
   }
   return new Set([
     ...scope.variables.map(variable => variable.name),
     ...scope.upper.variables.map(variable => variable.name),
-  ])
+  ]);
 }
 
 /**
@@ -138,22 +138,22 @@ function getVariableNamesInScope(scopeManager, node) {
  * @param {*} namespaceName
  */
 function generateLocalNames(names, nameConflicts, namespaceName) {
-  const localNames = {}
+  const localNames = {};
   names.forEach((name) => {
-    let localName
+    let localName;
     if (!nameConflicts[name].has(name)) {
-      localName = name
+      localName = name;
     } else if (!nameConflicts[name].has(`${namespaceName}_${name}`)) {
-      localName = `${namespaceName}_${name}`
+      localName = `${namespaceName}_${name}`;
     } else {
       for (let i = 1; i < Infinity; i++) {
         if (!nameConflicts[name].has(`${namespaceName}_${name}_${i}`)) {
-          localName = `${namespaceName}_${name}_${i}`
-          break
+          localName = `${namespaceName}_${name}_${i}`;
+          break;
         }
       }
     }
-    localNames[name] = localName
-  })
-  return localNames
+    localNames[name] = localName;
+  });
+  return localNames;
 }
diff --git a/src/rules/no-nodejs-modules.js b/src/rules/no-nodejs-modules.js
index fb9bc23e28..bca6c00d23 100644
--- a/src/rules/no-nodejs-modules.js
+++ b/src/rules/no-nodejs-modules.js
@@ -1,10 +1,10 @@
-import importType from '../core/importType'
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
+import importType from '../core/importType';
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
 
 function reportIfMissing(context, node, allowed, name) {
   if (allowed.indexOf(name) === -1 && importType(name, context) === 'builtin') {
-    context.report(node, 'Do not import Node.js builtin module "' + name + '"')
+    context.report(node, 'Do not import Node.js builtin module "' + name + '"');
   }
 }
 
@@ -32,18 +32,18 @@ module.exports = {
   },
 
   create: function (context) {
-    const options = context.options[0] || {}
-    const allowed = options.allow || []
+    const options = context.options[0] || {};
+    const allowed = options.allow || [];
 
     return {
       ImportDeclaration: function handleImports(node) {
-        reportIfMissing(context, node, allowed, node.source.value)
+        reportIfMissing(context, node, allowed, node.source.value);
       },
       CallExpression: function handleRequires(node) {
         if (isStaticRequire(node)) {
-          reportIfMissing(context, node, allowed, node.arguments[0].value)
+          reportIfMissing(context, node, allowed, node.arguments[0].value);
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js
index 544525755e..9826da826b 100644
--- a/src/rules/no-relative-parent-imports.js
+++ b/src/rules/no-relative-parent-imports.js
@@ -1,9 +1,9 @@
-import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor'
-import docsUrl from '../docsUrl'
-import { basename, dirname, relative } from 'path'
-import resolve from 'eslint-module-utils/resolve'
+import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
+import docsUrl from '../docsUrl';
+import { basename, dirname, relative } from 'path';
+import resolve from 'eslint-module-utils/resolve';
 
-import importType from '../core/importType'
+import importType from '../core/importType';
 
 module.exports = {
   meta: {
@@ -15,23 +15,23 @@ module.exports = {
   },
 
   create: function noRelativePackages(context) {
-    const myPath = context.getFilename()
-    if (myPath === '<text>') return {} // can't check a non-file
+    const myPath = context.getFilename();
+    if (myPath === '<text>') return {}; // can't check a non-file
 
     function checkSourceValue(sourceNode) {
-      const depPath = sourceNode.value
+      const depPath = sourceNode.value;
 
       if (importType(depPath, context) === 'external') { // ignore packages
-        return
+        return;
       }
 
-      const absDepPath = resolve(depPath, context)
+      const absDepPath = resolve(depPath, context);
 
       if (!absDepPath) { // unable to resolve path
-        return
+        return;
       }
 
-      const relDepPath = relative(dirname(myPath), absDepPath)
+      const relDepPath = relative(dirname(myPath), absDepPath);
 
       if (importType(relDepPath, context) === 'parent') {
         context.report({
@@ -40,10 +40,10 @@ module.exports = {
             `Please either pass what you're importing through at runtime ` +
             `(dependency injection), move \`${basename(myPath)}\` to same ` +
             `directory as \`${depPath}\` or consider making \`${depPath}\` a package.`,
-        })
+        });
       }
     }
 
-    return moduleVisitor(checkSourceValue, context.options[0])
+    return moduleVisitor(checkSourceValue, context.options[0]);
   },
-}
+};
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index a94b11ec16..71732437eb 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -1,10 +1,10 @@
-import containsPath from 'contains-path'
-import path from 'path'
+import containsPath from 'contains-path';
+import path from 'path';
 
-import resolve from 'eslint-module-utils/resolve'
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
-import importType from '../core/importType'
+import resolve from 'eslint-module-utils/resolve';
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
+import importType from '../core/importType';
 
 module.exports = {
   meta: {
@@ -45,81 +45,81 @@ module.exports = {
   },
 
   create: function noRestrictedPaths(context) {
-    const options = context.options[0] || {}
-    const restrictedPaths = options.zones || []
-    const basePath = options.basePath || process.cwd()
-    const currentFilename = context.getFilename()
+    const options = context.options[0] || {};
+    const restrictedPaths = options.zones || [];
+    const basePath = options.basePath || process.cwd();
+    const currentFilename = context.getFilename();
     const matchingZones = restrictedPaths.filter((zone) => {
-      const targetPath = path.resolve(basePath, zone.target)
+      const targetPath = path.resolve(basePath, zone.target);
 
-      return containsPath(currentFilename, targetPath)
-    })
+      return containsPath(currentFilename, targetPath);
+    });
 
     function isValidExceptionPath(absoluteFromPath, absoluteExceptionPath) {
-      const relativeExceptionPath = path.relative(absoluteFromPath, absoluteExceptionPath)
+      const relativeExceptionPath = path.relative(absoluteFromPath, absoluteExceptionPath);
 
-      return importType(relativeExceptionPath, context) !== 'parent'
+      return importType(relativeExceptionPath, context) !== 'parent';
     }
 
     function reportInvalidExceptionPath(node) {
       context.report({
         node,
         message: 'Restricted path exceptions must be descendants of the configured `from` path for that zone.',
-      })
+      });
     }
 
     function checkForRestrictedImportPath(importPath, node) {
-        const absoluteImportPath = resolve(importPath, context)
+        const absoluteImportPath = resolve(importPath, context);
 
         if (!absoluteImportPath) {
-          return
+          return;
         }
 
         matchingZones.forEach((zone) => {
-          const exceptionPaths = zone.except || []
-          const absoluteFrom = path.resolve(basePath, zone.from)
+          const exceptionPaths = zone.except || [];
+          const absoluteFrom = path.resolve(basePath, zone.from);
 
           if (!containsPath(absoluteImportPath, absoluteFrom)) {
-            return
+            return;
           }
 
           const absoluteExceptionPaths = exceptionPaths.map((exceptionPath) =>
             path.resolve(absoluteFrom, exceptionPath)
-          )
+          );
           const hasValidExceptionPaths = absoluteExceptionPaths
-            .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath))
+            .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
 
           if (!hasValidExceptionPaths) {
-            reportInvalidExceptionPath(node)
-            return
+            reportInvalidExceptionPath(node);
+            return;
           }
 
           const pathIsExcepted = absoluteExceptionPaths
-            .some((absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath))
+            .some((absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath));
 
           if (pathIsExcepted) {
-            return
+            return;
           }
 
           context.report({
             node,
             message: `Unexpected path "{{importPath}}" imported in restricted zone.${zone.message ? ` ${zone.message}` : ''}`,
             data: { importPath },
-          })
-        })
+          });
+        });
     }
 
     return {
       ImportDeclaration(node) {
-        checkForRestrictedImportPath(node.source.value, node.source)
+        checkForRestrictedImportPath(node.source.value, node.source);
       },
       CallExpression(node) {
         if (isStaticRequire(node)) {
-          const [ firstArgument ] = node.arguments
+          const [ firstArgument ] = node.arguments;
 
-          checkForRestrictedImportPath(firstArgument.value, firstArgument)
+          checkForRestrictedImportPath(firstArgument.value, firstArgument);
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-self-import.js b/src/rules/no-self-import.js
index b869d46e06..a90ba13fbe 100644
--- a/src/rules/no-self-import.js
+++ b/src/rules/no-self-import.js
@@ -3,19 +3,19 @@
  * @author Gio d'Amelio
  */
 
-import resolve from 'eslint-module-utils/resolve'
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
+import resolve from 'eslint-module-utils/resolve';
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
 
 function isImportingSelf(context, node, requireName) {
-  const filePath = context.getFilename()
+  const filePath = context.getFilename();
 
   // If the input is from stdin, this test can't fail
   if (filePath !== '<text>' && filePath === resolve(requireName, context)) {
     context.report({
         node,
         message: 'Module imports itself.',
-    })
+    });
   }
 }
 
@@ -33,13 +33,13 @@ module.exports = {
   create: function (context) {
     return {
       ImportDeclaration(node) {
-        isImportingSelf(context, node, node.source.value)
+        isImportingSelf(context, node, node.source.value);
       },
       CallExpression(node) {
         if (isStaticRequire(node)) {
-          isImportingSelf(context, node, node.arguments[0].value)
+          isImportingSelf(context, node, node.arguments[0].value);
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-unassigned-import.js b/src/rules/no-unassigned-import.js
index 5ea637e67b..ed292e9128 100644
--- a/src/rules/no-unassigned-import.js
+++ b/src/rules/no-unassigned-import.js
@@ -1,54 +1,54 @@
-import path from 'path'
-import minimatch from 'minimatch'
+import path from 'path';
+import minimatch from 'minimatch';
 
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
 
 function report(context, node) {
   context.report({
     node,
     message: 'Imported module should be assigned',
-  })
+  });
 }
 
 function testIsAllow(globs, filename, source) {
   if (!Array.isArray(globs)) {
-    return false // default doesn't allow any patterns
+    return false; // default doesn't allow any patterns
   }
 
-  let filePath
+  let filePath;
 
   if (source[0] !== '.' && source[0] !== '/') { // a node module
-    filePath = source
+    filePath = source;
   } else {
-    filePath = path.resolve(path.dirname(filename), source) // get source absolute path
+    filePath = path.resolve(path.dirname(filename), source); // get source absolute path
   }
 
   return globs.find(glob => (
     minimatch(filePath, glob) ||
     minimatch(filePath, path.join(process.cwd(), glob))
-  )) !== undefined
+  )) !== undefined;
 }
 
 function create(context) {
-  const options = context.options[0] || {}
-  const filename = context.getFilename()
-  const isAllow = source => testIsAllow(options.allow, filename, source)
+  const options = context.options[0] || {};
+  const filename = context.getFilename();
+  const isAllow = source => testIsAllow(options.allow, filename, source);
 
   return {
     ImportDeclaration(node) {
       if (node.specifiers.length === 0 && !isAllow(node.source.value)) {
-        report(context, node)
+        report(context, node);
       }
     },
     ExpressionStatement(node) {
       if (node.expression.type === 'CallExpression' &&
         isStaticRequire(node.expression) &&
         !isAllow(node.expression.arguments[0].value)) {
-        report(context, node.expression)
+        report(context, node.expression);
       }
     },
-  }
+  };
 }
 
 module.exports = {
@@ -76,4 +76,4 @@ module.exports = {
       },
     ],
   },
-}
+};
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index 8436e4c92b..61dc0b6c70 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -3,10 +3,10 @@
  * @author Ben Mosher
  */
 
-import resolve, { CASE_SENSITIVE_FS, fileExistsWithCaseSync } from 'eslint-module-utils/resolve'
-import ModuleCache from 'eslint-module-utils/ModuleCache'
-import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor'
-import docsUrl from '../docsUrl'
+import resolve, { CASE_SENSITIVE_FS, fileExistsWithCaseSync } from 'eslint-module-utils/resolve';
+import ModuleCache from 'eslint-module-utils/ModuleCache';
+import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -24,26 +24,26 @@ module.exports = {
 
     function checkSourceValue(source) {
       const shouldCheckCase = !CASE_SENSITIVE_FS &&
-        (!context.options[0] || context.options[0].caseSensitive !== false)
+        (!context.options[0] || context.options[0].caseSensitive !== false);
 
-      const resolvedPath = resolve(source.value, context)
+      const resolvedPath = resolve(source.value, context);
 
       if (resolvedPath === undefined) {
         context.report(source,
-          `Unable to resolve path to module '${source.value}'.`)
+          `Unable to resolve path to module '${source.value}'.`);
       }
 
       else if (shouldCheckCase) {
-        const cacheSettings = ModuleCache.getSettings(context.settings)
+        const cacheSettings = ModuleCache.getSettings(context.settings);
         if (!fileExistsWithCaseSync(resolvedPath, cacheSettings)) {
           context.report(source,
-            `Casing of ${source.value} does not match the underlying filesystem.`)
+            `Casing of ${source.value} does not match the underlying filesystem.`);
         }
 
       }
     }
 
-    return moduleVisitor(checkSourceValue, context.options[0])
+    return moduleVisitor(checkSourceValue, context.options[0]);
 
   },
-}
+};
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 9f38ac8e1c..cb60784c7c 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -4,69 +4,69 @@
  * @author René Fermann
  */
 
-import Exports from '../ExportMap'
-import { getFileExtensions } from 'eslint-module-utils/ignore'
-import resolve from 'eslint-module-utils/resolve'
-import docsUrl from '../docsUrl'
-import { dirname, join } from 'path'
-import readPkgUp from 'read-pkg-up'
-import values from 'object.values'
-import includes from 'array-includes'
+import Exports from '../ExportMap';
+import { getFileExtensions } from 'eslint-module-utils/ignore';
+import resolve from 'eslint-module-utils/resolve';
+import docsUrl from '../docsUrl';
+import { dirname, join } from 'path';
+import readPkgUp from 'read-pkg-up';
+import values from 'object.values';
+import includes from 'array-includes';
 
 // eslint/lib/util/glob-util has been moved to eslint/lib/util/glob-utils with version 5.3
 // and has been moved to eslint/lib/cli-engine/file-enumerator in version 6
-let listFilesToProcess
+let listFilesToProcess;
 try {
-  const FileEnumerator = require('eslint/lib/cli-engine/file-enumerator').FileEnumerator
+  const FileEnumerator = require('eslint/lib/cli-engine/file-enumerator').FileEnumerator;
   listFilesToProcess = function (src, extensions) {
     const e = new FileEnumerator({
       extensions: extensions,
-    })
+    });
     return Array.from(e.iterateFiles(src), ({ filePath, ignored }) => ({
       ignored,
       filename: filePath,
-    }))
-  }
+    }));
+  };
 } catch (e1) {
   // Prevent passing invalid options (extensions array) to old versions of the function.
   // https://github.com/eslint/eslint/blob/v5.16.0/lib/util/glob-utils.js#L178-L280
   // https://github.com/eslint/eslint/blob/v5.2.0/lib/util/glob-util.js#L174-L269
-  let originalListFilesToProcess
+  let originalListFilesToProcess;
   try {
-    originalListFilesToProcess = require('eslint/lib/util/glob-utils').listFilesToProcess
+    originalListFilesToProcess = require('eslint/lib/util/glob-utils').listFilesToProcess;
     listFilesToProcess = function (src, extensions) {
       return originalListFilesToProcess(src, {
         extensions: extensions,
-      })
-    }
+      });
+    };
   } catch (e2) {
-    originalListFilesToProcess = require('eslint/lib/util/glob-util').listFilesToProcess
+    originalListFilesToProcess = require('eslint/lib/util/glob-util').listFilesToProcess;
 
     listFilesToProcess = function (src, extensions) {
       const patterns = src.reduce((carry, pattern) => {
         return carry.concat(extensions.map((extension) => {
-          return /\*\*|\*\./.test(pattern) ? pattern : `${pattern}/**/*${extension}`
-        }))
-      }, src.slice())
+          return /\*\*|\*\./.test(pattern) ? pattern : `${pattern}/**/*${extension}`;
+        }));
+      }, src.slice());
 
-      return originalListFilesToProcess(patterns)
-    }
+      return originalListFilesToProcess(patterns);
+    };
   }
 }
 
-const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration'
-const EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration'
-const EXPORT_ALL_DECLARATION = 'ExportAllDeclaration'
-const IMPORT_DECLARATION = 'ImportDeclaration'
-const IMPORT_NAMESPACE_SPECIFIER = 'ImportNamespaceSpecifier'
-const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier'
-const VARIABLE_DECLARATION = 'VariableDeclaration'
-const FUNCTION_DECLARATION = 'FunctionDeclaration'
-const CLASS_DECLARATION = 'ClassDeclaration'
-const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration'
-const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration'
-const TS_ENUM_DECLARATION = 'TSEnumDeclaration'
-const DEFAULT = 'default'
+const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration';
+const EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration';
+const EXPORT_ALL_DECLARATION = 'ExportAllDeclaration';
+const IMPORT_DECLARATION = 'ImportDeclaration';
+const IMPORT_NAMESPACE_SPECIFIER = 'ImportNamespaceSpecifier';
+const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier';
+const VARIABLE_DECLARATION = 'VariableDeclaration';
+const FUNCTION_DECLARATION = 'FunctionDeclaration';
+const CLASS_DECLARATION = 'ClassDeclaration';
+const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration';
+const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration';
+const TS_ENUM_DECLARATION = 'TSEnumDeclaration';
+const DEFAULT = 'default';
 
 function forEachDeclarationIdentifier(declaration, cb) {
   if (declaration) {
@@ -77,11 +77,11 @@ function forEachDeclarationIdentifier(declaration, cb) {
       declaration.type === TS_TYPE_ALIAS_DECLARATION ||
       declaration.type === TS_ENUM_DECLARATION
     ) {
-      cb(declaration.id.name)
+      cb(declaration.id.name);
     } else if (declaration.type === VARIABLE_DECLARATION) {
       declaration.declarations.forEach(({ id }) => {
-        cb(id.name)
-      })
+        cb(id.name);
+      });
     }
   }
 }
@@ -105,7 +105,7 @@ function forEachDeclarationIdentifier(declaration, cb) {
  *
  * @type {Map<string, Map<string, Set<string>>>}
  */
-const importList = new Map()
+const importList = new Map();
 
 /**
  * List of exports per file.
@@ -132,14 +132,14 @@ const importList = new Map()
  *
  * @type {Map<string, Map<string, object>>}
  */
-const exportList = new Map()
+const exportList = new Map();
 
-const ignoredFiles = new Set()
-const filesOutsideSrc = new Set()
+const ignoredFiles = new Set();
+const filesOutsideSrc = new Set();
 
 const isNodeModule = path => {
-  return /\/(node_modules)\//.test(path)
-}
+  return /\/(node_modules)\//.test(path);
+};
 
 /**
  * read all files matching the patterns in src and ignoreExports
@@ -147,109 +147,109 @@ const isNodeModule = path => {
  * return all files matching src pattern, which are not matching the ignoreExports pattern
  */
 const resolveFiles = (src, ignoreExports, context) => {
-  const extensions = Array.from(getFileExtensions(context.settings))
+  const extensions = Array.from(getFileExtensions(context.settings));
 
-  const srcFiles = new Set()
-  const srcFileList = listFilesToProcess(src, extensions)
+  const srcFiles = new Set();
+  const srcFileList = listFilesToProcess(src, extensions);
 
   // prepare list of ignored files
-  const ignoredFilesList =  listFilesToProcess(ignoreExports, extensions)
-  ignoredFilesList.forEach(({ filename }) => ignoredFiles.add(filename))
+  const ignoredFilesList =  listFilesToProcess(ignoreExports, extensions);
+  ignoredFilesList.forEach(({ filename }) => ignoredFiles.add(filename));
 
   // prepare list of source files, don't consider files from node_modules
   srcFileList.filter(({ filename }) => !isNodeModule(filename)).forEach(({ filename }) => {
-    srcFiles.add(filename)
-  })
-  return srcFiles
-}
+    srcFiles.add(filename);
+  });
+  return srcFiles;
+};
 
 /**
  * parse all source files and build up 2 maps containing the existing imports and exports
  */
 const prepareImportsAndExports = (srcFiles, context) => {
-  const exportAll = new Map()
+  const exportAll = new Map();
   srcFiles.forEach(file => {
-    const exports = new Map()
-    const imports = new Map()
-    const currentExports = Exports.get(file, context)
+    const exports = new Map();
+    const imports = new Map();
+    const currentExports = Exports.get(file, context);
     if (currentExports) {
-      const { dependencies, reexports, imports: localImportList, namespace  } = currentExports
+      const { dependencies, reexports, imports: localImportList, namespace  } = currentExports;
 
       // dependencies === export * from
-      const currentExportAll = new Set()
+      const currentExportAll = new Set();
       dependencies.forEach(getDependency => {
-        const dependency = getDependency()
+        const dependency = getDependency();
         if (dependency === null) {
-          return
+          return;
         }
 
-        currentExportAll.add(dependency.path)
-      })
-      exportAll.set(file, currentExportAll)
+        currentExportAll.add(dependency.path);
+      });
+      exportAll.set(file, currentExportAll);
 
       reexports.forEach((value, key) => {
         if (key === DEFAULT) {
-          exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed: new Set() })
+          exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed: new Set() });
         } else {
-          exports.set(key, { whereUsed: new Set() })
+          exports.set(key, { whereUsed: new Set() });
         }
-        const reexport =  value.getImport()
+        const reexport =  value.getImport();
         if (!reexport) {
-          return
+          return;
         }
-        let localImport = imports.get(reexport.path)
-        let currentValue
+        let localImport = imports.get(reexport.path);
+        let currentValue;
         if (value.local === DEFAULT) {
-          currentValue = IMPORT_DEFAULT_SPECIFIER
+          currentValue = IMPORT_DEFAULT_SPECIFIER;
         } else {
-          currentValue = value.local
+          currentValue = value.local;
         }
         if (typeof localImport !== 'undefined') {
-          localImport = new Set([...localImport, currentValue])
+          localImport = new Set([...localImport, currentValue]);
         } else {
-          localImport = new Set([currentValue])
+          localImport = new Set([currentValue]);
         }
-        imports.set(reexport.path, localImport)
-      })
+        imports.set(reexport.path, localImport);
+      });
 
       localImportList.forEach((value, key) => {
         if (isNodeModule(key)) {
-          return
+          return;
         }
-        let localImport = imports.get(key)
+        let localImport = imports.get(key);
         if (typeof localImport !== 'undefined') {
-          localImport = new Set([...localImport, ...value.importedSpecifiers])
+          localImport = new Set([...localImport, ...value.importedSpecifiers]);
         } else {
-          localImport = value.importedSpecifiers
+          localImport = value.importedSpecifiers;
         }
-        imports.set(key, localImport)
-      })
-      importList.set(file, imports)
+        imports.set(key, localImport);
+      });
+      importList.set(file, imports);
 
       // build up export list only, if file is not ignored
       if (ignoredFiles.has(file)) {
-        return
+        return;
       }
       namespace.forEach((value, key) => {
         if (key === DEFAULT) {
-          exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed: new Set() })
+          exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed: new Set() });
         } else {
-          exports.set(key, { whereUsed: new Set() })
+          exports.set(key, { whereUsed: new Set() });
         }
-      })
+      });
     }
-    exports.set(EXPORT_ALL_DECLARATION, { whereUsed: new Set() })
-    exports.set(IMPORT_NAMESPACE_SPECIFIER, { whereUsed: new Set() })
-    exportList.set(file, exports)
-  })
+    exports.set(EXPORT_ALL_DECLARATION, { whereUsed: new Set() });
+    exports.set(IMPORT_NAMESPACE_SPECIFIER, { whereUsed: new Set() });
+    exportList.set(file, exports);
+  });
   exportAll.forEach((value, key) => {
     value.forEach(val => {
-      const currentExports = exportList.get(val)
-      const currentExport = currentExports.get(EXPORT_ALL_DECLARATION)
-      currentExport.whereUsed.add(key)
-    })
-  })
-}
+      const currentExports = exportList.get(val);
+      const currentExport = currentExports.get(EXPORT_ALL_DECLARATION);
+      currentExport.whereUsed.add(key);
+    });
+  });
+};
 
 /**
  * traverse through all imports and add the respective path to the whereUsed-list
@@ -258,122 +258,122 @@ const prepareImportsAndExports = (srcFiles, context) => {
 const determineUsage = () => {
   importList.forEach((listValue, listKey) => {
     listValue.forEach((value, key) => {
-      const exports = exportList.get(key)
+      const exports = exportList.get(key);
       if (typeof exports !== 'undefined') {
         value.forEach(currentImport => {
-          let specifier
+          let specifier;
           if (currentImport === IMPORT_NAMESPACE_SPECIFIER) {
-            specifier = IMPORT_NAMESPACE_SPECIFIER
+            specifier = IMPORT_NAMESPACE_SPECIFIER;
           } else if (currentImport === IMPORT_DEFAULT_SPECIFIER) {
-            specifier = IMPORT_DEFAULT_SPECIFIER
+            specifier = IMPORT_DEFAULT_SPECIFIER;
           } else {
-            specifier = currentImport
+            specifier = currentImport;
           }
           if (typeof specifier !== 'undefined') {
-            const exportStatement = exports.get(specifier)
+            const exportStatement = exports.get(specifier);
             if (typeof exportStatement !== 'undefined') {
-              const { whereUsed } = exportStatement
-              whereUsed.add(listKey)
-              exports.set(specifier, { whereUsed })
+              const { whereUsed } = exportStatement;
+              whereUsed.add(listKey);
+              exports.set(specifier, { whereUsed });
             }
           }
-        })
+        });
       }
-    })
-  })
-}
+    });
+  });
+};
 
 const getSrc = src => {
   if (src) {
-    return src
+    return src;
   }
-  return [process.cwd()]
-}
+  return [process.cwd()];
+};
 
 /**
  * prepare the lists of existing imports and exports - should only be executed once at
  * the start of a new eslint run
  */
-let srcFiles
-let lastPrepareKey
+let srcFiles;
+let lastPrepareKey;
 const doPreparation = (src, ignoreExports, context) => {
   const prepareKey = JSON.stringify({
     src: (src || []).sort(),
     ignoreExports: (ignoreExports || []).sort(),
     extensions: Array.from(getFileExtensions(context.settings)).sort(),
-  })
+  });
   if (prepareKey === lastPrepareKey) {
-    return
+    return;
   }
 
-  importList.clear()
-  exportList.clear()
-  ignoredFiles.clear()
-  filesOutsideSrc.clear()
+  importList.clear();
+  exportList.clear();
+  ignoredFiles.clear();
+  filesOutsideSrc.clear();
 
-  srcFiles = resolveFiles(getSrc(src), ignoreExports, context)
-  prepareImportsAndExports(srcFiles, context)
-  determineUsage()
-  lastPrepareKey = prepareKey
-}
+  srcFiles = resolveFiles(getSrc(src), ignoreExports, context);
+  prepareImportsAndExports(srcFiles, context);
+  determineUsage();
+  lastPrepareKey = prepareKey;
+};
 
 const newNamespaceImportExists = specifiers =>
-  specifiers.some(({ type }) => type === IMPORT_NAMESPACE_SPECIFIER)
+  specifiers.some(({ type }) => type === IMPORT_NAMESPACE_SPECIFIER);
 
 const newDefaultImportExists = specifiers =>
-  specifiers.some(({ type }) => type === IMPORT_DEFAULT_SPECIFIER)
+  specifiers.some(({ type }) => type === IMPORT_DEFAULT_SPECIFIER);
 
 const fileIsInPkg = file => {
-  const { path, pkg } = readPkgUp.sync({cwd: file, normalize: false})
-  const basePath = dirname(path)
+  const { path, pkg } = readPkgUp.sync({cwd: file, normalize: false});
+  const basePath = dirname(path);
 
   const checkPkgFieldString = pkgField => {
     if (join(basePath, pkgField) === file) {
-        return true
+        return true;
       }
-  }
+  };
 
   const checkPkgFieldObject = pkgField => {
-      const pkgFieldFiles = values(pkgField).map(value => join(basePath, value))
+      const pkgFieldFiles = values(pkgField).map(value => join(basePath, value));
       if (includes(pkgFieldFiles, file)) {
-        return true
+        return true;
       }
-  }
+  };
 
   const checkPkgField = pkgField => {
     if (typeof pkgField === 'string') {
-      return checkPkgFieldString(pkgField)
+      return checkPkgFieldString(pkgField);
     }
 
     if (typeof pkgField === 'object') {
-      return checkPkgFieldObject(pkgField)
+      return checkPkgFieldObject(pkgField);
     }
-  }
+  };
 
   if (pkg.private === true) {
-    return false
+    return false;
   }
 
   if (pkg.bin) {
     if (checkPkgField(pkg.bin)) {
-      return true
+      return true;
     }
   }
 
   if (pkg.browser) {
     if (checkPkgField(pkg.browser)) {
-      return true
+      return true;
     }
   }
 
   if (pkg.main) {
     if (checkPkgFieldString(pkg.main)) {
-      return true
+      return true;
     }
   }
 
-  return false
-}
+  return false;
+};
 
 module.exports = {
   meta: {
@@ -449,103 +449,103 @@ module.exports = {
       ignoreExports = [],
       missingExports,
       unusedExports,
-    } = context.options[0] || {}
+    } = context.options[0] || {};
 
     if (unusedExports) {
-      doPreparation(src, ignoreExports, context)
+      doPreparation(src, ignoreExports, context);
     }
 
-    const file = context.getFilename()
+    const file = context.getFilename();
 
     const checkExportPresence = node => {
       if (!missingExports) {
-        return
+        return;
       }
 
       if (ignoredFiles.has(file)) {
-        return
+        return;
       }
 
-      const exportCount = exportList.get(file)
-      const exportAll = exportCount.get(EXPORT_ALL_DECLARATION)
-      const namespaceImports = exportCount.get(IMPORT_NAMESPACE_SPECIFIER)
+      const exportCount = exportList.get(file);
+      const exportAll = exportCount.get(EXPORT_ALL_DECLARATION);
+      const namespaceImports = exportCount.get(IMPORT_NAMESPACE_SPECIFIER);
 
-      exportCount.delete(EXPORT_ALL_DECLARATION)
-      exportCount.delete(IMPORT_NAMESPACE_SPECIFIER)
+      exportCount.delete(EXPORT_ALL_DECLARATION);
+      exportCount.delete(IMPORT_NAMESPACE_SPECIFIER);
       if (exportCount.size < 1) {
         // node.body[0] === 'undefined' only happens, if everything is commented out in the file
         // being linted
-        context.report(node.body[0] ? node.body[0] : node, 'No exports found')
+        context.report(node.body[0] ? node.body[0] : node, 'No exports found');
       }
-      exportCount.set(EXPORT_ALL_DECLARATION, exportAll)
-      exportCount.set(IMPORT_NAMESPACE_SPECIFIER, namespaceImports)
-    }
+      exportCount.set(EXPORT_ALL_DECLARATION, exportAll);
+      exportCount.set(IMPORT_NAMESPACE_SPECIFIER, namespaceImports);
+    };
 
     const checkUsage = (node, exportedValue) => {
       if (!unusedExports) {
-        return
+        return;
       }
 
       if (ignoredFiles.has(file)) {
-        return
+        return;
       }
 
       if (fileIsInPkg(file)) {
-        return
+        return;
       }
 
       if (filesOutsideSrc.has(file)) {
-        return
+        return;
       }
 
       // make sure file to be linted is included in source files
       if (!srcFiles.has(file)) {
-        srcFiles = resolveFiles(getSrc(src), ignoreExports, context)
+        srcFiles = resolveFiles(getSrc(src), ignoreExports, context);
         if (!srcFiles.has(file)) {
-          filesOutsideSrc.add(file)
-          return
+          filesOutsideSrc.add(file);
+          return;
         }
       }
 
-      exports = exportList.get(file)
+      exports = exportList.get(file);
 
       // special case: export * from
-      const exportAll = exports.get(EXPORT_ALL_DECLARATION)
+      const exportAll = exports.get(EXPORT_ALL_DECLARATION);
       if (typeof exportAll !== 'undefined' && exportedValue !== IMPORT_DEFAULT_SPECIFIER) {
         if (exportAll.whereUsed.size > 0) {
-          return
+          return;
         }
       }
 
       // special case: namespace import
-      const namespaceImports = exports.get(IMPORT_NAMESPACE_SPECIFIER)
+      const namespaceImports = exports.get(IMPORT_NAMESPACE_SPECIFIER);
       if (typeof namespaceImports !== 'undefined') {
         if (namespaceImports.whereUsed.size > 0) {
-          return
+          return;
         }
       }
 
       // exportsList will always map any imported value of 'default' to 'ImportDefaultSpecifier'
-      const exportsKey = exportedValue === DEFAULT ? IMPORT_DEFAULT_SPECIFIER : exportedValue
+      const exportsKey = exportedValue === DEFAULT ? IMPORT_DEFAULT_SPECIFIER : exportedValue;
 
-      const exportStatement = exports.get(exportsKey)
+      const exportStatement = exports.get(exportsKey);
 
-      const value = exportsKey === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportsKey
+      const value = exportsKey === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportsKey;
 
       if (typeof exportStatement !== 'undefined'){
         if (exportStatement.whereUsed.size < 1) {
           context.report(
             node,
             `exported declaration '${value}' not used within other modules`
-          )
+          );
         }
       } else {
         context.report(
           node,
           `exported declaration '${value}' not used within other modules`
-        )
+        );
       }
-    }
+    };
 
     /**
      * only useful for tools like vscode-eslint
@@ -554,64 +554,64 @@ module.exports = {
      */
     const updateExportUsage = node => {
       if (ignoredFiles.has(file)) {
-        return
+        return;
       }
 
-      let exports = exportList.get(file)
+      let exports = exportList.get(file);
 
       // new module has been created during runtime
       // include it in further processing
       if (typeof exports === 'undefined') {
-        exports = new Map()
+        exports = new Map();
       }
 
-      const newExports = new Map()
-      const newExportIdentifiers = new Set()
+      const newExports = new Map();
+      const newExportIdentifiers = new Set();
 
       node.body.forEach(({ type, declaration, specifiers }) => {
         if (type === EXPORT_DEFAULT_DECLARATION) {
-          newExportIdentifiers.add(IMPORT_DEFAULT_SPECIFIER)
+          newExportIdentifiers.add(IMPORT_DEFAULT_SPECIFIER);
         }
         if (type === EXPORT_NAMED_DECLARATION) {
           if (specifiers.length > 0) {
             specifiers.forEach(specifier => {
               if (specifier.exported) {
-                newExportIdentifiers.add(specifier.exported.name)
+                newExportIdentifiers.add(specifier.exported.name);
               }
-            })
+            });
           }
           forEachDeclarationIdentifier(declaration, (name) => {
-            newExportIdentifiers.add(name)
-          })
+            newExportIdentifiers.add(name);
+          });
         }
-      })
+      });
 
       // old exports exist within list of new exports identifiers: add to map of new exports
       exports.forEach((value, key) => {
         if (newExportIdentifiers.has(key)) {
-          newExports.set(key, value)
+          newExports.set(key, value);
         }
-      })
+      });
 
       // new export identifiers added: add to map of new exports
       newExportIdentifiers.forEach(key => {
         if (!exports.has(key)) {
-          newExports.set(key, { whereUsed: new Set() })
+          newExports.set(key, { whereUsed: new Set() });
         }
-      })
+      });
 
       // preserve information about namespace imports
-      let exportAll = exports.get(EXPORT_ALL_DECLARATION)
-      let namespaceImports = exports.get(IMPORT_NAMESPACE_SPECIFIER)
+      let exportAll = exports.get(EXPORT_ALL_DECLARATION);
+      let namespaceImports = exports.get(IMPORT_NAMESPACE_SPECIFIER);
 
       if (typeof namespaceImports === 'undefined') {
-        namespaceImports = { whereUsed: new Set() }
+        namespaceImports = { whereUsed: new Set() };
       }
 
-      newExports.set(EXPORT_ALL_DECLARATION, exportAll)
-      newExports.set(IMPORT_NAMESPACE_SPECIFIER, namespaceImports)
-      exportList.set(file, newExports)
-    }
+      newExports.set(EXPORT_ALL_DECLARATION, exportAll);
+      newExports.set(IMPORT_NAMESPACE_SPECIFIER, namespaceImports);
+      exportList.set(file, newExports);
+    };
 
     /**
      * only useful for tools like vscode-eslint
@@ -620,284 +620,284 @@ module.exports = {
      */
     const updateImportUsage = node => {
       if (!unusedExports) {
-        return
+        return;
       }
 
-      let oldImportPaths = importList.get(file)
+      let oldImportPaths = importList.get(file);
       if (typeof oldImportPaths === 'undefined') {
-        oldImportPaths = new Map()
+        oldImportPaths = new Map();
       }
 
-      const oldNamespaceImports = new Set()
-      const newNamespaceImports = new Set()
+      const oldNamespaceImports = new Set();
+      const newNamespaceImports = new Set();
 
-      const oldExportAll = new Set()
-      const newExportAll = new Set()
+      const oldExportAll = new Set();
+      const newExportAll = new Set();
 
-      const oldDefaultImports = new Set()
-      const newDefaultImports = new Set()
+      const oldDefaultImports = new Set();
+      const newDefaultImports = new Set();
 
-      const oldImports = new Map()
-      const newImports = new Map()
+      const oldImports = new Map();
+      const newImports = new Map();
       oldImportPaths.forEach((value, key) => {
         if (value.has(EXPORT_ALL_DECLARATION)) {
-          oldExportAll.add(key)
+          oldExportAll.add(key);
         }
         if (value.has(IMPORT_NAMESPACE_SPECIFIER)) {
-          oldNamespaceImports.add(key)
+          oldNamespaceImports.add(key);
         }
         if (value.has(IMPORT_DEFAULT_SPECIFIER)) {
-          oldDefaultImports.add(key)
+          oldDefaultImports.add(key);
         }
         value.forEach(val => {
           if (val !== IMPORT_NAMESPACE_SPECIFIER &&
               val !== IMPORT_DEFAULT_SPECIFIER) {
-               oldImports.set(val, key)
+               oldImports.set(val, key);
              }
-        })
-      })
+        });
+      });
 
       node.body.forEach(astNode => {
-        let resolvedPath
+        let resolvedPath;
 
         // support for export { value } from 'module'
         if (astNode.type === EXPORT_NAMED_DECLARATION) {
           if (astNode.source) {
-            resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context)
+            resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context);
             astNode.specifiers.forEach(specifier => {
-              const name = specifier.local.name
+              const name = specifier.local.name;
               if (specifier.local.name === DEFAULT) {
-                newDefaultImports.add(resolvedPath)
+                newDefaultImports.add(resolvedPath);
               } else {
-                newImports.set(name, resolvedPath)
+                newImports.set(name, resolvedPath);
               }
-            })
+            });
           }
         }
 
         if (astNode.type === EXPORT_ALL_DECLARATION) {
-          resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context)
-          newExportAll.add(resolvedPath)
+          resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context);
+          newExportAll.add(resolvedPath);
         }
 
         if (astNode.type === IMPORT_DECLARATION) {
-          resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context)
+          resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context);
           if (!resolvedPath) {
-            return
+            return;
           }
 
           if (isNodeModule(resolvedPath)) {
-            return
+            return;
           }
 
           if (newNamespaceImportExists(astNode.specifiers)) {
-            newNamespaceImports.add(resolvedPath)
+            newNamespaceImports.add(resolvedPath);
           }
 
           if (newDefaultImportExists(astNode.specifiers)) {
-            newDefaultImports.add(resolvedPath)
+            newDefaultImports.add(resolvedPath);
           }
 
           astNode.specifiers.forEach(specifier => {
             if (specifier.type === IMPORT_DEFAULT_SPECIFIER ||
                 specifier.type === IMPORT_NAMESPACE_SPECIFIER) {
-              return
+              return;
             }
-            newImports.set(specifier.imported.name, resolvedPath)
-          })
+            newImports.set(specifier.imported.name, resolvedPath);
+          });
         }
-      })
+      });
 
       newExportAll.forEach(value => {
         if (!oldExportAll.has(value)) {
-          let imports = oldImportPaths.get(value)
+          let imports = oldImportPaths.get(value);
           if (typeof imports === 'undefined') {
-            imports = new Set()
+            imports = new Set();
           }
-          imports.add(EXPORT_ALL_DECLARATION)
-          oldImportPaths.set(value, imports)
+          imports.add(EXPORT_ALL_DECLARATION);
+          oldImportPaths.set(value, imports);
 
-          let exports = exportList.get(value)
-          let currentExport
+          let exports = exportList.get(value);
+          let currentExport;
           if (typeof exports !== 'undefined') {
-            currentExport = exports.get(EXPORT_ALL_DECLARATION)
+            currentExport = exports.get(EXPORT_ALL_DECLARATION);
           } else {
-            exports = new Map()
-            exportList.set(value, exports)
+            exports = new Map();
+            exportList.set(value, exports);
           }
 
           if (typeof currentExport !== 'undefined') {
-            currentExport.whereUsed.add(file)
+            currentExport.whereUsed.add(file);
           } else {
-            const whereUsed = new Set()
-            whereUsed.add(file)
-            exports.set(EXPORT_ALL_DECLARATION, { whereUsed })
+            const whereUsed = new Set();
+            whereUsed.add(file);
+            exports.set(EXPORT_ALL_DECLARATION, { whereUsed });
           }
         }
-      })
+      });
 
       oldExportAll.forEach(value => {
         if (!newExportAll.has(value)) {
-          const imports = oldImportPaths.get(value)
-          imports.delete(EXPORT_ALL_DECLARATION)
+          const imports = oldImportPaths.get(value);
+          imports.delete(EXPORT_ALL_DECLARATION);
 
-          const exports = exportList.get(value)
+          const exports = exportList.get(value);
           if (typeof exports !== 'undefined') {
-            const currentExport = exports.get(EXPORT_ALL_DECLARATION)
+            const currentExport = exports.get(EXPORT_ALL_DECLARATION);
             if (typeof currentExport !== 'undefined') {
-              currentExport.whereUsed.delete(file)
+              currentExport.whereUsed.delete(file);
             }
           }
         }
-      })
+      });
 
       newDefaultImports.forEach(value => {
         if (!oldDefaultImports.has(value)) {
-          let imports = oldImportPaths.get(value)
+          let imports = oldImportPaths.get(value);
           if (typeof imports === 'undefined') {
-            imports = new Set()
+            imports = new Set();
           }
-          imports.add(IMPORT_DEFAULT_SPECIFIER)
-          oldImportPaths.set(value, imports)
+          imports.add(IMPORT_DEFAULT_SPECIFIER);
+          oldImportPaths.set(value, imports);
 
-          let exports = exportList.get(value)
-          let currentExport
+          let exports = exportList.get(value);
+          let currentExport;
           if (typeof exports !== 'undefined') {
-            currentExport = exports.get(IMPORT_DEFAULT_SPECIFIER)
+            currentExport = exports.get(IMPORT_DEFAULT_SPECIFIER);
           } else {
-            exports = new Map()
-            exportList.set(value, exports)
+            exports = new Map();
+            exportList.set(value, exports);
           }
 
           if (typeof currentExport !== 'undefined') {
-            currentExport.whereUsed.add(file)
+            currentExport.whereUsed.add(file);
           } else {
-            const whereUsed = new Set()
-            whereUsed.add(file)
-            exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed })
+            const whereUsed = new Set();
+            whereUsed.add(file);
+            exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed });
           }
         }
-      })
+      });
 
       oldDefaultImports.forEach(value => {
         if (!newDefaultImports.has(value)) {
-          const imports = oldImportPaths.get(value)
-          imports.delete(IMPORT_DEFAULT_SPECIFIER)
+          const imports = oldImportPaths.get(value);
+          imports.delete(IMPORT_DEFAULT_SPECIFIER);
 
-          const exports = exportList.get(value)
+          const exports = exportList.get(value);
           if (typeof exports !== 'undefined') {
-            const currentExport = exports.get(IMPORT_DEFAULT_SPECIFIER)
+            const currentExport = exports.get(IMPORT_DEFAULT_SPECIFIER);
             if (typeof currentExport !== 'undefined') {
-              currentExport.whereUsed.delete(file)
+              currentExport.whereUsed.delete(file);
             }
           }
         }
-      })
+      });
 
       newNamespaceImports.forEach(value => {
         if (!oldNamespaceImports.has(value)) {
-          let imports = oldImportPaths.get(value)
+          let imports = oldImportPaths.get(value);
           if (typeof imports === 'undefined') {
-            imports = new Set()
+            imports = new Set();
           }
-          imports.add(IMPORT_NAMESPACE_SPECIFIER)
-          oldImportPaths.set(value, imports)
+          imports.add(IMPORT_NAMESPACE_SPECIFIER);
+          oldImportPaths.set(value, imports);
 
-          let exports = exportList.get(value)
-          let currentExport
+          let exports = exportList.get(value);
+          let currentExport;
           if (typeof exports !== 'undefined') {
-            currentExport = exports.get(IMPORT_NAMESPACE_SPECIFIER)
+            currentExport = exports.get(IMPORT_NAMESPACE_SPECIFIER);
           } else {
-            exports = new Map()
-            exportList.set(value, exports)
+            exports = new Map();
+            exportList.set(value, exports);
           }
 
           if (typeof currentExport !== 'undefined') {
-            currentExport.whereUsed.add(file)
+            currentExport.whereUsed.add(file);
           } else {
-            const whereUsed = new Set()
-            whereUsed.add(file)
-            exports.set(IMPORT_NAMESPACE_SPECIFIER, { whereUsed })
+            const whereUsed = new Set();
+            whereUsed.add(file);
+            exports.set(IMPORT_NAMESPACE_SPECIFIER, { whereUsed });
           }
         }
-      })
+      });
 
       oldNamespaceImports.forEach(value => {
         if (!newNamespaceImports.has(value)) {
-          const imports = oldImportPaths.get(value)
-          imports.delete(IMPORT_NAMESPACE_SPECIFIER)
+          const imports = oldImportPaths.get(value);
+          imports.delete(IMPORT_NAMESPACE_SPECIFIER);
 
-          const exports = exportList.get(value)
+          const exports = exportList.get(value);
           if (typeof exports !== 'undefined') {
-            const currentExport = exports.get(IMPORT_NAMESPACE_SPECIFIER)
+            const currentExport = exports.get(IMPORT_NAMESPACE_SPECIFIER);
             if (typeof currentExport !== 'undefined') {
-              currentExport.whereUsed.delete(file)
+              currentExport.whereUsed.delete(file);
             }
           }
         }
-      })
+      });
 
       newImports.forEach((value, key) => {
         if (!oldImports.has(key)) {
-          let imports = oldImportPaths.get(value)
+          let imports = oldImportPaths.get(value);
           if (typeof imports === 'undefined') {
-            imports = new Set()
+            imports = new Set();
           }
-          imports.add(key)
-          oldImportPaths.set(value, imports)
+          imports.add(key);
+          oldImportPaths.set(value, imports);
 
-          let exports = exportList.get(value)
-          let currentExport
+          let exports = exportList.get(value);
+          let currentExport;
           if (typeof exports !== 'undefined') {
-            currentExport = exports.get(key)
+            currentExport = exports.get(key);
           } else {
-            exports = new Map()
-            exportList.set(value, exports)
+            exports = new Map();
+            exportList.set(value, exports);
           }
 
           if (typeof currentExport !== 'undefined') {
-            currentExport.whereUsed.add(file)
+            currentExport.whereUsed.add(file);
           } else {
-            const whereUsed = new Set()
-            whereUsed.add(file)
-            exports.set(key, { whereUsed })
+            const whereUsed = new Set();
+            whereUsed.add(file);
+            exports.set(key, { whereUsed });
           }
         }
-      })
+      });
 
       oldImports.forEach((value, key) => {
         if (!newImports.has(key)) {
-          const imports = oldImportPaths.get(value)
-          imports.delete(key)
+          const imports = oldImportPaths.get(value);
+          imports.delete(key);
 
-          const exports = exportList.get(value)
+          const exports = exportList.get(value);
           if (typeof exports !== 'undefined') {
-            const currentExport = exports.get(key)
+            const currentExport = exports.get(key);
             if (typeof currentExport !== 'undefined') {
-              currentExport.whereUsed.delete(file)
+              currentExport.whereUsed.delete(file);
             }
           }
         }
-      })
-    }
+      });
+    };
 
     return {
       'Program:exit': node => {
-        updateExportUsage(node)
-        updateImportUsage(node)
-        checkExportPresence(node)
+        updateExportUsage(node);
+        updateImportUsage(node);
+        checkExportPresence(node);
       },
       'ExportDefaultDeclaration': node => {
-        checkUsage(node, IMPORT_DEFAULT_SPECIFIER)
+        checkUsage(node, IMPORT_DEFAULT_SPECIFIER);
       },
       'ExportNamedDeclaration': node => {
         node.specifiers.forEach(specifier => {
-            checkUsage(node, specifier.exported.name)
-        })
+            checkUsage(node, specifier.exported.name);
+        });
         forEachDeclarationIdentifier(node.declaration, (name) => {
-          checkUsage(node, name)
-        })
+          checkUsage(node, name);
+        });
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index 785b98f0d6..6bb12f4e0d 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -3,11 +3,11 @@
  * @author Thomas Grainger
  */
 
-import { getFileExtensions } from 'eslint-module-utils/ignore'
-import moduleVisitor from 'eslint-module-utils/moduleVisitor'
-import resolve from 'eslint-module-utils/resolve'
-import path from 'path'
-import docsUrl from '../docsUrl'
+import { getFileExtensions } from 'eslint-module-utils/ignore';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
+import resolve from 'eslint-module-utils/resolve';
+import path from 'path';
+import docsUrl from '../docsUrl';
 
 /**
  * convert a potentially relative path from node utils into a true
@@ -23,17 +23,17 @@ import docsUrl from '../docsUrl'
  * @returns {string} relative posix path that always starts with a ./
  **/
 function toRelativePath(relativePath) {
-  const stripped = relativePath.replace(/\/$/g, '') // Remove trailing /
+  const stripped = relativePath.replace(/\/$/g, ''); // Remove trailing /
 
-  return /^((\.\.)|(\.))($|\/)/.test(stripped) ? stripped : `./${stripped}`
+  return /^((\.\.)|(\.))($|\/)/.test(stripped) ? stripped : `./${stripped}`;
 }
 
 function normalize(fn) {
-  return toRelativePath(path.posix.normalize(fn))
+  return toRelativePath(path.posix.normalize(fn));
 }
 
 function countRelativeParents(pathSegments) {
-  return pathSegments.reduce((sum, pathSegment) => pathSegment === '..' ? sum + 1 : sum, 0)
+  return pathSegments.reduce((sum, pathSegment) => pathSegment === '..' ? sum + 1 : sum, 0);
 }
 
 module.exports = {
@@ -58,11 +58,11 @@ module.exports = {
   },
 
   create(context) {
-    const currentDir = path.dirname(context.getFilename())
-    const options = context.options[0]
+    const currentDir = path.dirname(context.getFilename());
+    const options = context.options[0];
 
     function checkSourceValue(source) {
-      const { value: importPath } = source
+      const { value: importPath } = source;
 
       function reportWithProposedPath(proposedPath) {
         context.report({
@@ -70,63 +70,63 @@ module.exports = {
           // Note: Using messageIds is not possible due to the support for ESLint 2 and 3
           message: `Useless path segments for "${importPath}", should be "${proposedPath}"`,
           fix: fixer => proposedPath && fixer.replaceText(source, JSON.stringify(proposedPath)),
-        })
+        });
       }
 
       // Only relative imports are relevant for this rule --> Skip checking
       if (!importPath.startsWith('.')) {
-        return
+        return;
       }
 
       // Report rule violation if path is not the shortest possible
-      const resolvedPath = resolve(importPath, context)
-      const normedPath = normalize(importPath)
-      const resolvedNormedPath = resolve(normedPath, context)
+      const resolvedPath = resolve(importPath, context);
+      const normedPath = normalize(importPath);
+      const resolvedNormedPath = resolve(normedPath, context);
       if (normedPath !== importPath && resolvedPath === resolvedNormedPath) {
-        return reportWithProposedPath(normedPath)
+        return reportWithProposedPath(normedPath);
       }
 
-      const fileExtensions = getFileExtensions(context.settings)
+      const fileExtensions = getFileExtensions(context.settings);
       const regexUnnecessaryIndex = new RegExp(
         `.*\\/index(\\${Array.from(fileExtensions).join('|\\')})?$`
-      )
+      );
 
       // Check if path contains unnecessary index (including a configured extension)
       if (options && options.noUselessIndex && regexUnnecessaryIndex.test(importPath)) {
-        const parentDirectory = path.dirname(importPath)
+        const parentDirectory = path.dirname(importPath);
 
         // Try to find ambiguous imports
         if (parentDirectory !== '.' && parentDirectory !== '..') {
           for (let fileExtension of fileExtensions) {
             if (resolve(`${parentDirectory}${fileExtension}`, context)) {
-              return reportWithProposedPath(`${parentDirectory}/`)
+              return reportWithProposedPath(`${parentDirectory}/`);
             }
           }
         }
 
-        return reportWithProposedPath(parentDirectory)
+        return reportWithProposedPath(parentDirectory);
       }
 
       // Path is shortest possible + starts from the current directory --> Return directly
       if (importPath.startsWith('./')) {
-        return
+        return;
       }
 
       // Path is not existing --> Return directly (following code requires path to be defined)
       if (resolvedPath === undefined) {
-        return
+        return;
       }
 
-      const expected = path.relative(currentDir, resolvedPath) // Expected import path
-      const expectedSplit = expected.split(path.sep) // Split by / or \ (depending on OS)
-      const importPathSplit = importPath.replace(/^\.\//, '').split('/')
-      const countImportPathRelativeParents = countRelativeParents(importPathSplit)
-      const countExpectedRelativeParents = countRelativeParents(expectedSplit)
-      const diff = countImportPathRelativeParents - countExpectedRelativeParents
+      const expected = path.relative(currentDir, resolvedPath); // Expected import path
+      const expectedSplit = expected.split(path.sep); // Split by / or \ (depending on OS)
+      const importPathSplit = importPath.replace(/^\.\//, '').split('/');
+      const countImportPathRelativeParents = countRelativeParents(importPathSplit);
+      const countExpectedRelativeParents = countRelativeParents(expectedSplit);
+      const diff = countImportPathRelativeParents - countExpectedRelativeParents;
 
       // Same number of relative parents --> Paths are the same --> Return directly
       if (diff <= 0) {
-        return
+        return;
       }
 
       // Report and propose minimal number of required relative parents
@@ -137,9 +137,9 @@ module.exports = {
             .concat(importPathSplit.slice(countImportPathRelativeParents + diff))
             .join('/')
         )
-      )
+      );
     }
 
-    return moduleVisitor(checkSourceValue, options)
+    return moduleVisitor(checkSourceValue, options);
   },
-}
+};
diff --git a/src/rules/no-webpack-loader-syntax.js b/src/rules/no-webpack-loader-syntax.js
index a80bc112d5..520a4cd240 100644
--- a/src/rules/no-webpack-loader-syntax.js
+++ b/src/rules/no-webpack-loader-syntax.js
@@ -1,11 +1,11 @@
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
 
 function reportIfNonStandard(context, node, name) {
   if (name && name.indexOf('!') !== -1) {
     context.report(node, `Unexpected '!' in '${name}'. ` +
       'Do not use import syntax to configure webpack loaders.'
-    )
+    );
   }
 }
 
@@ -21,13 +21,13 @@ module.exports = {
   create: function (context) {
     return {
       ImportDeclaration: function handleImports(node) {
-        reportIfNonStandard(context, node, node.source.value)
+        reportIfNonStandard(context, node, node.source.value);
       },
       CallExpression: function handleRequires(node) {
         if (isStaticRequire(node)) {
-          reportIfNonStandard(context, node, node.arguments[0].value)
+          reportIfNonStandard(context, node, node.arguments[0].value);
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/order.js b/src/rules/order.js
index fe2376cfe1..ef1eb75ed9 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -1,142 +1,142 @@
-'use strict'
+'use strict';
 
-import minimatch from 'minimatch'
-import importType from '../core/importType'
-import isStaticRequire from '../core/staticRequire'
-import docsUrl from '../docsUrl'
+import minimatch from 'minimatch';
+import importType from '../core/importType';
+import isStaticRequire from '../core/staticRequire';
+import docsUrl from '../docsUrl';
 
-const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index']
+const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index'];
 
 // REPORTING AND FIXING
 
 function reverse(array) {
   return array.map(function (v) {
-    return Object.assign({}, v, { rank: -v.rank })
-  }).reverse()
+    return Object.assign({}, v, { rank: -v.rank });
+  }).reverse();
 }
 
 function getTokensOrCommentsAfter(sourceCode, node, count) {
-  let currentNodeOrToken = node
-  const result = []
+  let currentNodeOrToken = node;
+  const result = [];
   for (let i = 0; i < count; i++) {
-    currentNodeOrToken = sourceCode.getTokenOrCommentAfter(currentNodeOrToken)
+    currentNodeOrToken = sourceCode.getTokenOrCommentAfter(currentNodeOrToken);
     if (currentNodeOrToken == null) {
-      break
+      break;
     }
-    result.push(currentNodeOrToken)
+    result.push(currentNodeOrToken);
   }
-  return result
+  return result;
 }
 
 function getTokensOrCommentsBefore(sourceCode, node, count) {
-  let currentNodeOrToken = node
-  const result = []
+  let currentNodeOrToken = node;
+  const result = [];
   for (let i = 0; i < count; i++) {
-    currentNodeOrToken = sourceCode.getTokenOrCommentBefore(currentNodeOrToken)
+    currentNodeOrToken = sourceCode.getTokenOrCommentBefore(currentNodeOrToken);
     if (currentNodeOrToken == null) {
-      break
+      break;
     }
-    result.push(currentNodeOrToken)
+    result.push(currentNodeOrToken);
   }
-  return result.reverse()
+  return result.reverse();
 }
 
 function takeTokensAfterWhile(sourceCode, node, condition) {
-  const tokens = getTokensOrCommentsAfter(sourceCode, node, 100)
-  const result = []
+  const tokens = getTokensOrCommentsAfter(sourceCode, node, 100);
+  const result = [];
   for (let i = 0; i < tokens.length; i++) {
     if (condition(tokens[i])) {
-      result.push(tokens[i])
+      result.push(tokens[i]);
     }
     else {
-      break
+      break;
     }
   }
-  return result
+  return result;
 }
 
 function takeTokensBeforeWhile(sourceCode, node, condition) {
-  const tokens = getTokensOrCommentsBefore(sourceCode, node, 100)
-  const result = []
+  const tokens = getTokensOrCommentsBefore(sourceCode, node, 100);
+  const result = [];
   for (let i = tokens.length - 1; i >= 0; i--) {
     if (condition(tokens[i])) {
-      result.push(tokens[i])
+      result.push(tokens[i]);
     }
     else {
-      break
+      break;
     }
   }
-  return result.reverse()
+  return result.reverse();
 }
 
 function findOutOfOrder(imported) {
   if (imported.length === 0) {
-    return []
+    return [];
   }
-  let maxSeenRankNode = imported[0]
+  let maxSeenRankNode = imported[0];
   return imported.filter(function (importedModule) {
-    const res = importedModule.rank < maxSeenRankNode.rank
+    const res = importedModule.rank < maxSeenRankNode.rank;
     if (maxSeenRankNode.rank < importedModule.rank) {
-      maxSeenRankNode = importedModule
+      maxSeenRankNode = importedModule;
     }
-    return res
-  })
+    return res;
+  });
 }
 
 function findRootNode(node) {
-  let parent = node
+  let parent = node;
   while (parent.parent != null && parent.parent.body == null) {
-    parent = parent.parent
+    parent = parent.parent;
   }
-  return parent
+  return parent;
 }
 
 function findEndOfLineWithComments(sourceCode, node) {
-  const tokensToEndOfLine = takeTokensAfterWhile(sourceCode, node, commentOnSameLineAs(node))
+  const tokensToEndOfLine = takeTokensAfterWhile(sourceCode, node, commentOnSameLineAs(node));
   let endOfTokens = tokensToEndOfLine.length > 0
     ? tokensToEndOfLine[tokensToEndOfLine.length - 1].range[1]
-    : node.range[1]
-  let result = endOfTokens
+    : node.range[1];
+  let result = endOfTokens;
   for (let i = endOfTokens; i < sourceCode.text.length; i++) {
     if (sourceCode.text[i] === '\n') {
-      result = i + 1
-      break
+      result = i + 1;
+      break;
     }
     if (sourceCode.text[i] !== ' ' && sourceCode.text[i] !== '\t' && sourceCode.text[i] !== '\r') {
-      break
+      break;
     }
-    result = i + 1
+    result = i + 1;
   }
-  return result
+  return result;
 }
 
 function commentOnSameLineAs(node) {
   return token => (token.type === 'Block' ||  token.type === 'Line') &&
       token.loc.start.line === token.loc.end.line &&
-      token.loc.end.line === node.loc.end.line
+      token.loc.end.line === node.loc.end.line;
 }
 
 function findStartOfLineWithComments(sourceCode, node) {
-  const tokensToEndOfLine = takeTokensBeforeWhile(sourceCode, node, commentOnSameLineAs(node))
-  let startOfTokens = tokensToEndOfLine.length > 0 ? tokensToEndOfLine[0].range[0] : node.range[0]
-  let result = startOfTokens
+  const tokensToEndOfLine = takeTokensBeforeWhile(sourceCode, node, commentOnSameLineAs(node));
+  let startOfTokens = tokensToEndOfLine.length > 0 ? tokensToEndOfLine[0].range[0] : node.range[0];
+  let result = startOfTokens;
   for (let i = startOfTokens - 1; i > 0; i--) {
     if (sourceCode.text[i] !== ' ' && sourceCode.text[i] !== '\t') {
-      break
+      break;
     }
-    result = i
+    result = i;
   }
-  return result
+  return result;
 }
 
 function isPlainRequireModule(node) {
   if (node.type !== 'VariableDeclaration') {
-    return false
+    return false;
   }
   if (node.declarations.length !== 1) {
-    return false
+    return false;
   }
-  const decl = node.declarations[0]
+  const decl = node.declarations[0];
   const result = decl.id &&
     (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') &&
     decl.init != null &&
@@ -145,55 +145,55 @@ function isPlainRequireModule(node) {
     decl.init.callee.name === 'require' &&
     decl.init.arguments != null &&
     decl.init.arguments.length === 1 &&
-    decl.init.arguments[0].type === 'Literal'
-  return result
+    decl.init.arguments[0].type === 'Literal';
+  return result;
 }
 
 function isPlainImportModule(node) {
-  return node.type === 'ImportDeclaration' && node.specifiers != null && node.specifiers.length > 0
+  return node.type === 'ImportDeclaration' && node.specifiers != null && node.specifiers.length > 0;
 }
 
 function isPlainImportEquals(node) {
-  return node.type === 'TSImportEqualsDeclaration' && node.moduleReference.expression
+  return node.type === 'TSImportEqualsDeclaration' && node.moduleReference.expression;
 }
 
 function canCrossNodeWhileReorder(node) {
-  return isPlainRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node)
+  return isPlainRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node);
 }
 
 function canReorderItems(firstNode, secondNode) {
-  const parent = firstNode.parent
+  const parent = firstNode.parent;
   const [firstIndex, secondIndex] = [
     parent.body.indexOf(firstNode),
     parent.body.indexOf(secondNode),
-  ].sort()
-  const nodesBetween = parent.body.slice(firstIndex, secondIndex + 1)
+  ].sort();
+  const nodesBetween = parent.body.slice(firstIndex, secondIndex + 1);
   for (var nodeBetween of nodesBetween) {
     if (!canCrossNodeWhileReorder(nodeBetween)) {
-      return false
+      return false;
     }
   }
-  return true
+  return true;
 }
 
 function fixOutOfOrder(context, firstNode, secondNode, order) {
-  const sourceCode = context.getSourceCode()
+  const sourceCode = context.getSourceCode();
 
-  const firstRoot = findRootNode(firstNode.node)
-  const firstRootStart = findStartOfLineWithComments(sourceCode, firstRoot)
-  const firstRootEnd = findEndOfLineWithComments(sourceCode, firstRoot)
+  const firstRoot = findRootNode(firstNode.node);
+  const firstRootStart = findStartOfLineWithComments(sourceCode, firstRoot);
+  const firstRootEnd = findEndOfLineWithComments(sourceCode, firstRoot);
 
-  const secondRoot = findRootNode(secondNode.node)
-  const secondRootStart = findStartOfLineWithComments(sourceCode, secondRoot)
-  const secondRootEnd = findEndOfLineWithComments(sourceCode, secondRoot)
-  const canFix = canReorderItems(firstRoot, secondRoot)
+  const secondRoot = findRootNode(secondNode.node);
+  const secondRootStart = findStartOfLineWithComments(sourceCode, secondRoot);
+  const secondRootEnd = findEndOfLineWithComments(sourceCode, secondRoot);
+  const canFix = canReorderItems(firstRoot, secondRoot);
 
-  let newCode = sourceCode.text.substring(secondRootStart, secondRootEnd)
+  let newCode = sourceCode.text.substring(secondRootStart, secondRootEnd);
   if (newCode[newCode.length - 1] !== '\n') {
-    newCode = newCode + '\n'
+    newCode = newCode + '\n';
   }
 
-  const message = `\`${secondNode.displayName}\` import should occur ${order} import of \`${firstNode.displayName}\``
+  const message = `\`${secondNode.displayName}\` import should occur ${order} import of \`${firstNode.displayName}\``;
 
   if (order === 'before') {
     context.report({
@@ -204,7 +204,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
           [firstRootStart, secondRootEnd],
           newCode + sourceCode.text.substring(firstRootStart, secondRootStart)
         )),
-    })
+    });
   } else if (order === 'after') {
     context.report({
       node: secondNode.node,
@@ -214,143 +214,143 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
           [secondRootStart, firstRootEnd],
           sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode
         )),
-    })
+    });
   }
 }
 
 function reportOutOfOrder(context, imported, outOfOrder, order) {
   outOfOrder.forEach(function (imp) {
     const found = imported.find(function hasHigherRank(importedItem) {
-      return importedItem.rank > imp.rank
-    })
-    fixOutOfOrder(context, found, imp, order)
-  })
+      return importedItem.rank > imp.rank;
+    });
+    fixOutOfOrder(context, found, imp, order);
+  });
 }
 
 function makeOutOfOrderReport(context, imported) {
-  const outOfOrder = findOutOfOrder(imported)
+  const outOfOrder = findOutOfOrder(imported);
   if (!outOfOrder.length) {
-    return
+    return;
   }
   // There are things to report. Try to minimize the number of reported errors.
-  const reversedImported = reverse(imported)
-  const reversedOrder = findOutOfOrder(reversedImported)
+  const reversedImported = reverse(imported);
+  const reversedOrder = findOutOfOrder(reversedImported);
   if (reversedOrder.length < outOfOrder.length) {
-    reportOutOfOrder(context, reversedImported, reversedOrder, 'after')
-    return
+    reportOutOfOrder(context, reversedImported, reversedOrder, 'after');
+    return;
   }
-  reportOutOfOrder(context, imported, outOfOrder, 'before')
+  reportOutOfOrder(context, imported, outOfOrder, 'before');
 }
 
 function getSorter(ascending) {
-  const multiplier = ascending ? 1 : -1
+  const multiplier = ascending ? 1 : -1;
 
   return function importsSorter(importA, importB) {
-    let result
+    let result;
 
     if (importA < importB) {
-      result = -1
+      result = -1;
     } else if (importA > importB) {
-      result = 1
+      result = 1;
     } else {
-      result = 0
+      result = 0;
     }
 
-    return result * multiplier
-  }
+    return result * multiplier;
+  };
 }
 
 function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
   const groupedByRanks = imported.reduce(function(acc, importedItem) {
     if (!Array.isArray(acc[importedItem.rank])) {
-      acc[importedItem.rank] = []
+      acc[importedItem.rank] = [];
     }
-    acc[importedItem.rank].push(importedItem.value)
-    return acc
-  }, {})
+    acc[importedItem.rank].push(importedItem.value);
+    return acc;
+  }, {});
 
-  const groupRanks = Object.keys(groupedByRanks)
+  const groupRanks = Object.keys(groupedByRanks);
 
-  const sorterFn = getSorter(alphabetizeOptions.order === 'asc')
-  const comparator = alphabetizeOptions.caseInsensitive ? (a, b) => sorterFn(String(a).toLowerCase(), String(b).toLowerCase()) : (a, b) => sorterFn(a, b)
+  const sorterFn = getSorter(alphabetizeOptions.order === 'asc');
+  const comparator = alphabetizeOptions.caseInsensitive ? (a, b) => sorterFn(String(a).toLowerCase(), String(b).toLowerCase()) : (a, b) => sorterFn(a, b);
   // sort imports locally within their group
   groupRanks.forEach(function(groupRank) {
-    groupedByRanks[groupRank].sort(comparator)
-  })
+    groupedByRanks[groupRank].sort(comparator);
+  });
 
   // assign globally unique rank to each import
-  let newRank = 0
+  let newRank = 0;
   const alphabetizedRanks = groupRanks.sort().reduce(function(acc, groupRank) {
     groupedByRanks[groupRank].forEach(function(importedItemName) {
-      acc[importedItemName] = parseInt(groupRank, 10) + newRank
-      newRank += 1
-    })
-    return acc
-  }, {})
+      acc[importedItemName] = parseInt(groupRank, 10) + newRank;
+      newRank += 1;
+    });
+    return acc;
+  }, {});
 
   // mutate the original group-rank with alphabetized-rank
   imported.forEach(function(importedItem) {
-    importedItem.rank = alphabetizedRanks[importedItem.value]
-  })
+    importedItem.rank = alphabetizedRanks[importedItem.value];
+  });
 }
 
 // DETECTING
 
 function computePathRank(ranks, pathGroups, path, maxPosition) {
   for (let i = 0, l = pathGroups.length; i < l; i++) {
-    const { pattern, patternOptions, group, position = 1 } = pathGroups[i]
+    const { pattern, patternOptions, group, position = 1 } = pathGroups[i];
     if (minimatch(path, pattern, patternOptions || { nocomment: true })) {
-      return ranks[group] + (position / maxPosition)
+      return ranks[group] + (position / maxPosition);
     }
   }
 }
 
 function computeRank(context, ranks, importEntry, excludedImportTypes) {
-  let impType
-  let rank
+  let impType;
+  let rank;
   if (importEntry.type === 'import:object') {
-    impType = 'object'
+    impType = 'object';
   } else {
-    impType = importType(importEntry.value, context)
+    impType = importType(importEntry.value, context);
   }
   if (!excludedImportTypes.has(impType)) {
-    rank = computePathRank(ranks.groups, ranks.pathGroups, importEntry.value, ranks.maxPosition)
+    rank = computePathRank(ranks.groups, ranks.pathGroups, importEntry.value, ranks.maxPosition);
   }
   if (typeof rank === 'undefined') {
-    rank = ranks.groups[impType]
+    rank = ranks.groups[impType];
   }
   if (importEntry.type !== 'import' && !importEntry.type.startsWith('import:')) {
-    rank += 100
+    rank += 100;
   }
 
-  return rank
+  return rank;
 }
 
 function registerNode(context, importEntry, ranks, imported, excludedImportTypes) {
-  const rank = computeRank(context, ranks, importEntry, excludedImportTypes)
+  const rank = computeRank(context, ranks, importEntry, excludedImportTypes);
   if (rank !== -1) {
-    imported.push(Object.assign({}, importEntry, { rank }))
+    imported.push(Object.assign({}, importEntry, { rank }));
   }
 }
 
 function isModuleLevelRequire(node) {
-  let n = node
+  let n = node;
   // Handle cases like `const baz = require('foo').bar.baz`
   // and `const foo = require('foo')()`
   while ( 
     (n.parent.type === 'MemberExpression' && n.parent.object === n) ||
     (n.parent.type === 'CallExpression' && n.parent.callee === n)
    ) {
-    n = n.parent
+    n = n.parent;
   }
   return (
     n.parent.type === 'VariableDeclarator' &&
     n.parent.parent.type === 'VariableDeclaration' &&
     n.parent.parent.parent.type === 'Program' 
-  )
+  );
 }
 
-const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object']
+const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object'];
 
 // Creates an object with type-rank pairs.
 // Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
@@ -358,98 +358,98 @@ const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling'
 function convertGroupsToRanks(groups) {
   const rankObject = groups.reduce(function(res, group, index) {
     if (typeof group === 'string') {
-      group = [group]
+      group = [group];
     }
     group.forEach(function(groupItem) {
       if (types.indexOf(groupItem) === -1) {
         throw new Error('Incorrect configuration of the rule: Unknown type `' +
-          JSON.stringify(groupItem) + '`')
+          JSON.stringify(groupItem) + '`');
       }
       if (res[groupItem] !== undefined) {
-        throw new Error('Incorrect configuration of the rule: `' + groupItem + '` is duplicated')
+        throw new Error('Incorrect configuration of the rule: `' + groupItem + '` is duplicated');
       }
-      res[groupItem] = index
-    })
-    return res
-  }, {})
+      res[groupItem] = index;
+    });
+    return res;
+  }, {});
 
   const omittedTypes = types.filter(function(type) {
-    return rankObject[type] === undefined
-  })
+    return rankObject[type] === undefined;
+  });
 
   return omittedTypes.reduce(function(res, type) {
-    res[type] = groups.length
-    return res
-  }, rankObject)
+    res[type] = groups.length;
+    return res;
+  }, rankObject);
 }
 
 function convertPathGroupsForRanks(pathGroups) {
-  const after = {}
-  const before = {}
+  const after = {};
+  const before = {};
 
   const transformed = pathGroups.map((pathGroup, index) => {
-    const { group, position: positionString } = pathGroup
-    let position = 0
+    const { group, position: positionString } = pathGroup;
+    let position = 0;
     if (positionString === 'after') {
       if (!after[group]) {
-        after[group] = 1
+        after[group] = 1;
       }
-      position = after[group]++
+      position = after[group]++;
     } else if (positionString === 'before') {
       if (!before[group]) {
-        before[group] = []
+        before[group] = [];
       }
-      before[group].push(index)
+      before[group].push(index);
     }
 
-    return Object.assign({}, pathGroup, { position })
-  })
+    return Object.assign({}, pathGroup, { position });
+  });
 
-  let maxPosition = 1
+  let maxPosition = 1;
 
   Object.keys(before).forEach((group) => {
-    const groupLength = before[group].length
+    const groupLength = before[group].length;
     before[group].forEach((groupIndex, index) => {
-      transformed[groupIndex].position = -1 * (groupLength - index)
-    })
-    maxPosition = Math.max(maxPosition, groupLength)
-  })
+      transformed[groupIndex].position = -1 * (groupLength - index);
+    });
+    maxPosition = Math.max(maxPosition, groupLength);
+  });
 
   Object.keys(after).forEach((key) => {
-    const groupNextPosition = after[key]
-    maxPosition = Math.max(maxPosition, groupNextPosition - 1)
-  })
+    const groupNextPosition = after[key];
+    maxPosition = Math.max(maxPosition, groupNextPosition - 1);
+  });
 
   return {
     pathGroups: transformed,
     maxPosition: maxPosition > 10 ? Math.pow(10, Math.ceil(Math.log10(maxPosition))) : 10,
-  }
+  };
 }
 
 function fixNewLineAfterImport(context, previousImport) {
-  const prevRoot = findRootNode(previousImport.node)
+  const prevRoot = findRootNode(previousImport.node);
   const tokensToEndOfLine = takeTokensAfterWhile(
-    context.getSourceCode(), prevRoot, commentOnSameLineAs(prevRoot))
+    context.getSourceCode(), prevRoot, commentOnSameLineAs(prevRoot));
 
-  let endOfLine = prevRoot.range[1]
+  let endOfLine = prevRoot.range[1];
   if (tokensToEndOfLine.length > 0) {
-    endOfLine = tokensToEndOfLine[tokensToEndOfLine.length - 1].range[1]
+    endOfLine = tokensToEndOfLine[tokensToEndOfLine.length - 1].range[1];
   }
-  return (fixer) => fixer.insertTextAfterRange([prevRoot.range[0], endOfLine], '\n')
+  return (fixer) => fixer.insertTextAfterRange([prevRoot.range[0], endOfLine], '\n');
 }
 
 function removeNewLineAfterImport(context, currentImport, previousImport) {
-  const sourceCode = context.getSourceCode()
-  const prevRoot = findRootNode(previousImport.node)
-  const currRoot = findRootNode(currentImport.node)
+  const sourceCode = context.getSourceCode();
+  const prevRoot = findRootNode(previousImport.node);
+  const currRoot = findRootNode(currentImport.node);
   const rangeToRemove = [
     findEndOfLineWithComments(sourceCode, prevRoot),
     findStartOfLineWithComments(sourceCode, currRoot),
-  ]
+  ];
   if (/^\s*$/.test(sourceCode.text.substring(rangeToRemove[0], rangeToRemove[1]))) {
-    return (fixer) => fixer.removeRange(rangeToRemove)
+    return (fixer) => fixer.removeRange(rangeToRemove);
   }
-  return undefined
+  return undefined;
 }
 
 function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
@@ -457,14 +457,14 @@ function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
     const linesBetweenImports = context.getSourceCode().lines.slice(
       previousImport.node.loc.end.line,
       currentImport.node.loc.start.line - 1
-    )
+    );
 
-    return linesBetweenImports.filter((line) => !line.trim().length).length
-  }
-  let previousImport = imported[0]
+    return linesBetweenImports.filter((line) => !line.trim().length).length;
+  };
+  let previousImport = imported[0];
 
   imported.slice(1).forEach(function(currentImport) {
-    const emptyLinesBetween = getNumberOfEmptyLinesBetween(currentImport, previousImport)
+    const emptyLinesBetween = getNumberOfEmptyLinesBetween(currentImport, previousImport);
 
     if (newlinesBetweenImports === 'always'
         || newlinesBetweenImports === 'always-and-inside-groups') {
@@ -473,7 +473,7 @@ function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
           node: previousImport.node,
           message: 'There should be at least one empty line between import groups',
           fix: fixNewLineAfterImport(context, previousImport),
-        })
+        });
       } else if (currentImport.rank === previousImport.rank
         && emptyLinesBetween > 0
         && newlinesBetweenImports !== 'always-and-inside-groups') {
@@ -481,26 +481,26 @@ function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
           node: previousImport.node,
           message: 'There should be no empty line within import group',
           fix: removeNewLineAfterImport(context, currentImport, previousImport),
-        })
+        });
       }
     } else if (emptyLinesBetween > 0) {
       context.report({
         node: previousImport.node,
         message: 'There should be no empty line between import groups',
         fix: removeNewLineAfterImport(context, currentImport, previousImport),
-      })
+      });
     }
 
-    previousImport = currentImport
-  })
+    previousImport = currentImport;
+  });
 }
 
 function getAlphabetizeConfig(options) {
-  const alphabetize = options.alphabetize || {}
-  const order = alphabetize.order || 'ignore'
-  const caseInsensitive = alphabetize.caseInsensitive || false
+  const alphabetize = options.alphabetize || {};
+  const order = alphabetize.order || 'ignore';
+  const caseInsensitive = alphabetize.caseInsensitive || false;
 
-  return {order, caseInsensitive}
+  return {order, caseInsensitive};
 }
 
 module.exports = {
@@ -573,33 +573,33 @@ module.exports = {
   },
 
   create: function importOrderRule (context) {
-    const options = context.options[0] || {}
-    const newlinesBetweenImports = options['newlines-between'] || 'ignore'
-    const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external', 'object'])
-    const alphabetize = getAlphabetizeConfig(options)
-    let ranks
+    const options = context.options[0] || {};
+    const newlinesBetweenImports = options['newlines-between'] || 'ignore';
+    const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external', 'object']);
+    const alphabetize = getAlphabetizeConfig(options);
+    let ranks;
 
     try {
-      const { pathGroups, maxPosition } = convertPathGroupsForRanks(options.pathGroups || [])
+      const { pathGroups, maxPosition } = convertPathGroupsForRanks(options.pathGroups || []);
       ranks = {
         groups: convertGroupsToRanks(options.groups || defaultGroups),
         pathGroups,
         maxPosition,
-      }
+      };
     } catch (error) {
       // Malformed configuration
       return {
         Program: function(node) {
-          context.report(node, error.message)
+          context.report(node, error.message);
         },
-      }
+      };
     }
-    let imported = []
+    let imported = [];
 
     return {
       ImportDeclaration: function handleImports(node) {
         if (node.specifiers.length) { // Ignoring unassigned imports
-          const name = node.source.value
+          const name = node.source.value;
           registerNode(
             context,
             {
@@ -611,25 +611,25 @@ module.exports = {
             ranks,
             imported,
             pathGroupsExcludedImportTypes
-          )
+          );
         }
       },
       TSImportEqualsDeclaration: function handleImports(node) {
-        let displayName
-        let value
-        let type
+        let displayName;
+        let value;
+        let type;
         // skip "export import"s
         if (node.isExport) {
-          return
+          return;
         }
         if (node.moduleReference.type === 'TSExternalModuleReference') {
-          value = node.moduleReference.expression.value
-          displayName = value
-          type = 'import'
+          value = node.moduleReference.expression.value;
+          displayName = value;
+          type = 'import';
         } else {
-          value = ''
-          displayName = context.getSourceCode().getText(node.moduleReference)
-          type = 'import:object'
+          value = '';
+          displayName = context.getSourceCode().getText(node.moduleReference);
+          type = 'import:object';
         }
         registerNode(
           context,
@@ -642,13 +642,13 @@ module.exports = {
           ranks,
           imported,
           pathGroupsExcludedImportTypes
-        )
+        );
       },
       CallExpression: function handleRequires(node) {
         if (!isStaticRequire(node) || !isModuleLevelRequire(node)) {
-          return
+          return;
         }
-        const name = node.arguments[0].value
+        const name = node.arguments[0].value;
         registerNode(
           context,
           {
@@ -660,21 +660,21 @@ module.exports = {
           ranks,
           imported,
           pathGroupsExcludedImportTypes
-        )
+        );
       },
       'Program:exit': function reportAndReset() {
         if (newlinesBetweenImports !== 'ignore') {
-          makeNewlinesBetweenReport(context, imported, newlinesBetweenImports)
+          makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
         }
 
         if (alphabetize.order !== 'ignore') {
-          mutateRanksToAlphabetize(imported, alphabetize)
+          mutateRanksToAlphabetize(imported, alphabetize);
         }
 
-        makeOutOfOrderReport(context, imported)
+        makeOutOfOrderReport(context, imported);
 
-        imported = []
+        imported = [];
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 002cf2870f..5e77126dc0 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -1,6 +1,6 @@
-'use strict'
+'use strict';
 
-import docsUrl from '../docsUrl'
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -12,47 +12,47 @@ module.exports = {
   },
 
   create: function(context) {
-    let specifierExportCount = 0
-    let hasDefaultExport = false
-    let hasStarExport = false
-    let hasTypeExport = false
-    let namedExportNode = null
+    let specifierExportCount = 0;
+    let hasDefaultExport = false;
+    let hasStarExport = false;
+    let hasTypeExport = false;
+    let namedExportNode = null;
 
     function captureDeclaration(identifierOrPattern) {
       if (identifierOrPattern && identifierOrPattern.type === 'ObjectPattern') {
         // recursively capture
         identifierOrPattern.properties
           .forEach(function(property) {
-            captureDeclaration(property.value)
-          })
+            captureDeclaration(property.value);
+          });
       } else if (identifierOrPattern && identifierOrPattern.type === 'ArrayPattern') {
         identifierOrPattern.elements
-          .forEach(captureDeclaration)
+          .forEach(captureDeclaration);
       } else  {
       // assume it's a single standard identifier
-        specifierExportCount++
+        specifierExportCount++;
       }
     }
 
     return {
       'ExportDefaultSpecifier': function() {
-        hasDefaultExport = true
+        hasDefaultExport = true;
       },
 
       'ExportSpecifier': function(node) {
         if (node.exported.name === 'default') {
-          hasDefaultExport = true
+          hasDefaultExport = true;
         } else {
-          specifierExportCount++
-          namedExportNode = node
+          specifierExportCount++;
+          namedExportNode = node;
         }
       },
 
       'ExportNamedDeclaration': function(node) {
         // if there are specifiers, node.declaration should be null
-        if (!node.declaration) return
+        if (!node.declaration) return;
 
-        const { type } = node.declaration
+        const { type } = node.declaration;
 
         if (
           type === 'TSTypeAliasDeclaration' ||
@@ -60,37 +60,37 @@ module.exports = {
           type === 'TSInterfaceDeclaration' ||
           type === 'InterfaceDeclaration'
         ) {
-          specifierExportCount++
-          hasTypeExport = true
-          return
+          specifierExportCount++;
+          hasTypeExport = true;
+          return;
         }
 
         if (node.declaration.declarations) {
           node.declaration.declarations.forEach(function(declaration) {
-            captureDeclaration(declaration.id)
-          })
+            captureDeclaration(declaration.id);
+          });
         }
         else {
           // captures 'export function foo() {}' syntax
-          specifierExportCount++
+          specifierExportCount++;
         }
 
-        namedExportNode = node
+        namedExportNode = node;
       },
 
       'ExportDefaultDeclaration': function() {
-        hasDefaultExport = true
+        hasDefaultExport = true;
       },
 
       'ExportAllDeclaration': function() {
-        hasStarExport = true
+        hasStarExport = true;
       },
 
       'Program:exit': function() {
         if (specifierExportCount === 1 && !hasDefaultExport && !hasStarExport && !hasTypeExport) {
-          context.report(namedExportNode, 'Prefer default export.')
+          context.report(namedExportNode, 'Prefer default export.');
         }
       },
-    }
+    };
   },
-}
+};
diff --git a/src/rules/unambiguous.js b/src/rules/unambiguous.js
index 52c2f5ac19..c0570b066e 100644
--- a/src/rules/unambiguous.js
+++ b/src/rules/unambiguous.js
@@ -3,8 +3,8 @@
  * @author Ben Mosher
  */
 
-import { isModule } from 'eslint-module-utils/unambiguous'
-import docsUrl from '../docsUrl'
+import { isModule } from 'eslint-module-utils/unambiguous';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -18,7 +18,7 @@ module.exports = {
   create: function (context) {
     // ignore non-modules
     if (context.parserOptions.sourceType !== 'module') {
-      return {}
+      return {};
     }
 
     return {
@@ -27,10 +27,10 @@ module.exports = {
           context.report({
             node: ast,
             message: 'This module could be parsed as a valid script.',
-          })
+          });
         }
       },
-    }
+    };
 
   },
-}
+};
diff --git a/tests/src/cli.js b/tests/src/cli.js
index 9a2d796ade..033513ad62 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -1,16 +1,16 @@
 /**
  * tests that require fully booting up ESLint
  */
-import path from 'path'
+import path from 'path';
 
-import { expect } from 'chai'
-import { CLIEngine } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
+import { expect } from 'chai';
+import { CLIEngine } from 'eslint';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
 describe('CLI regression tests', function () {
   describe('issue #210', function () {
-    let cli
+    let cli;
     before(function () {
       cli = new CLIEngine({
         useEslintrc: false,
@@ -19,31 +19,31 @@ describe('CLI regression tests', function () {
         rules: {
           'named': 2,
         },
-      })
-    })
+      });
+    });
     it("doesn't throw an error on gratuitous, erroneous self-reference", function () {
-      expect(() => cli.executeOnFiles(['./tests/files/issue210.js'])).not.to.throw()
-    })
-  })
+      expect(() => cli.executeOnFiles(['./tests/files/issue210.js'])).not.to.throw();
+    });
+  });
 
   describe('issue #1645', function () {
-    let cli
+    let cli;
     beforeEach(function () {
       if (semver.satisfies(eslintPkg.version, '< 6')) {
-        this.skip()
+        this.skip();
       } else {
         cli = new CLIEngine({
           useEslintrc: false,
           configFile: './tests/files/just-json-files/.eslintrc.json',
           rulePaths: ['./src/rules'],
           ignore: false,
-        })
+        });
       }
-    })
+    });
 
     it('throws an error on invalid JSON', () => {
-      const invalidJSON = './tests/files/just-json-files/invalid.json'
-      const results = cli.executeOnFiles([invalidJSON])
+      const invalidJSON = './tests/files/just-json-files/invalid.json';
+      const results = cli.executeOnFiles([invalidJSON]);
       expect(results).to.eql({
         results: [
           {
@@ -73,7 +73,7 @@ describe('CLI regression tests', function () {
         fixableErrorCount: 0,
         fixableWarningCount: 0,
         usedDeprecatedRules: results.usedDeprecatedRules, // we don't care about this one
-      })
-    })
-  })
-})
+      });
+    });
+  });
+});
diff --git a/tests/src/config/typescript.js b/tests/src/config/typescript.js
index d5e3ec8507..34df49b38a 100644
--- a/tests/src/config/typescript.js
+++ b/tests/src/config/typescript.js
@@ -1,14 +1,14 @@
-import path from 'path'
-import { expect } from 'chai'
+import path from 'path';
+import { expect } from 'chai';
 
-const config = require(path.join(__dirname, '..', '..', '..', 'config', 'typescript'))
+const config = require(path.join(__dirname, '..', '..', '..', 'config', 'typescript'));
 
 describe('config typescript', () => {
   // https://github.com/benmosher/eslint-plugin-import/issues/1525
   it('should mark @types paths as external', () => {
-    const externalModuleFolders = config.settings['import/external-module-folders']
-    expect(externalModuleFolders).to.exist
-    expect(externalModuleFolders).to.contain('node_modules')
-    expect(externalModuleFolders).to.contain('node_modules/@types')
-  })
-})
+    const externalModuleFolders = config.settings['import/external-module-folders'];
+    expect(externalModuleFolders).to.exist;
+    expect(externalModuleFolders).to.contain('node_modules');
+    expect(externalModuleFolders).to.contain('node_modules/@types');
+  });
+});
diff --git a/tests/src/core/docsUrl.js b/tests/src/core/docsUrl.js
index 2ba778a4a5..57b186b2f7 100644
--- a/tests/src/core/docsUrl.js
+++ b/tests/src/core/docsUrl.js
@@ -1,14 +1,14 @@
-import { expect } from 'chai'
+import { expect } from 'chai';
 
-import pkg from '../../../package.json'
-import docsUrl from '../../../src/docsUrl'
+import pkg from '../../../package.json';
+import docsUrl from '../../../src/docsUrl';
 
 describe('docsUrl', function () {
   it('returns the rule documentation URL when given a rule name', function () {
-    expect(docsUrl('foo')).to.equal(`https://github.com/benmosher/eslint-plugin-import/blob/v${pkg.version}/docs/rules/foo.md`)
-  })
+    expect(docsUrl('foo')).to.equal(`https://github.com/benmosher/eslint-plugin-import/blob/v${pkg.version}/docs/rules/foo.md`);
+  });
 
   it('supports an optional commit-ish parameter', function () {
-    expect(docsUrl('foo', 'bar')).to.equal('https://github.com/benmosher/eslint-plugin-import/blob/bar/docs/rules/foo.md')
-  })
-})
+    expect(docsUrl('foo', 'bar')).to.equal('https://github.com/benmosher/eslint-plugin-import/blob/bar/docs/rules/foo.md');
+  });
+});
diff --git a/tests/src/core/eslintParser.js b/tests/src/core/eslintParser.js
index 3870ccc6e4..492b83ea4d 100644
--- a/tests/src/core/eslintParser.js
+++ b/tests/src/core/eslintParser.js
@@ -2,6 +2,6 @@ module.exports = {
   parseForESLint: function() {
     return {
       ast: {},
-    }
+    };
   },
-}
+};
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 145f236f10..60abcbf9ad 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -1,186 +1,186 @@
-import { expect } from  'chai'
-import semver from 'semver'
-import eslintPkg from 'eslint/package.json'
-import ExportMap from '../../../src/ExportMap'
+import { expect } from  'chai';
+import semver from 'semver';
+import eslintPkg from 'eslint/package.json';
+import ExportMap from '../../../src/ExportMap';
 
-import * as fs from 'fs'
+import * as fs from 'fs';
 
-import { getFilename } from '../utils'
-import * as unambiguous from 'eslint-module-utils/unambiguous'
+import { getFilename } from '../utils';
+import * as unambiguous from 'eslint-module-utils/unambiguous';
 
 describe('ExportMap', function () {
   const fakeContext = {
     getFilename: getFilename,
     settings: {},
     parserPath: 'babel-eslint',
-  }
+  };
 
   it('handles ExportAllDeclaration', function () {
-    var imports
+    var imports;
     expect(function () {
-      imports = ExportMap.get('./export-all', fakeContext)
-    }).not.to.throw(Error)
+      imports = ExportMap.get('./export-all', fakeContext);
+    }).not.to.throw(Error);
 
-    expect(imports).to.exist
-    expect(imports.has('foo')).to.be.true
+    expect(imports).to.exist;
+    expect(imports.has('foo')).to.be.true;
 
-  })
+  });
 
   it('returns a cached copy on subsequent requests', function () {
     expect(ExportMap.get('./named-exports', fakeContext))
-      .to.exist.and.equal(ExportMap.get('./named-exports', fakeContext))
-  })
+      .to.exist.and.equal(ExportMap.get('./named-exports', fakeContext));
+  });
 
   it('does not return a cached copy after modification', (done) => {
-    const firstAccess = ExportMap.get('./mutator', fakeContext)
-    expect(firstAccess).to.exist
+    const firstAccess = ExportMap.get('./mutator', fakeContext);
+    expect(firstAccess).to.exist;
 
     // mutate (update modified time)
-    const newDate = new Date()
+    const newDate = new Date();
     fs.utimes(getFilename('mutator.js'), newDate, newDate, (error) => {
-      expect(error).not.to.exist
-      expect(ExportMap.get('./mutator', fakeContext)).not.to.equal(firstAccess)
-      done()
-    })
-  })
+      expect(error).not.to.exist;
+      expect(ExportMap.get('./mutator', fakeContext)).not.to.equal(firstAccess);
+      done();
+    });
+  });
 
   it('does not return a cached copy with different settings', () => {
-    const firstAccess = ExportMap.get('./named-exports', fakeContext)
-    expect(firstAccess).to.exist
+    const firstAccess = ExportMap.get('./named-exports', fakeContext);
+    expect(firstAccess).to.exist;
 
     const differentSettings = Object.assign(
       {},
       fakeContext,
-      { parserPath: 'espree' })
+      { parserPath: 'espree' });
 
     expect(ExportMap.get('./named-exports', differentSettings))
       .to.exist.and
-      .not.to.equal(firstAccess)
-  })
+      .not.to.equal(firstAccess);
+  });
 
   it('does not throw for a missing file', function () {
-    var imports
+    var imports;
     expect(function () {
-      imports = ExportMap.get('./does-not-exist', fakeContext)
-    }).not.to.throw(Error)
+      imports = ExportMap.get('./does-not-exist', fakeContext);
+    }).not.to.throw(Error);
 
-    expect(imports).not.to.exist
+    expect(imports).not.to.exist;
 
-  })
+  });
 
   it('exports explicit names for a missing file in exports', function () {
-    var imports
+    var imports;
     expect(function () {
-      imports = ExportMap.get('./exports-missing', fakeContext)
-    }).not.to.throw(Error)
+      imports = ExportMap.get('./exports-missing', fakeContext);
+    }).not.to.throw(Error);
 
-    expect(imports).to.exist
-    expect(imports.has('bar')).to.be.true
+    expect(imports).to.exist;
+    expect(imports.has('bar')).to.be.true;
 
-  })
+  });
 
   it('finds exports for an ES7 module with babel-eslint', function () {
     const path = getFilename('jsx/FooES7.js')
-        , contents = fs.readFileSync(path, { encoding: 'utf8' })
+        , contents = fs.readFileSync(path, { encoding: 'utf8' });
     var imports = ExportMap.parse(
       path,
       contents,
       { parserPath: 'babel-eslint', settings: {} },
-    )
+    );
 
-    expect(imports, 'imports').to.exist
-    expect(imports.errors).to.be.empty
-    expect(imports.get('default'), 'default export').to.exist
-    expect(imports.has('Bar')).to.be.true
-  })
+    expect(imports, 'imports').to.exist;
+    expect(imports.errors).to.be.empty;
+    expect(imports.get('default'), 'default export').to.exist;
+    expect(imports.has('Bar')).to.be.true;
+  });
 
   context('deprecation metadata', function () {
 
     function jsdocTests(parseContext, lineEnding) {
       context('deprecated imports', function () {
-        let imports
+        let imports;
         before('parse file', function () {
           const path = getFilename('deprecated.js')
-              , contents = fs.readFileSync(path, { encoding: 'utf8' }).replace(/[\r]\n/g, lineEnding)
-          imports = ExportMap.parse(path, contents, parseContext)
+              , contents = fs.readFileSync(path, { encoding: 'utf8' }).replace(/[\r]\n/g, lineEnding);
+          imports = ExportMap.parse(path, contents, parseContext);
 
           // sanity checks
-          expect(imports.errors).to.be.empty
-        })
+          expect(imports.errors).to.be.empty;
+        });
 
         it('works with named imports.', function () {
-          expect(imports.has('fn')).to.be.true
+          expect(imports.has('fn')).to.be.true;
 
           expect(imports.get('fn'))
-            .to.have.nested.property('doc.tags[0].title', 'deprecated')
+            .to.have.nested.property('doc.tags[0].title', 'deprecated');
           expect(imports.get('fn'))
-            .to.have.nested.property('doc.tags[0].description', 'please use \'x\' instead.')
-        })
+            .to.have.nested.property('doc.tags[0].description', 'please use \'x\' instead.');
+        });
 
         it('works with default imports.', function () {
-          expect(imports.has('default')).to.be.true
-          const importMeta = imports.get('default')
+          expect(imports.has('default')).to.be.true;
+          const importMeta = imports.get('default');
 
-          expect(importMeta).to.have.nested.property('doc.tags[0].title', 'deprecated')
-          expect(importMeta).to.have.nested.property('doc.tags[0].description', 'this is awful, use NotAsBadClass.')
-        })
+          expect(importMeta).to.have.nested.property('doc.tags[0].title', 'deprecated');
+          expect(importMeta).to.have.nested.property('doc.tags[0].description', 'this is awful, use NotAsBadClass.');
+        });
 
         it('works with variables.', function () {
-          expect(imports.has('MY_TERRIBLE_ACTION')).to.be.true
-          const importMeta = imports.get('MY_TERRIBLE_ACTION')
+          expect(imports.has('MY_TERRIBLE_ACTION')).to.be.true;
+          const importMeta = imports.get('MY_TERRIBLE_ACTION');
 
           expect(importMeta).to.have.nested.property(
-            'doc.tags[0].title', 'deprecated')
+            'doc.tags[0].title', 'deprecated');
           expect(importMeta).to.have.nested.property(
-            'doc.tags[0].description', 'please stop sending/handling this action type.')
-        })
+            'doc.tags[0].description', 'please stop sending/handling this action type.');
+        });
 
         context('multi-line variables', function () {
           it('works for the first one', function () {
-            expect(imports.has('CHAIN_A')).to.be.true
-            const importMeta = imports.get('CHAIN_A')
+            expect(imports.has('CHAIN_A')).to.be.true;
+            const importMeta = imports.get('CHAIN_A');
 
             expect(importMeta).to.have.nested.property(
-              'doc.tags[0].title', 'deprecated')
+              'doc.tags[0].title', 'deprecated');
             expect(importMeta).to.have.nested.property(
-              'doc.tags[0].description', 'this chain is awful')
-          })
+              'doc.tags[0].description', 'this chain is awful');
+          });
           it('works for the second one', function () {
-            expect(imports.has('CHAIN_B')).to.be.true
-            const importMeta = imports.get('CHAIN_B')
+            expect(imports.has('CHAIN_B')).to.be.true;
+            const importMeta = imports.get('CHAIN_B');
 
             expect(importMeta).to.have.nested.property(
-              'doc.tags[0].title', 'deprecated')
+              'doc.tags[0].title', 'deprecated');
             expect(importMeta).to.have.nested.property(
-              'doc.tags[0].description', 'so awful')
-          })
+              'doc.tags[0].description', 'so awful');
+          });
           it('works for the third one, etc.', function () {
-            expect(imports.has('CHAIN_C')).to.be.true
-            const importMeta = imports.get('CHAIN_C')
+            expect(imports.has('CHAIN_C')).to.be.true;
+            const importMeta = imports.get('CHAIN_C');
 
             expect(importMeta).to.have.nested.property(
-              'doc.tags[0].title', 'deprecated')
+              'doc.tags[0].title', 'deprecated');
             expect(importMeta).to.have.nested.property(
-              'doc.tags[0].description', 'still terrible')
-          })
-        })
-      })
+              'doc.tags[0].description', 'still terrible');
+          });
+        });
+      });
 
       context('full module', function () {
-        let imports
+        let imports;
         before('parse file', function () {
           const path = getFilename('deprecated-file.js')
-              , contents = fs.readFileSync(path, { encoding: 'utf8' })
-          imports = ExportMap.parse(path, contents, parseContext)
+              , contents = fs.readFileSync(path, { encoding: 'utf8' });
+          imports = ExportMap.parse(path, contents, parseContext);
 
           // sanity checks
-          expect(imports.errors).to.be.empty
-        })
+          expect(imports.errors).to.be.empty;
+        });
 
         it('has JSDoc metadata', function () {
-          expect(imports.doc).to.exist
-        })
-      })
+          expect(imports.doc).to.exist;
+        });
+      });
     }
 
     context('default parser', function () {
@@ -192,7 +192,7 @@ describe('ExportMap', function () {
           attachComment: true,
         },
         settings: {},
-      }, '\n')
+      }, '\n');
       jsdocTests({
         parserPath: 'espree',
         parserOptions: {
@@ -201,8 +201,8 @@ describe('ExportMap', function () {
           attachComment: true,
         },
         settings: {},
-      }, '\r\n')
-    })
+      }, '\r\n');
+    });
 
     context('babel-eslint', function () {
       jsdocTests({
@@ -213,7 +213,7 @@ describe('ExportMap', function () {
           attachComment: true,
         },
         settings: {},
-      }, '\n')
+      }, '\n');
       jsdocTests({
         parserPath: 'babel-eslint',
         parserOptions: {
@@ -222,128 +222,128 @@ describe('ExportMap', function () {
           attachComment: true,
         },
         settings: {},
-      }, '\r\n')
-    })
-  })
+      }, '\r\n');
+    });
+  });
 
   context('exported static namespaces', function () {
-    const espreeContext = { parserPath: 'espree', parserOptions: { ecmaVersion: 2015, sourceType: 'module' }, settings: {} }
-    const babelContext = { parserPath: 'babel-eslint', parserOptions: { ecmaVersion: 2015, sourceType: 'module' }, settings: {} }
+    const espreeContext = { parserPath: 'espree', parserOptions: { ecmaVersion: 2015, sourceType: 'module' }, settings: {} };
+    const babelContext = { parserPath: 'babel-eslint', parserOptions: { ecmaVersion: 2015, sourceType: 'module' }, settings: {} };
 
     it('works with espree & traditional namespace exports', function () {
       const path = getFilename('deep/a.js')
-          , contents = fs.readFileSync(path, { encoding: 'utf8' })
-      const a = ExportMap.parse(path, contents, espreeContext)
-      expect(a.errors).to.be.empty
-      expect(a.get('b').namespace).to.exist
-      expect(a.get('b').namespace.has('c')).to.be.true
-    })
+          , contents = fs.readFileSync(path, { encoding: 'utf8' });
+      const a = ExportMap.parse(path, contents, espreeContext);
+      expect(a.errors).to.be.empty;
+      expect(a.get('b').namespace).to.exist;
+      expect(a.get('b').namespace.has('c')).to.be.true;
+    });
 
     it('captures namespace exported as default', function () {
       const path = getFilename('deep/default.js')
-          , contents = fs.readFileSync(path, { encoding: 'utf8' })
-      const def = ExportMap.parse(path, contents, espreeContext)
-      expect(def.errors).to.be.empty
-      expect(def.get('default').namespace).to.exist
-      expect(def.get('default').namespace.has('c')).to.be.true
-    })
+          , contents = fs.readFileSync(path, { encoding: 'utf8' });
+      const def = ExportMap.parse(path, contents, espreeContext);
+      expect(def.errors).to.be.empty;
+      expect(def.get('default').namespace).to.exist;
+      expect(def.get('default').namespace.has('c')).to.be.true;
+    });
 
     it('works with babel-eslint & ES7 namespace exports', function () {
       const path = getFilename('deep-es7/a.js')
-          , contents = fs.readFileSync(path, { encoding: 'utf8' })
-      const a = ExportMap.parse(path, contents, babelContext)
-      expect(a.errors).to.be.empty
-      expect(a.get('b').namespace).to.exist
-      expect(a.get('b').namespace.has('c')).to.be.true
-    })
-  })
+          , contents = fs.readFileSync(path, { encoding: 'utf8' });
+      const a = ExportMap.parse(path, contents, babelContext);
+      expect(a.errors).to.be.empty;
+      expect(a.get('b').namespace).to.exist;
+      expect(a.get('b').namespace.has('c')).to.be.true;
+    });
+  });
 
   context('deep namespace caching', function () {
-    const espreeContext = { parserPath: 'espree', parserOptions: { ecmaVersion: 2015, sourceType: 'module' }, settings: {} }
-    let a
+    const espreeContext = { parserPath: 'espree', parserOptions: { ecmaVersion: 2015, sourceType: 'module' }, settings: {} };
+    let a;
     before('sanity check and prime cache', function (done) {
       // first version
       fs.writeFileSync(getFilename('deep/cache-2.js'),
-        fs.readFileSync(getFilename('deep/cache-2a.js')))
+        fs.readFileSync(getFilename('deep/cache-2a.js')));
 
       const path = getFilename('deep/cache-1.js')
-          , contents = fs.readFileSync(path, { encoding: 'utf8' })
-      a = ExportMap.parse(path, contents, espreeContext)
-      expect(a.errors).to.be.empty
+          , contents = fs.readFileSync(path, { encoding: 'utf8' });
+      a = ExportMap.parse(path, contents, espreeContext);
+      expect(a.errors).to.be.empty;
 
-      expect(a.get('b').namespace).to.exist
-      expect(a.get('b').namespace.has('c')).to.be.true
+      expect(a.get('b').namespace).to.exist;
+      expect(a.get('b').namespace.has('c')).to.be.true;
 
       // wait ~1s, cache check is 1s resolution
       setTimeout(function reup() {
-        fs.unlinkSync(getFilename('deep/cache-2.js'))
+        fs.unlinkSync(getFilename('deep/cache-2.js'));
         // swap in a new file and touch it
         fs.writeFileSync(getFilename('deep/cache-2.js'),
-          fs.readFileSync(getFilename('deep/cache-2b.js')))
-        done()
-      }, 1100)
-    })
+          fs.readFileSync(getFilename('deep/cache-2b.js')));
+        done();
+      }, 1100);
+    });
 
     it('works', function () {
-      expect(a.get('b').namespace.has('c')).to.be.false
-    })
+      expect(a.get('b').namespace.has('c')).to.be.false;
+    });
 
-    after('remove test file', (done) => fs.unlink(getFilename('deep/cache-2.js'), done))
-  })
+    after('remove test file', (done) => fs.unlink(getFilename('deep/cache-2.js'), done));
+  });
 
   context('Map API', function () {
     context('#size', function () {
 
       it('counts the names', () => expect(ExportMap.get('./named-exports', fakeContext))
-        .to.have.property('size', 12))
+        .to.have.property('size', 12));
 
       it('includes exported namespace size', () => expect(ExportMap.get('./export-all', fakeContext))
-        .to.have.property('size', 1))
+        .to.have.property('size', 1));
 
-    })
-  })
+    });
+  });
 
   context('issue #210: self-reference', function () {
     it(`doesn't crash`, function () {
-      expect(() => ExportMap.get('./narcissist', fakeContext)).not.to.throw(Error)
-    })
+      expect(() => ExportMap.get('./narcissist', fakeContext)).not.to.throw(Error);
+    });
     it(`'has' circular reference`, function () {
       expect(ExportMap.get('./narcissist', fakeContext))
-        .to.exist.and.satisfy(m => m.has('soGreat'))
-    })
+        .to.exist.and.satisfy(m => m.has('soGreat'));
+    });
     it(`can 'get' circular reference`, function () {
       expect(ExportMap.get('./narcissist', fakeContext))
-        .to.exist.and.satisfy(m => m.get('soGreat') != null)
-    })
-  })
+        .to.exist.and.satisfy(m => m.get('soGreat') != null);
+    });
+  });
 
   context('issue #478: never parse non-whitelist extensions', function () {
     const context = Object.assign({}, fakeContext,
-      { settings: { 'import/extensions': ['.js'] } })
+      { settings: { 'import/extensions': ['.js'] } });
 
-    let imports
+    let imports;
     before('load imports', function () {
-      imports = ExportMap.get('./typescript.ts', context)
-    })
+      imports = ExportMap.get('./typescript.ts', context);
+    });
 
     it('returns nothing for a TypeScript file', function () {
-      expect(imports).not.to.exist
-    })
+      expect(imports).not.to.exist;
+    });
 
-  })
+  });
 
   context('alternate parsers', function () {
 
     const configs = [
       // ['string form', { 'typescript-eslint-parser': '.ts' }],
-    ]
+    ];
 
     if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-      configs.push(['array form', { '@typescript-eslint/parser': ['.ts', '.tsx'] }])
+      configs.push(['array form', { '@typescript-eslint/parser': ['.ts', '.tsx'] }]);
     }
 
     if (semver.satisfies(eslintPkg.version, '<6.0.0')) {
-      configs.push(['array form', { 'typescript-eslint-parser': ['.ts', '.tsx'] }])
+      configs.push(['array form', { 'typescript-eslint-parser': ['.ts', '.tsx'] }]);
     }
 
     configs.forEach(([description, parserConfig]) => {
@@ -353,45 +353,45 @@ describe('ExportMap', function () {
           { settings: {
             'import/extensions': ['.js'],
             'import/parsers': parserConfig,
-          } })
+          } });
 
-        let imports
+        let imports;
         before('load imports', function () {
-          this.timeout(20000)  // takes a long time :shrug:
-          imports = ExportMap.get('./typescript.ts', context)
-        })
+          this.timeout(20000);  // takes a long time :shrug:
+          imports = ExportMap.get('./typescript.ts', context);
+        });
 
         it('returns something for a TypeScript file', function () {
-          expect(imports).to.exist
-        })
+          expect(imports).to.exist;
+        });
 
         it('has no parse errors', function () {
-          expect(imports).property('errors').to.be.empty
-        })
+          expect(imports).property('errors').to.be.empty;
+        });
 
         it('has exported function', function () {
-          expect(imports.has('getFoo')).to.be.true
-        })
+          expect(imports.has('getFoo')).to.be.true;
+        });
 
         it('has exported typedef', function () {
-          expect(imports.has('MyType')).to.be.true
-        })
+          expect(imports.has('MyType')).to.be.true;
+        });
 
         it('has exported enum', function () {
-          expect(imports.has('MyEnum')).to.be.true
-        })
+          expect(imports.has('MyEnum')).to.be.true;
+        });
 
         it('has exported interface', function () {
-          expect(imports.has('Foo')).to.be.true
-        })
+          expect(imports.has('Foo')).to.be.true;
+        });
 
         it('has exported abstract class', function () {
-          expect(imports.has('Bar')).to.be.true
-        })
-      })
-    })
+          expect(imports.has('Bar')).to.be.true;
+        });
+      });
+    });
 
-  })
+  });
 
   // todo: move to utils
   describe('unambiguous regex', function () {
@@ -401,15 +401,15 @@ describe('ExportMap', function () {
       ['bar.js', true],
       ['deep-es7/b.js', true],
       ['common.js', false],
-    ]
+    ];
 
     for (let [testFile, expectedRegexResult] of testFiles) {
       it(`works for ${testFile} (${expectedRegexResult})`, function () {
-        const content = fs.readFileSync('./tests/files/' + testFile, 'utf8')
-        expect(unambiguous.test(content)).to.equal(expectedRegexResult)
-      })
+        const content = fs.readFileSync('./tests/files/' + testFile, 'utf8');
+        expect(unambiguous.test(content)).to.equal(expectedRegexResult);
+      });
     }
 
-  })
+  });
 
-})
+});
diff --git a/tests/src/core/hash.js b/tests/src/core/hash.js
index f8dd4b49ac..e75783fb06 100644
--- a/tests/src/core/hash.js
+++ b/tests/src/core/hash.js
@@ -1,76 +1,76 @@
-import { expect } from 'chai'
+import { expect } from 'chai';
 
-import hashify, { hashArray, hashObject } from 'eslint-module-utils/hash'
+import hashify, { hashArray, hashObject } from 'eslint-module-utils/hash';
 
-const createHash = require('crypto').createHash
+const createHash = require('crypto').createHash;
 
 function expectHash(actualHash, expectedString) {
-  const expectedHash = createHash('sha256')
-  expectedHash.update(expectedString)
-  expect(actualHash.digest('hex'), 'to be a hex digest of sha256 hash of string <' + expectedString + '>').to.equal(expectedHash.digest('hex'))
+  const expectedHash = createHash('sha256');
+  expectedHash.update(expectedString);
+  expect(actualHash.digest('hex'), 'to be a hex digest of sha256 hash of string <' + expectedString + '>').to.equal(expectedHash.digest('hex'));
 }
 
 describe('hash', function () {
   describe('hashify', function () {
     it('handles null', function () {
-      expectHash(hashify(null), 'null')
-    })
+      expectHash(hashify(null), 'null');
+    });
 
     it('handles undefined', function () {
-      expectHash(hashify(undefined), 'undefined')
-    })
+      expectHash(hashify(undefined), 'undefined');
+    });
 
     it('handles numbers', function () {
-      expectHash(hashify(123.456), '123.456')
-    })
+      expectHash(hashify(123.456), '123.456');
+    });
 
     it('handles strings', function () {
-      expectHash(hashify('a string'), '"a string"')
-    })
+      expectHash(hashify('a string'), '"a string"');
+    });
 
     it('handles Array instances', function () {
-      expectHash(hashify([ 'a string' ]), '["a string",]')
-    })
+      expectHash(hashify([ 'a string' ]), '["a string",]');
+    });
 
     it('handles empty Array instances', function () {
-      expectHash(hashify([]), '[]')
-    })
+      expectHash(hashify([]), '[]');
+    });
 
     it('handles Object instances', function () {
-      expectHash(hashify({ foo: 123.456, 'a key': 'a value' }), '{"a key":"a value","foo":123.456,}')
-    })
+      expectHash(hashify({ foo: 123.456, 'a key': 'a value' }), '{"a key":"a value","foo":123.456,}');
+    });
 
     it('handles nested Object instances', function () {
-      expectHash(hashify({ foo: 123.456, 'a key': 'a value', obj: { abc: { def: 'ghi' } } }), '{"a key":"a value","foo":123.456,"obj":{"abc":{"def":"ghi",},},}')
-    })
+      expectHash(hashify({ foo: 123.456, 'a key': 'a value', obj: { abc: { def: 'ghi' } } }), '{"a key":"a value","foo":123.456,"obj":{"abc":{"def":"ghi",},},}');
+    });
 
     it('handles nested Object and Array instances', function () {
-      expectHash(hashify({ foo: 123.456, 'a key': 'a value', obj: { arr: [ { def: 'ghi' } ] } }), '{"a key":"a value","foo":123.456,"obj":{"arr":[{"def":"ghi",},],},}')
-    })
-  })
+      expectHash(hashify({ foo: 123.456, 'a key': 'a value', obj: { arr: [ { def: 'ghi' } ] } }), '{"a key":"a value","foo":123.456,"obj":{"arr":[{"def":"ghi",},],},}');
+    });
+  });
 
   describe('hashArray', function () {
     it('handles Array instances', function () {
-      expectHash(hashArray([ 'a string' ]), '["a string",]')
-    })
+      expectHash(hashArray([ 'a string' ]), '["a string",]');
+    });
 
     it('handles empty Array instances', function () {
-      expectHash(hashArray([]), '[]')
-    })
-  })
+      expectHash(hashArray([]), '[]');
+    });
+  });
 
   describe('hashObject', function () {
     it('handles Object instances', function () {
-      expectHash(hashObject({ foo: 123.456, 'a key': 'a value' }), '{"a key":"a value","foo":123.456,}')
-    })
+      expectHash(hashObject({ foo: 123.456, 'a key': 'a value' }), '{"a key":"a value","foo":123.456,}');
+    });
 
     it('handles nested Object instances', function () {
-      expectHash(hashObject({ foo: 123.456, 'a key': 'a value', obj: { abc: { def: 'ghi' } } }), '{"a key":"a value","foo":123.456,"obj":{"abc":{"def":"ghi",},},}')
-    })
+      expectHash(hashObject({ foo: 123.456, 'a key': 'a value', obj: { abc: { def: 'ghi' } } }), '{"a key":"a value","foo":123.456,"obj":{"abc":{"def":"ghi",},},}');
+    });
 
     it('handles nested Object and Array instances', function () {
-      expectHash(hashObject({ foo: 123.456, 'a key': 'a value', obj: { arr: [ { def: 'ghi' } ] } }), '{"a key":"a value","foo":123.456,"obj":{"arr":[{"def":"ghi",},],},}')
-    })
-  })
+      expectHash(hashObject({ foo: 123.456, 'a key': 'a value', obj: { arr: [ { def: 'ghi' } ] } }), '{"a key":"a value","foo":123.456,"obj":{"arr":[{"def":"ghi",},],},}');
+    });
+  });
 
-})
+});
diff --git a/tests/src/core/ignore.js b/tests/src/core/ignore.js
index 8870158a51..2b2126c8b5 100644
--- a/tests/src/core/ignore.js
+++ b/tests/src/core/ignore.js
@@ -1,90 +1,90 @@
-import { expect } from 'chai'
+import { expect } from 'chai';
 
-import isIgnored, { getFileExtensions, hasValidExtension } from 'eslint-module-utils/ignore'
+import isIgnored, { getFileExtensions, hasValidExtension } from 'eslint-module-utils/ignore';
 
-import * as utils from '../utils'
+import * as utils from '../utils';
 
 describe('ignore', function () {
   describe('isIgnored', function () {
     it('ignores paths with extensions other than .js', function () {
-      const testContext = utils.testContext({})
+      const testContext = utils.testContext({});
 
-      expect(isIgnored('../files/foo.js', testContext)).to.equal(false)
+      expect(isIgnored('../files/foo.js', testContext)).to.equal(false);
 
-      expect(isIgnored('../files/bar.jsx', testContext)).to.equal(true)
+      expect(isIgnored('../files/bar.jsx', testContext)).to.equal(true);
 
-      expect(isIgnored('../files/typescript.ts', testContext)).to.equal(true)
+      expect(isIgnored('../files/typescript.ts', testContext)).to.equal(true);
 
-      expect(isIgnored('../files/ignore.invalid.extension', testContext)).to.equal(true)
-    })
+      expect(isIgnored('../files/ignore.invalid.extension', testContext)).to.equal(true);
+    });
 
     it('ignores paths with invalid extensions when configured with import/extensions', function () {
-      const testContext = utils.testContext({ 'import/extensions': [ '.js', '.jsx', '.ts' ] })
+      const testContext = utils.testContext({ 'import/extensions': [ '.js', '.jsx', '.ts' ] });
 
-      expect(isIgnored('../files/foo.js', testContext)).to.equal(false)
+      expect(isIgnored('../files/foo.js', testContext)).to.equal(false);
 
-      expect(isIgnored('../files/bar.jsx', testContext)).to.equal(false)
+      expect(isIgnored('../files/bar.jsx', testContext)).to.equal(false);
 
-      expect(isIgnored('../files/typescript.ts', testContext)).to.equal(false)
+      expect(isIgnored('../files/typescript.ts', testContext)).to.equal(false);
 
-      expect(isIgnored('../files/ignore.invalid.extension', testContext)).to.equal(true)
-    })
-  })
+      expect(isIgnored('../files/ignore.invalid.extension', testContext)).to.equal(true);
+    });
+  });
 
   describe('hasValidExtension', function () {
     it('assumes only .js as valid by default', function () {
-      const testContext = utils.testContext({})
+      const testContext = utils.testContext({});
 
-      expect(hasValidExtension('../files/foo.js', testContext)).to.equal(true)
+      expect(hasValidExtension('../files/foo.js', testContext)).to.equal(true);
 
-      expect(hasValidExtension('../files/foo.jsx', testContext)).to.equal(false)
+      expect(hasValidExtension('../files/foo.jsx', testContext)).to.equal(false);
 
-      expect(hasValidExtension('../files/foo.css', testContext)).to.equal(false)
+      expect(hasValidExtension('../files/foo.css', testContext)).to.equal(false);
 
-      expect(hasValidExtension('../files/foo.invalid.extension', testContext)).to.equal(false)
-    })
+      expect(hasValidExtension('../files/foo.invalid.extension', testContext)).to.equal(false);
+    });
 
     it('can be configured with import/extensions', function () {
-      const testContext = utils.testContext({ 'import/extensions': [ '.foo', '.bar' ] })
+      const testContext = utils.testContext({ 'import/extensions': [ '.foo', '.bar' ] });
 
-      expect(hasValidExtension('../files/foo.foo', testContext)).to.equal(true)
+      expect(hasValidExtension('../files/foo.foo', testContext)).to.equal(true);
 
-      expect(hasValidExtension('../files/foo.bar', testContext)).to.equal(true)
+      expect(hasValidExtension('../files/foo.bar', testContext)).to.equal(true);
 
-      expect(hasValidExtension('../files/foo.js', testContext)).to.equal(false)
-    })
-  })
+      expect(hasValidExtension('../files/foo.js', testContext)).to.equal(false);
+    });
+  });
 
   describe('getFileExtensions', function () {
     it('returns a set with the file extension ".js" if "import/extensions" is not configured', function () {
-      const fileExtensions = getFileExtensions({})
+      const fileExtensions = getFileExtensions({});
 
-      expect(fileExtensions).to.include('.js')
-    })
+      expect(fileExtensions).to.include('.js');
+    });
 
     it('returns a set with the file extensions configured in "import/extension"', function () {
       const settings = {
         'import/extensions': ['.js', '.jsx'],
-      }
+      };
 
-      const fileExtensions = getFileExtensions(settings)
+      const fileExtensions = getFileExtensions(settings);
 
-      expect(fileExtensions).to.include('.js')
-      expect(fileExtensions).to.include('.jsx')
-    })
+      expect(fileExtensions).to.include('.js');
+      expect(fileExtensions).to.include('.jsx');
+    });
 
     it('returns a set with the file extensions configured in "import/extension" and "import/parsers"', function () {
       const settings = {
         'import/parsers': {
           'typescript-eslint-parser': ['.ts', '.tsx'],
         },
-      }
+      };
 
-      const fileExtensions = getFileExtensions(settings)
+      const fileExtensions = getFileExtensions(settings);
 
-      expect(fileExtensions).to.include('.js') // If "import/extensions" is not configured, this is the default
-      expect(fileExtensions).to.include('.ts')
-      expect(fileExtensions).to.include('.tsx')
-    })
-  })
-})
+      expect(fileExtensions).to.include('.js'); // If "import/extensions" is not configured, this is the default
+      expect(fileExtensions).to.include('.ts');
+      expect(fileExtensions).to.include('.tsx');
+    });
+  });
+});
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index f6db95158c..ddac19c9c2 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -1,158 +1,158 @@
-import { expect } from 'chai'
-import * as path from 'path'
+import { expect } from 'chai';
+import * as path from 'path';
 
-import importType, {isExternalModule, isScopedModule} from 'core/importType'
+import importType, {isExternalModule, isScopedModule} from 'core/importType';
 
-import { testContext, testFilePath } from '../utils'
+import { testContext, testFilePath } from '../utils';
 
 describe('importType(name)', function () {
-  const context = testContext()
-  const pathToTestFiles = path.join(__dirname, '..', '..', 'files')
+  const context = testContext();
+  const pathToTestFiles = path.join(__dirname, '..', '..', 'files');
 
   it("should return 'absolute' for paths starting with a /", function() {
-    expect(importType('/', context)).to.equal('absolute')
-    expect(importType('/path', context)).to.equal('absolute')
-    expect(importType('/some/path', context)).to.equal('absolute')
-  })
+    expect(importType('/', context)).to.equal('absolute');
+    expect(importType('/path', context)).to.equal('absolute');
+    expect(importType('/some/path', context)).to.equal('absolute');
+  });
 
   it("should return 'builtin' for node.js modules", function() {
-    expect(importType('fs', context)).to.equal('builtin')
-    expect(importType('path', context)).to.equal('builtin')
-  })
+    expect(importType('fs', context)).to.equal('builtin');
+    expect(importType('path', context)).to.equal('builtin');
+  });
 
   it("should return 'external' for non-builtin modules without a relative path", function() {
-    expect(importType('lodash', context)).to.equal('external')
-    expect(importType('async', context)).to.equal('external')
-    expect(importType('chalk', context)).to.equal('external')
-    expect(importType('foo', context)).to.equal('external')
-    expect(importType('lodash.find', context)).to.equal('external')
-    expect(importType('lodash/fp', context)).to.equal('external')
-  })
+    expect(importType('lodash', context)).to.equal('external');
+    expect(importType('async', context)).to.equal('external');
+    expect(importType('chalk', context)).to.equal('external');
+    expect(importType('foo', context)).to.equal('external');
+    expect(importType('lodash.find', context)).to.equal('external');
+    expect(importType('lodash/fp', context)).to.equal('external');
+  });
 
   it("should return 'external' for scopes packages", function() {
-    expect(importType('@cycle/', context)).to.equal('external')
-    expect(importType('@cycle/core', context)).to.equal('external')
-    expect(importType('@cycle/dom', context)).to.equal('external')
-    expect(importType('@some-thing/something', context)).to.equal('external')
-    expect(importType('@some-thing/something/some-module', context)).to.equal('external')
-    expect(importType('@some-thing/something/some-directory/someModule.js', context)).to.equal('external')
-  })
+    expect(importType('@cycle/', context)).to.equal('external');
+    expect(importType('@cycle/core', context)).to.equal('external');
+    expect(importType('@cycle/dom', context)).to.equal('external');
+    expect(importType('@some-thing/something', context)).to.equal('external');
+    expect(importType('@some-thing/something/some-module', context)).to.equal('external');
+    expect(importType('@some-thing/something/some-directory/someModule.js', context)).to.equal('external');
+  });
 
   it("should return 'external' for external modules that redirect to its parent module using package.json", function() {
-    expect(importType('eslint-import-test-order-redirect/module', context)).to.equal('external')
-    expect(importType('@eslint/import-test-order-redirect-scoped/module', context)).to.equal('external')
-  })
+    expect(importType('eslint-import-test-order-redirect/module', context)).to.equal('external');
+    expect(importType('@eslint/import-test-order-redirect-scoped/module', context)).to.equal('external');
+  });
 
   it("should return 'internal' for non-builtins resolved outside of node_modules", function () {
-    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
-    expect(importType('importType', pathContext)).to.equal('internal')
-  })
+    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } });
+    expect(importType('importType', pathContext)).to.equal('internal');
+  });
 
   it("should return 'internal' for scoped packages resolved outside of node_modules", function () {
-    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
-    expect(importType('@importType/index', pathContext)).to.equal('internal')
-  })
+    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } });
+    expect(importType('@importType/index', pathContext)).to.equal('internal');
+  });
 
   it("should return 'internal' for internal modules that are referenced by aliases", function () {
-    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
-    expect(importType('@my-alias/fn', pathContext)).to.equal('internal')
-    expect(importType('@importType', pathContext)).to.equal('internal')
-  })
+    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } });
+    expect(importType('@my-alias/fn', pathContext)).to.equal('internal');
+    expect(importType('@importType', pathContext)).to.equal('internal');
+  });
 
   it("should return 'internal' for aliased internal modules that look like core modules (node resolver)", function () {
-    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
-    expect(importType('constants/index', pathContext)).to.equal('internal')
-    expect(importType('constants/', pathContext)).to.equal('internal')
+    const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } });
+    expect(importType('constants/index', pathContext)).to.equal('internal');
+    expect(importType('constants/', pathContext)).to.equal('internal');
     // resolves exact core modules over internal modules
-    expect(importType('constants', pathContext)).to.equal('builtin')
-  })
+    expect(importType('constants', pathContext)).to.equal('builtin');
+  });
 
   it("should return 'internal' for aliased internal modules that look like core modules (webpack resolver)", function () {
-    const webpackConfig = { resolve: { modules: [pathToTestFiles, 'node_modules'] } }
-    const pathContext = testContext({ 'import/resolver': { webpack: { config: webpackConfig } } })
-    expect(importType('constants/index', pathContext)).to.equal('internal')
-    expect(importType('constants/', pathContext)).to.equal('internal')
-    expect(importType('constants', pathContext)).to.equal('internal')
-  })
+    const webpackConfig = { resolve: { modules: [pathToTestFiles, 'node_modules'] } };
+    const pathContext = testContext({ 'import/resolver': { webpack: { config: webpackConfig } } });
+    expect(importType('constants/index', pathContext)).to.equal('internal');
+    expect(importType('constants/', pathContext)).to.equal('internal');
+    expect(importType('constants', pathContext)).to.equal('internal');
+  });
 
   it("should return 'parent' for internal modules that go through the parent", function() {
-    expect(importType('../foo', context)).to.equal('parent')
-    expect(importType('../../foo', context)).to.equal('parent')
-    expect(importType('../bar/foo', context)).to.equal('parent')
-  })
+    expect(importType('../foo', context)).to.equal('parent');
+    expect(importType('../../foo', context)).to.equal('parent');
+    expect(importType('../bar/foo', context)).to.equal('parent');
+  });
 
   it("should return 'sibling' for internal modules that are connected to one of the siblings", function() {
-    expect(importType('./foo', context)).to.equal('sibling')
-    expect(importType('./foo/bar', context)).to.equal('sibling')
-    expect(importType('./importType', context)).to.equal('sibling')
-    expect(importType('./importType/', context)).to.equal('sibling')
-    expect(importType('./importType/index', context)).to.equal('sibling')
-    expect(importType('./importType/index.js', context)).to.equal('sibling')
-  })
+    expect(importType('./foo', context)).to.equal('sibling');
+    expect(importType('./foo/bar', context)).to.equal('sibling');
+    expect(importType('./importType', context)).to.equal('sibling');
+    expect(importType('./importType/', context)).to.equal('sibling');
+    expect(importType('./importType/index', context)).to.equal('sibling');
+    expect(importType('./importType/index.js', context)).to.equal('sibling');
+  });
 
   it("should return 'index' for sibling index file", function() {
-    expect(importType('.', context)).to.equal('index')
-    expect(importType('./', context)).to.equal('index')
-    expect(importType('./index', context)).to.equal('index')
-    expect(importType('./index.js', context)).to.equal('index')
-  })
+    expect(importType('.', context)).to.equal('index');
+    expect(importType('./', context)).to.equal('index');
+    expect(importType('./index', context)).to.equal('index');
+    expect(importType('./index.js', context)).to.equal('index');
+  });
 
   it("should return 'unknown' for any unhandled cases", function() {
-    expect(importType('  /malformed', context)).to.equal('unknown')
-    expect(importType('   foo', context)).to.equal('unknown')
-  })
+    expect(importType('  /malformed', context)).to.equal('unknown');
+    expect(importType('   foo', context)).to.equal('unknown');
+  });
 
   it("should return 'builtin' for additional core modules", function() {
     // without extra config, should be marked external
-    expect(importType('electron', context)).to.equal('external')
-    expect(importType('@org/foobar', context)).to.equal('external')
+    expect(importType('electron', context)).to.equal('external');
+    expect(importType('@org/foobar', context)).to.equal('external');
 
-    const electronContext = testContext({ 'import/core-modules': ['electron'] })
-    expect(importType('electron', electronContext)).to.equal('builtin')
+    const electronContext = testContext({ 'import/core-modules': ['electron'] });
+    expect(importType('electron', electronContext)).to.equal('builtin');
 
-    const scopedContext = testContext({ 'import/core-modules': ['@org/foobar'] })
-    expect(importType('@org/foobar', scopedContext)).to.equal('builtin')
-  })
+    const scopedContext = testContext({ 'import/core-modules': ['@org/foobar'] });
+    expect(importType('@org/foobar', scopedContext)).to.equal('builtin');
+  });
 
   it("should return 'builtin' for resources inside additional core modules", function() {
-    const electronContext = testContext({ 'import/core-modules': ['electron'] })
-    expect(importType('electron/some/path/to/resource.json', electronContext)).to.equal('builtin')
+    const electronContext = testContext({ 'import/core-modules': ['electron'] });
+    expect(importType('electron/some/path/to/resource.json', electronContext)).to.equal('builtin');
 
-    const scopedContext = testContext({ 'import/core-modules': ['@org/foobar'] })
-    expect(importType('@org/foobar/some/path/to/resource.json', scopedContext)).to.equal('builtin')
-  })
+    const scopedContext = testContext({ 'import/core-modules': ['@org/foobar'] });
+    expect(importType('@org/foobar/some/path/to/resource.json', scopedContext)).to.equal('builtin');
+  });
 
   it("should return 'external' for module from 'node_modules' with default config", function() {
-    expect(importType('resolve', context)).to.equal('external')
-  })
+    expect(importType('resolve', context)).to.equal('external');
+  });
 
   it("should return 'internal' for module from 'node_modules' if 'node_modules' missed in 'external-module-folders'", function() {
-    const foldersContext = testContext({ 'import/external-module-folders': [] })
-    expect(importType('resolve', foldersContext)).to.equal('internal')
-  })
+    const foldersContext = testContext({ 'import/external-module-folders': [] });
+    expect(importType('resolve', foldersContext)).to.equal('internal');
+  });
 
   it("should return 'internal' for module from 'node_modules' if its name matched 'internal-regex'", function() {
-    const foldersContext = testContext({ 'import/internal-regex': '^@org' })
-    expect(importType('@org/foobar', foldersContext)).to.equal('internal')
-  })
+    const foldersContext = testContext({ 'import/internal-regex': '^@org' });
+    expect(importType('@org/foobar', foldersContext)).to.equal('internal');
+  });
 
   it("should return 'external' for module from 'node_modules' if its name did not match 'internal-regex'", function() {
-    const foldersContext = testContext({ 'import/internal-regex': '^@bar' })
-    expect(importType('@org/foobar', foldersContext)).to.equal('external')
-  })
+    const foldersContext = testContext({ 'import/internal-regex': '^@bar' });
+    expect(importType('@org/foobar', foldersContext)).to.equal('external');
+  });
 
   it("should return 'external' for module from 'node_modules' if 'node_modules' contained in 'external-module-folders'", function() {
-    const foldersContext = testContext({ 'import/external-module-folders': ['node_modules'] })
-    expect(importType('resolve', foldersContext)).to.equal('external')
-  })
+    const foldersContext = testContext({ 'import/external-module-folders': ['node_modules'] });
+    expect(importType('resolve', foldersContext)).to.equal('external');
+  });
 
   it('returns "external" for a scoped symlinked module', function() {
     const foldersContext = testContext({
       'import/resolver': 'node',
       'import/external-module-folders': ['node_modules'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
-  })
+    });
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
+  });
 
   // We're using Webpack resolver here since it resolves all symlinks, which means that
   // directory path will not contain node_modules/<package-name> but will point to the
@@ -161,85 +161,85 @@ describe('importType(name)', function () {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['symlinked-module'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
-  })
+    });
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
+  });
 
   it('returns "internal" for a scoped module from a symlinked directory which incomplete name is contained in "external-module-folders" (webpack resolver)', function() {
     const foldersContext_1 = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['symlinked-mod'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext_1)).to.equal('internal')
+    });
+    expect(importType('@test-scope/some-module', foldersContext_1)).to.equal('internal');
 
     const foldersContext_2 = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['linked-module'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal')
-  })
+    });
+    expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal');
+  });
 
   it('returns "external" for a scoped module from a symlinked directory which partial path is contained in "external-module-folders" (webpack resolver)', function() {
     const originalFoldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': [],
-    })
-    expect(importType('@test-scope/some-module', originalFoldersContext)).to.equal('internal')
+    });
+    expect(importType('@test-scope/some-module', originalFoldersContext)).to.equal('internal');
 
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['files/symlinked-module'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
-  })
+    });
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
+  });
 
   it('returns "internal" for a scoped module from a symlinked directory which partial path w/ incomplete segment is contained in "external-module-folders" (webpack resolver)', function() {
     const foldersContext_1 = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['files/symlinked-mod'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext_1)).to.equal('internal')
+    });
+    expect(importType('@test-scope/some-module', foldersContext_1)).to.equal('internal');
 
     const foldersContext_2 = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['les/symlinked-module'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal')
-  })
+    });
+    expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal');
+  });
 
   it('returns "external" for a scoped module from a symlinked directory which partial path ending w/ slash is contained in "external-module-folders" (webpack resolver)', function() {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['files/symlinked-module/'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
-  })
+    });
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
+  });
 
   it('returns "internal" for a scoped module from a symlinked directory when "external-module-folders" contains an absolute path resembling directory‘s relative path (webpack resolver)', function() {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['/files/symlinked-module'],
-    })
-    expect(importType('@test-scope/some-module', foldersContext)).to.equal('internal')
-  })
+    });
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('internal');
+  });
 
   it('returns "external" for a scoped module from a symlinked directory which absolute path is contained in "external-module-folders" (webpack resolver)', function() {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': [testFilePath('symlinked-module')],
-    })
-    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external')
-  })
+    });
+    expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
+  });
 
   it('`isExternalModule` works with windows directory separator', function() {
-    expect(isExternalModule('foo', {}, 'E:\\path\\to\\node_modules\\foo')).to.equal(true)
+    expect(isExternalModule('foo', {}, 'E:\\path\\to\\node_modules\\foo')).to.equal(true);
     expect(isExternalModule('foo', {
       'import/external-module-folders': ['E:\\path\\to\\node_modules'],
-    }, 'E:\\path\\to\\node_modules\\foo')).to.equal(true)
-  })
+    }, 'E:\\path\\to\\node_modules\\foo')).to.equal(true);
+  });
 
   it('correctly identifies scoped modules with `isScopedModule`', () => {
-    expect(isScopedModule('@/abc')).to.equal(false)
-    expect(isScopedModule('@a/abc')).to.equal(true)
-  })
-})
+    expect(isScopedModule('@/abc')).to.equal(false);
+    expect(isScopedModule('@a/abc')).to.equal(true);
+  });
+});
diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index 72d232730d..4535a7d933 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -1,73 +1,73 @@
-import * as fs from 'fs'
-import { expect } from 'chai'
-import sinon from 'sinon'
-import parse from 'eslint-module-utils/parse'
+import * as fs from 'fs';
+import { expect } from 'chai';
+import sinon from 'sinon';
+import parse from 'eslint-module-utils/parse';
 
-import { getFilename } from '../utils'
+import { getFilename } from '../utils';
 
 describe('parse(content, { settings, ecmaFeatures })', function () {
-  const path = getFilename('jsx.js')
-  const parseStubParser = require('./parseStubParser')
-  const parseStubParserPath = require.resolve('./parseStubParser')
-  const eslintParser = require('./eslintParser')
-  const eslintParserPath = require.resolve('./eslintParser')
-  let content
+  const path = getFilename('jsx.js');
+  const parseStubParser = require('./parseStubParser');
+  const parseStubParserPath = require.resolve('./parseStubParser');
+  const eslintParser = require('./eslintParser');
+  const eslintParserPath = require.resolve('./eslintParser');
+  let content;
 
   before((done) =>
     fs.readFile(path, { encoding: 'utf8' },
-      (err, f) => { if (err) { done(err) } else { content = f; done() }}))
+      (err, f) => { if (err) { done(err); } else { content = f; done(); }}));
 
   it('doesn\'t support JSX by default', function () {
-    expect(() => parse(path, content, { parserPath: 'espree' })).to.throw(Error)
-  })
+    expect(() => parse(path, content, { parserPath: 'espree' })).to.throw(Error);
+  });
 
   it('infers jsx from ecmaFeatures when using stock parser', function () {
     expect(() => parse(path, content, { settings: {}, parserPath: 'espree', parserOptions: { ecmaVersion: 2015, sourceType: 'module', ecmaFeatures: { jsx: true } } }))
-      .not.to.throw(Error)
-  })
+      .not.to.throw(Error);
+  });
 
   it('passes expected parserOptions to custom parser', function () {
-    const parseSpy = sinon.spy()
-    const parserOptions = { ecmaFeatures: { jsx: true } }
-    parseStubParser.parse = parseSpy
-    parse(path, content, { settings: {}, parserPath: parseStubParserPath, parserOptions: parserOptions })
-    expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1)
-    expect(parseSpy.args[0][0], 'custom parser to get content as its first argument').to.equal(content)
-    expect(parseSpy.args[0][1], 'custom parser to get an object as its second argument').to.be.an('object')
-    expect(parseSpy.args[0][1], 'custom parser to clone the parserOptions object').to.not.equal(parserOptions)
+    const parseSpy = sinon.spy();
+    const parserOptions = { ecmaFeatures: { jsx: true } };
+    parseStubParser.parse = parseSpy;
+    parse(path, content, { settings: {}, parserPath: parseStubParserPath, parserOptions: parserOptions });
+    expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
+    expect(parseSpy.args[0][0], 'custom parser to get content as its first argument').to.equal(content);
+    expect(parseSpy.args[0][1], 'custom parser to get an object as its second argument').to.be.an('object');
+    expect(parseSpy.args[0][1], 'custom parser to clone the parserOptions object').to.not.equal(parserOptions);
     expect(parseSpy.args[0][1], 'custom parser to get ecmaFeatures in parserOptions which is a clone of ecmaFeatures passed in')
       .to.have.property('ecmaFeatures')
         .that.is.eql(parserOptions.ecmaFeatures)
-        .and.is.not.equal(parserOptions.ecmaFeatures)
-    expect(parseSpy.args[0][1], 'custom parser to get parserOptions.attachComment equal to true').to.have.property('attachComment', true)
-    expect(parseSpy.args[0][1], 'custom parser to get parserOptions.tokens equal to true').to.have.property('tokens', true)
-    expect(parseSpy.args[0][1], 'custom parser to get parserOptions.range equal to true').to.have.property('range', true)
-    expect(parseSpy.args[0][1], 'custom parser to get parserOptions.filePath equal to the full path of the source file').to.have.property('filePath', path)
-  })
+        .and.is.not.equal(parserOptions.ecmaFeatures);
+    expect(parseSpy.args[0][1], 'custom parser to get parserOptions.attachComment equal to true').to.have.property('attachComment', true);
+    expect(parseSpy.args[0][1], 'custom parser to get parserOptions.tokens equal to true').to.have.property('tokens', true);
+    expect(parseSpy.args[0][1], 'custom parser to get parserOptions.range equal to true').to.have.property('range', true);
+    expect(parseSpy.args[0][1], 'custom parser to get parserOptions.filePath equal to the full path of the source file').to.have.property('filePath', path);
+  });
 
   it('passes with custom `parseForESLint` parser', function () {
-    const parseForESLintSpy = sinon.spy(eslintParser, 'parseForESLint')
-    const parseSpy = sinon.spy()
-    eslintParser.parse = parseSpy
-    parse(path, content, { settings: {}, parserPath: eslintParserPath })
-    expect(parseForESLintSpy.callCount, 'custom `parseForESLint` parser to be called once').to.equal(1)
-    expect(parseSpy.callCount, '`parseForESLint` takes higher priority than `parse`').to.equal(0)
-  })
+    const parseForESLintSpy = sinon.spy(eslintParser, 'parseForESLint');
+    const parseSpy = sinon.spy();
+    eslintParser.parse = parseSpy;
+    parse(path, content, { settings: {}, parserPath: eslintParserPath });
+    expect(parseForESLintSpy.callCount, 'custom `parseForESLint` parser to be called once').to.equal(1);
+    expect(parseSpy.callCount, '`parseForESLint` takes higher priority than `parse`').to.equal(0);
+  });
 
   it('throws on context == null', function () {
-    expect(parse.bind(null, path, content, null)).to.throw(Error)
-  })
+    expect(parse.bind(null, path, content, null)).to.throw(Error);
+  });
 
   it('throws on unable to resolve parserPath', function () {
-    expect(parse.bind(null, path, content, { settings: {}, parserPath: null })).to.throw(Error)
-  })
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: null })).to.throw(Error);
+  });
 
   it('takes the alternate parser specified in settings', function () {
-    const parseSpy = sinon.spy()
-    const parserOptions = { ecmaFeatures: { jsx: true } }
-    parseStubParser.parse = parseSpy
-    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, parserOptions: parserOptions })).not.to.throw(Error)
-    expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1)
-  })
+    const parseSpy = sinon.spy();
+    const parserOptions = { ecmaFeatures: { jsx: true } };
+    parseStubParser.parse = parseSpy;
+    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, parserOptions: parserOptions })).not.to.throw(Error);
+    expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
+  });
 
-})
+});
diff --git a/tests/src/core/parseStubParser.js b/tests/src/core/parseStubParser.js
index 81daace434..9d17f0b041 100644
--- a/tests/src/core/parseStubParser.js
+++ b/tests/src/core/parseStubParser.js
@@ -1,4 +1,4 @@
 // this stub must be in a separate file to require from parse via moduleRequire
 module.exports = {
   parse: function () {},
-}
+};
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index 1aa2071db6..2e713846a3 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -1,273 +1,273 @@
-import { expect } from 'chai'
+import { expect } from 'chai';
 
-import resolve, { CASE_SENSITIVE_FS, fileExistsWithCaseSync } from 'eslint-module-utils/resolve'
-import ModuleCache from 'eslint-module-utils/ModuleCache'
+import resolve, { CASE_SENSITIVE_FS, fileExistsWithCaseSync } from 'eslint-module-utils/resolve';
+import ModuleCache from 'eslint-module-utils/ModuleCache';
 
-import * as path from 'path'
-import * as fs from 'fs'
-import * as utils from '../utils'
+import * as path from 'path';
+import * as fs from 'fs';
+import * as utils from '../utils';
 
 describe('resolve', function () {
   // We don't want to test for a specific stack, just that it was there in the error message.
   function replaceErrorStackForTest(str) {
-    return typeof str === 'string' ? str.replace(/(\n\s+at .+:\d+\)?)+$/, '\n<stack-was-here>') : str
+    return typeof str === 'string' ? str.replace(/(\n\s+at .+:\d+\)?)+$/, '\n<stack-was-here>') : str;
   }
 
   it('throws on bad parameters', function () {
-    expect(resolve.bind(null, null, null)).to.throw(Error)
-  })
+    expect(resolve.bind(null, null, null)).to.throw(Error);
+  });
 
   it('resolves via a custom resolver with interface version 1', function () {
-    const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' })
+    const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'))
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                      )).to.equal(utils.testFilePath('./bar.jsx'));
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
-                    )).to.equal(undefined)
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+                    )).to.equal(undefined);
 
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } }),
-                    )).to.equal(undefined)
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+                    )).to.equal(undefined);
+  });
 
   it('resolves via a custom resolver with interface version 1 assumed if not specified', function () {
-    const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' })
+    const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'))
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                      )).to.equal(utils.testFilePath('./bar.jsx'));
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
-                    )).to.equal(undefined)
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+                    )).to.equal(undefined);
 
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } }),
-                    )).to.equal(undefined)
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+                    )).to.equal(undefined);
+  });
 
   it('resolves via a custom resolver with interface version 2', function () {
-    const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v2' })
-    const testContextReports = []
+    const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v2' });
+    const testContextReports = [];
     testContext.report = function (reportInfo) {
-      testContextReports.push(reportInfo)
-    }
+      testContextReports.push(reportInfo);
+    };
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'))
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                      )).to.equal(utils.testFilePath('./bar.jsx'));
 
-    testContextReports.length = 0
+    testContextReports.length = 0;
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
-                    )).to.equal(undefined)
-    expect(testContextReports[0]).to.be.an('object')
-    expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>')
-    expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+                    )).to.equal(undefined);
+    expect(testContextReports[0]).to.be.an('object');
+    expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>');
+    expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
 
-    testContextReports.length = 0
+    testContextReports.length = 0;
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js') } }),
-                    )).to.equal(undefined)
-    expect(testContextReports.length).to.equal(0)
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+                    )).to.equal(undefined);
+    expect(testContextReports.length).to.equal(0);
+  });
 
   it('respects import/resolver as array of strings', function () {
-    const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] })
+    const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'))
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                      )).to.equal(utils.testFilePath('./bar.jsx'));
+  });
 
   it('respects import/resolver as object', function () {
-    const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } })
+    const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'))
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                      )).to.equal(utils.testFilePath('./bar.jsx'));
+  });
 
   it('respects import/resolver as array of objects', function () {
-    const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] })
+    const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'))
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                      )).to.equal(utils.testFilePath('./bar.jsx'));
+  });
 
   it('finds resolvers from the source files rather than eslint-module-utils', function () {
-    const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } })
+    const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'))
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                      )).to.equal(utils.testFilePath('./bar.jsx'));
+  });
 
   it('reports invalid import/resolver config', function () {
-    const testContext = utils.testContext({ 'import/resolver': 123.456 })
-    const testContextReports = []
+    const testContext = utils.testContext({ 'import/resolver': 123.456 });
+    const testContextReports = [];
     testContext.report = function (reportInfo) {
-      testContextReports.push(reportInfo)
-    }
+      testContextReports.push(reportInfo);
+    };
 
-    testContextReports.length = 0
+    testContextReports.length = 0;
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                    )).to.equal(undefined)
-    expect(testContextReports[0]).to.be.an('object')
-    expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config')
-    expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 })
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                    )).to.equal(undefined);
+    expect(testContextReports[0]).to.be.an('object');
+    expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config');
+    expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
+  });
 
   it('reports loaded resolver with invalid interface', function () {
-    const resolverName = './foo-bar-resolver-invalid'
-    const testContext = utils.testContext({ 'import/resolver': resolverName })
-    const testContextReports = []
+    const resolverName = './foo-bar-resolver-invalid';
+    const testContext = utils.testContext({ 'import/resolver': resolverName });
+    const testContextReports = [];
     testContext.report = function (reportInfo) {
-      testContextReports.push(reportInfo)
-    }
-    testContextReports.length = 0
+      testContextReports.push(reportInfo);
+    };
+    testContextReports.length = 0;
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js') } }),
-                    )).to.equal(undefined)
-    expect(testContextReports[0]).to.be.an('object')
-    expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`)
-    expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 })
-  })
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+                    )).to.equal(undefined);
+    expect(testContextReports[0]).to.be.an('object');
+    expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`);
+    expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
+  });
 
   it('respects import/resolve extensions', function () {
-    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }})
+    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }});
 
     expect(resolve( './jsx/MyCoolComponent'
                       , testContext,
-                      )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx'))
-  })
+                      )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx'));
+  });
 
   it('reports load exception in a user resolver', function () {
-    const testContext = utils.testContext({ 'import/resolver': './load-error-resolver' })
-    const testContextReports = []
+    const testContext = utils.testContext({ 'import/resolver': './load-error-resolver' });
+    const testContextReports = [];
     testContext.report = function (reportInfo) {
-      testContextReports.push(reportInfo)
-    }
+      testContextReports.push(reportInfo);
+    };
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }),
-                    )).to.equal(undefined)
-    expect(testContextReports[0]).to.be.an('object')
-    expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>')
-    expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 })
-  })
-
-  const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip)
+                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+                    )).to.equal(undefined);
+    expect(testContextReports[0]).to.be.an('object');
+    expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>');
+    expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
+  });
+
+  const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip);
   caseDescribe('case sensitivity', function () {
-    let file
-    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }})
+    let file;
+    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }});
     before('resolve', function () {
       file = resolve(
       // Note the case difference 'MyUncoolComponent' vs 'MyUnCoolComponent'
-        './jsx/MyUncoolComponent', testContext)
-    })
+        './jsx/MyUncoolComponent', testContext);
+    });
     it('resolves regardless of case', function () {
-      expect(file, 'path to ./jsx/MyUncoolComponent').to.exist
-    })
+      expect(file, 'path to ./jsx/MyUncoolComponent').to.exist;
+    });
     it('detects case does not match FS', function () {
       expect(fileExistsWithCaseSync(file, ModuleCache.getSettings(testContext)))
-        .to.be.false
-    })
+        .to.be.false;
+    });
     it('detecting case does not include parent folder path (issue #720)', function () {
-      const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx')
+      const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx');
       expect(fileExistsWithCaseSync(f, ModuleCache.getSettings(testContext), true))
-        .to.be.true
-    })
-  })
+        .to.be.true;
+    });
+  });
 
   describe('rename cache correctness', function () {
     const context = utils.testContext({
       'import/cache': { 'lifetime': 1 },
-    })
+    });
 
     const infiniteContexts = [ '∞', 'Infinity' ].map(inf => [inf,
       utils.testContext({
         'import/cache': { 'lifetime': inf },
-      })])
+      })]);
 
 
     const pairs = [
       ['./CaseyKasem.js', './CASEYKASEM2.js'],
-    ]
+    ];
 
     pairs.forEach(([original, changed]) => {
       describe(`${original} => ${changed}`, function () {
 
         before('sanity check', function () {
-          expect(resolve(original, context)).to.exist
-          expect(resolve(changed, context)).not.to.exist
-        })
+          expect(resolve(original, context)).to.exist;
+          expect(resolve(changed, context)).not.to.exist;
+        });
 
         // settings are part of cache key
         before('warm up infinite entries', function () {
           infiniteContexts.forEach(([,c]) => {
-            expect(resolve(original, c)).to.exist
-          })
-        })
+            expect(resolve(original, c)).to.exist;
+          });
+        });
 
         before('rename', function (done) {
           fs.rename(
             utils.testFilePath(original),
             utils.testFilePath(changed),
-            done)
-        })
+            done);
+        });
 
         before('verify rename', (done) =>
           fs.exists(
             utils.testFilePath(changed),
-            exists => done(exists ? null : new Error('new file does not exist'))))
+            exists => done(exists ? null : new Error('new file does not exist'))));
 
         it('gets cached values within cache lifetime', function () {
           // get cached values initially
-          expect(resolve(original, context)).to.exist
-        })
+          expect(resolve(original, context)).to.exist;
+        });
 
         it('gets updated values immediately', function () {
           // get cached values initially
-          expect(resolve(changed, context)).to.exist
-        })
+          expect(resolve(changed, context)).to.exist;
+        });
 
         // special behavior for infinity
         describe('infinite cache', function () {
-          this.timeout(1500)
+          this.timeout(1500);
 
-          before((done) => setTimeout(done, 1100))
+          before((done) => setTimeout(done, 1100));
 
           infiniteContexts.forEach(([inf, infiniteContext]) => {
             it(`lifetime: ${inf} still gets cached values after ~1s`, function () {
-              expect(resolve(original, infiniteContext), original).to.exist
-            })
-          })
+              expect(resolve(original, infiniteContext), original).to.exist;
+            });
+          });
 
-        })
+        });
 
         describe('finite cache', function () {
-          this.timeout(1200)
-          before((done) => setTimeout(done, 1000))
+          this.timeout(1200);
+          before((done) => setTimeout(done, 1000));
           it('gets correct values after cache lifetime', function () {
-            expect(resolve(original, context)).not.to.exist
-            expect(resolve(changed, context)).to.exist
-          })
-        })
+            expect(resolve(original, context)).not.to.exist;
+            expect(resolve(changed, context)).to.exist;
+          });
+        });
 
         after('restore original case', function (done) {
           fs.rename(
             utils.testFilePath(changed),
             utils.testFilePath(original),
-            done)
-        })
-      })
-    })
-  })
+            done);
+        });
+      });
+    });
+  });
 
-})
+});
diff --git a/tests/src/package.js b/tests/src/package.js
index 700d4121b4..a7a60e2531 100644
--- a/tests/src/package.js
+++ b/tests/src/package.js
@@ -1,58 +1,58 @@
-var expect = require('chai').expect
+var expect = require('chai').expect;
 
 var path = require('path')
-  , fs = require('fs')
+  , fs = require('fs');
 
 function isJSFile(f) {
-  return path.extname(f) === '.js'
+  return path.extname(f) === '.js';
 }
 
 describe('package', function () {
   let pkg = path.join(process.cwd(), 'src')
-    , module
+    , module;
 
   before('is importable', function () {
-    module = require(pkg)
-  })
+    module = require(pkg);
+  });
 
   it('exists', function () {
-    expect(module).to.exist
-  })
+    expect(module).to.exist;
+  });
 
   it('has every rule', function (done) {
 
     fs.readdir(
       path.join(pkg, 'rules')
     , function (err, files) {
-        expect(err).not.to.exist
+        expect(err).not.to.exist;
 
         files.filter(isJSFile).forEach(function (f) {
           expect(module.rules).to.have
-            .property(path.basename(f, '.js'))
-        })
+            .property(path.basename(f, '.js'));
+        });
 
-        done()
-      })
-  })
+        done();
+      });
+  });
 
   it('exports all configs', function (done) {
     fs.readdir(path.join(process.cwd(), 'config'), function (err, files) {
-      if (err) { done(err); return }
+      if (err) { done(err); return; }
       files.filter(isJSFile).forEach(file => {
-        if (file[0] === '.') return
-        expect(module.configs).to.have.property(path.basename(file, '.js'))
-      })
-      done()
-    })
-  })
+        if (file[0] === '.') return;
+        expect(module.configs).to.have.property(path.basename(file, '.js'));
+      });
+      done();
+    });
+  });
 
   it('has configs only for rules that exist', function () {
     for (let configFile in module.configs) {
-      let preamble = 'import/'
+      let preamble = 'import/';
 
       for (let rule in module.configs[configFile].rules) {
         expect(() => require(getRulePath(rule.slice(preamble.length))))
-          .not.to.throw(Error)
+          .not.to.throw(Error);
       }
     }
 
@@ -60,13 +60,13 @@ describe('package', function () {
       // 'require' does not work with dynamic paths because of the compilation step by babel
       // (which resolves paths according to the root folder configuration)
       // the usage of require.resolve on a static path gets around this
-      return path.resolve(require.resolve('rules/no-unresolved'), '..', ruleName)
+      return path.resolve(require.resolve('rules/no-unresolved'), '..', ruleName);
     }
-  })
+  });
 
   it('marks deprecated rules in their metadata', function () {
-    expect(module.rules['imports-first'].meta.deprecated).to.be.true
-    expect(module.rules['first'].meta.deprecated).not.to.be.true
-  })
+    expect(module.rules['imports-first'].meta.deprecated).to.be.true;
+    expect(module.rules['first'].meta.deprecated).not.to.be.true;
+  });
 
-})
+});
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index 3f2c8dac1f..f80957a442 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -1,11 +1,11 @@
-import path from 'path'
-import { test, SYNTAX_CASES, getTSParsers } from '../utils'
-import { RuleTester } from 'eslint'
+import path from 'path';
+import { test, SYNTAX_CASES, getTSParsers } from '../utils';
+import { RuleTester } from 'eslint';
 
-import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve'
+import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
 var ruleTester = new RuleTester()
-  , rule = require('rules/default')
+  , rule = require('rules/default');
 
 ruleTester.run('default', rule, {
   valid: [
@@ -135,7 +135,7 @@ ruleTester.run('default', rule, {
       errors: ['No default export found in imported module "./re-export".'],
     }),
   ],
-})
+});
 
 // #311: import of mismatched case
 if (!CASE_SENSITIVE_FS) {
@@ -151,7 +151,7 @@ if (!CASE_SENSITIVE_FS) {
         errors: ['No default export found in imported module "./Named-Exports".'],
       }),
     ],
-  })
+  });
 }
 
 context('TypeScript', function () {
@@ -259,6 +259,6 @@ context('TypeScript', function () {
             errors: ['No default export found in imported module "./typescript-export-as-default-namespace".'],
           }),
         ],
-      })
-    })
-})
+      });
+    });
+});
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index cd321019d2..a2ee55f13a 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -1,28 +1,28 @@
-import { SYNTAX_CASES, getTSParsers } from '../utils'
-import { RuleTester } from 'eslint'
-import semver from 'semver'
+import { SYNTAX_CASES, getTSParsers } from '../utils';
+import { RuleTester } from 'eslint';
+import semver from 'semver';
 
-const rule = require('rules/dynamic-import-chunkname')
-const ruleTester = new RuleTester()
+const rule = require('rules/dynamic-import-chunkname');
+const ruleTester = new RuleTester();
 
-const commentFormat = '[0-9a-zA-Z-_/.]+'
-const pickyCommentFormat = '[a-zA-Z-_/.]+'
-const options = [{ importFunctions: ['dynamicImport'] }]
+const commentFormat = '[0-9a-zA-Z-_/.]+';
+const pickyCommentFormat = '[a-zA-Z-_/.]+';
+const options = [{ importFunctions: ['dynamicImport'] }];
 const pickyCommentOptions = [{
   importFunctions: ['dynamicImport'],
   webpackChunknameFormat: pickyCommentFormat,
-}]
+}];
 const multipleImportFunctionOptions = [{
   importFunctions: ['dynamicImport', 'definitelyNotStaticImport'],
-}]
-const parser = require.resolve('babel-eslint')
+}];
+const parser = require.resolve('babel-eslint');
 
-const noLeadingCommentError = 'dynamic imports require a leading comment with the webpack chunkname'
-const nonBlockCommentError = 'dynamic imports require a /* foo */ style comment, not a // foo comment'
-const noPaddingCommentError = 'dynamic imports require a block comment padded with spaces - /* foo */'
-const invalidSyntaxCommentError = 'dynamic imports require a "webpack" comment with valid syntax'
-const commentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${commentFormat}["'],? */`
-const pickyCommentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${pickyCommentFormat}["'],? */`
+const noLeadingCommentError = 'dynamic imports require a leading comment with the webpack chunkname';
+const nonBlockCommentError = 'dynamic imports require a /* foo */ style comment, not a // foo comment';
+const noPaddingCommentError = 'dynamic imports require a block comment padded with spaces - /* foo */';
+const invalidSyntaxCommentError = 'dynamic imports require a "webpack" comment with valid syntax';
+const commentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${commentFormat}["'],? */`;
+const pickyCommentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${pickyCommentFormat}["'],? */`;
 
 ruleTester.run('dynamic-import-chunkname', rule, {
   valid: [
@@ -491,13 +491,13 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       }],
     },
   ],
-})
+});
 
 context('TypeScript', () => {
   getTSParsers().forEach((typescriptParser) => {
     const nodeType = typescriptParser.includes('typescript-eslint-parser') || (typescriptParser.includes('@typescript-eslint/parser') && semver.satisfies(require('@typescript-eslint/parser/package.json').version, '^2'))
       ? 'CallExpression'
-      : 'ImportExpression'
+      : 'ImportExpression';
 
     ruleTester.run('dynamic-import-chunkname', rule, {
       valid: [
@@ -818,6 +818,6 @@ context('TypeScript', () => {
           }],
         },
       ],
-    })
-  })
-})
+    });
+  });
+});
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 12341c7da9..cee5e5ccb5 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -1,11 +1,11 @@
-import { test, testFilePath, SYNTAX_CASES, getTSParsers, testVersion } from '../utils'
+import { test, testFilePath, SYNTAX_CASES, getTSParsers, testVersion } from '../utils';
 
-import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
+import { RuleTester } from 'eslint';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
 var ruleTester = new RuleTester()
-  , rule = require('rules/export')
+  , rule = require('rules/export');
 
 ruleTester.run('export', rule, {
   valid: [].concat(
@@ -123,7 +123,7 @@ ruleTester.run('export', rule, {
       errors: [`No named exports found in module './default-export'.`],
     }),
   ],
-})
+});
 
 
 context('TypeScript', function () {
@@ -134,7 +134,7 @@ context('TypeScript', function () {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
-    }
+    };
 
     ruleTester.run('export', rule, {
       valid: [
@@ -361,6 +361,6 @@ context('TypeScript', function () {
           ],
         }, parserConfig)),
       ],
-    })
-  })
-})
+    });
+  });
+});
diff --git a/tests/src/rules/exports-last.js b/tests/src/rules/exports-last.js
index cc853ba76c..9f01f27f42 100644
--- a/tests/src/rules/exports-last.js
+++ b/tests/src/rules/exports-last.js
@@ -1,14 +1,14 @@
-import { test } from '../utils'
+import { test } from '../utils';
 
-import { RuleTester } from 'eslint'
-import rule from 'rules/exports-last'
+import { RuleTester } from 'eslint';
+import rule from 'rules/exports-last';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 const error = type => ({
   message: 'Export statements should appear at the end of the file',
   type,
-})
+});
 
 ruleTester.run('exports-last', rule, {
   valid: [
@@ -120,4 +120,4 @@ ruleTester.run('exports-last', rule, {
       ],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 93860c16ab..e06e6496d4 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -1,8 +1,8 @@
-import { RuleTester } from 'eslint'
-import rule from 'rules/extensions'
-import { test, testFilePath } from '../utils'
+import { RuleTester } from 'eslint';
+import rule from 'rules/extensions';
+import { test, testFilePath } from '../utils';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 ruleTester.run('extensions', rule, {
   valid: [
@@ -455,4 +455,4 @@ ruleTester.run('extensions', rule, {
       ],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index 8c5d72a34c..603a595d91 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -1,9 +1,9 @@
-import { test } from '../utils'
+import { test } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/first')
+    , rule = require('rules/first');
 
 ruleTester.run('first', rule, {
   valid: [
@@ -67,4 +67,4 @@ ruleTester.run('first', rule, {
   })
   ,
   ],
-})
+});
diff --git a/tests/src/rules/group-exports.js b/tests/src/rules/group-exports.js
index 0766a325e6..a3f2a11d5d 100644
--- a/tests/src/rules/group-exports.js
+++ b/tests/src/rules/group-exports.js
@@ -1,14 +1,14 @@
-import { test } from '../utils'
-import { RuleTester } from 'eslint'
-import rule from 'rules/group-exports'
-import {resolve} from 'path'
-import {default as babelPresetFlow} from 'babel-preset-flow'
+import { test } from '../utils';
+import { RuleTester } from 'eslint';
+import rule from 'rules/group-exports';
+import {resolve} from 'path';
+import {default as babelPresetFlow} from 'babel-preset-flow';
 
 /* eslint-disable max-len */
 const errors = {
   named: 'Multiple named export declarations; consolidate all named exports into a single export declaration',
   commonjs: 'Multiple CommonJS exports; consolidate all exports into a single assignment to `module.exports`',
-}
+};
 /* eslint-enable max-len */
 const ruleTester = new RuleTester({
   parser: resolve(__dirname, '../../../node_modules/babel-eslint'),
@@ -19,7 +19,7 @@ const ruleTester = new RuleTester({
       presets: [babelPresetFlow],
     },
   },
-})
+});
 
 ruleTester.run('group-exports', rule, {
   valid: [
@@ -292,4 +292,4 @@ ruleTester.run('group-exports', rule, {
       ],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/max-dependencies.js b/tests/src/rules/max-dependencies.js
index ee35b648fb..09d13a060c 100644
--- a/tests/src/rules/max-dependencies.js
+++ b/tests/src/rules/max-dependencies.js
@@ -1,9 +1,9 @@
-import { test } from '../utils'
+import { test } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/max-dependencies')
+    , rule = require('rules/max-dependencies');
 
 ruleTester.run('max-dependencies', rule, {
   valid: [
@@ -75,4 +75,4 @@ ruleTester.run('max-dependencies', rule, {
       ],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 030368877f..3a23e3e93d 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -1,15 +1,15 @@
-import { test, SYNTAX_CASES, getTSParsers } from '../utils'
-import { RuleTester } from 'eslint'
+import { test, SYNTAX_CASES, getTSParsers } from '../utils';
+import { RuleTester } from 'eslint';
 
-import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve'
+import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
 
 var ruleTester = new RuleTester()
-  , rule = require('rules/named')
+  , rule = require('rules/named');
 
 function error(name, module) {
   return { message: name + ' not found in \'' + module + '\''
-         , type: 'Identifier' }
+         , type: 'Identifier' };
 }
 
 ruleTester.run('named', rule, {
@@ -248,7 +248,7 @@ ruleTester.run('named', rule, {
       errors: [`default not found in './re-export'`],
     }),
   ],
-})
+});
 
 // #311: import of mismatched case
 if (!CASE_SENSITIVE_FS) {
@@ -264,7 +264,7 @@ if (!CASE_SENSITIVE_FS) {
         errors: [`foo not found in './Named-Exports'`],
       }),
     ],
-  })
+  });
 }
 
 // export-all
@@ -280,7 +280,7 @@ ruleTester.run('named (export *)', rule, {
       errors: [`bar not found in './export-all'`],
     }),
   ],
-})
+});
 
 
 context('TypeScript', function () {
@@ -383,7 +383,7 @@ context('TypeScript', function () {
             }],
           }),
         ],
-      })
-    })
-  })
-})
+      });
+    });
+  });
+});
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 93d503eb4f..63192228b6 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -1,13 +1,13 @@
-import { test, SYNTAX_CASES, getTSParsers } from '../utils'
-import { RuleTester } from 'eslint'
-import flatMap from 'array.prototype.flatmap'
+import { test, SYNTAX_CASES, getTSParsers } from '../utils';
+import { RuleTester } from 'eslint';
+import flatMap from 'array.prototype.flatmap';
 
 var ruleTester = new RuleTester({ env: { es6: true }})
-  , rule = require('rules/namespace')
+  , rule = require('rules/namespace');
 
 
 function error(name, namespace) {
-  return { message: `'${name}' not found in imported namespace '${namespace}'.` }
+  return { message: `'${name}' not found in imported namespace '${namespace}'.` };
 }
 
 const valid = [
@@ -172,7 +172,7 @@ const valid = [
     export const getExampleColor = () => color.example
     `,
   }),
-]
+];
 
 const invalid = [
   test({ code: "import * as names from './named-exports'; " +
@@ -274,7 +274,7 @@ const invalid = [
     test({ parser, code: `import { b } from "./${folder}/a"; console.log(b.c.d.e)` }),
     test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.c.d.e.f)` }),
     test({ parser, code: `import * as a from "./${folder}/a"; var {b:{c:{d:{e}}}} = a` }),
-    test({ parser, code: `import { b } from "./${folder}/a"; var {c:{d:{e}}} = b` }))
+    test({ parser, code: `import { b } from "./${folder}/a"; var {c:{d:{e}}} = b` }));
 
     // deep namespaces should include explicitly exported defaults
     test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.default)` }),
@@ -309,7 +309,7 @@ const invalid = [
       parser,
       code: `import * as a from "./${folder}/a"; var {b:{c:{ e }}} = a`,
       errors: [ "'e' not found in deeply imported namespace 'a.b.c'." ],
-    }))
-})
+    }));
+});
 
-ruleTester.run('namespace', rule, { valid, invalid })
+ruleTester.run('namespace', rule, { valid, invalid });
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index fcd7c72a9f..9965f315ed 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -1,15 +1,15 @@
-import { RuleTester } from 'eslint'
-import flatMap from 'array.prototype.flatmap'
+import { RuleTester } from 'eslint';
+import flatMap from 'array.prototype.flatmap';
 
-import { getTSParsers } from '../utils'
+import { getTSParsers } from '../utils';
 
-const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.'
+const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.';
 const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => {
-    return `Expected ${count} empty lines after import statement not followed by another import.`
-}
-const REQUIRE_ERROR_MESSAGE = 'Expected 1 empty line after require statement not followed by another require.'
+    return `Expected ${count} empty lines after import statement not followed by another import.`;
+};
+const REQUIRE_ERROR_MESSAGE = 'Expected 1 empty line after require statement not followed by another require.';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
   valid: [
@@ -430,4 +430,4 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parser: require.resolve('babel-eslint'),
     },
   ],
-})
+});
diff --git a/tests/src/rules/no-absolute-path.js b/tests/src/rules/no-absolute-path.js
index 2a95829b00..e22d867f09 100644
--- a/tests/src/rules/no-absolute-path.js
+++ b/tests/src/rules/no-absolute-path.js
@@ -1,13 +1,13 @@
-import { test } from '../utils'
+import { test } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-absolute-path')
+    , rule = require('rules/no-absolute-path');
 
 const error = {
   message: 'Do not import modules using an absolute path',
-}
+};
 
 ruleTester.run('no-absolute-path', rule, {
   valid: [
@@ -97,4 +97,4 @@ ruleTester.run('no-absolute-path', rule, {
       errors: [error],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-amd.js b/tests/src/rules/no-amd.js
index 62de5ac26a..b7f7793842 100644
--- a/tests/src/rules/no-amd.js
+++ b/tests/src/rules/no-amd.js
@@ -1,8 +1,8 @@
-import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
+import { RuleTester } from 'eslint';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
-var ruleTester = new RuleTester()
+var ruleTester = new RuleTester();
 
 ruleTester.run('no-amd', require('rules/no-amd'), {
   valid: [
@@ -34,4 +34,4 @@ ruleTester.run('no-amd', require('rules/no-amd'), {
       { code: 'require([], function() {})', errors: [ { message: 'Expected imports instead of AMD require().' }] },
       { code: 'require(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD require().' }] },
 	],
-})
+});
diff --git a/tests/src/rules/no-anonymous-default-export.js b/tests/src/rules/no-anonymous-default-export.js
index c872cf4d09..735f2dbd58 100644
--- a/tests/src/rules/no-anonymous-default-export.js
+++ b/tests/src/rules/no-anonymous-default-export.js
@@ -1,9 +1,9 @@
-import { test, SYNTAX_CASES } from '../utils'
+import { test, SYNTAX_CASES } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-const rule = require('rules/no-anonymous-default-export')
+const ruleTester = new RuleTester();
+const rule = require('rules/no-anonymous-default-export');
 
 ruleTester.run('no-anonymous-default-export', rule, {
     valid: [
@@ -52,4 +52,4 @@ ruleTester.run('no-anonymous-default-export', rule, {
       // Test failure with non-covering exception
       test({ code: 'export default 123', options: [{ allowObject: true }], errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
     ],
-})
+});
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index d2c4ed3100..f474abd5cd 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -1,11 +1,11 @@
-import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
+import { RuleTester } from 'eslint';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
 const EXPORT_MESSAGE = 'Expected "export" or "export default"'
-    , IMPORT_MESSAGE = 'Expected "import" instead of "require()"'
+    , IMPORT_MESSAGE = 'Expected "import" instead of "require()"';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
   valid: [
@@ -106,4 +106,4 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
       errors: [ { message: EXPORT_MESSAGE }],
     },
   ],
-})
+});
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 2539ba5945..beb459ccfb 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -1,15 +1,15 @@
-import { test as _test, testFilePath } from '../utils'
+import { test as _test, testFilePath } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-cycle')
+    , rule = require('rules/no-cycle');
 
-const error = message => ({ message })
+const error = message => ({ message });
 
 const test = def => _test(Object.assign(def, {
   filename: testFilePath('./cycles/depth-zero.js'),
-}))
+}));
 
 // describe.only("no-cycle", () => {
 ruleTester.run('no-cycle', rule, {
@@ -172,5 +172,5 @@ ruleTester.run('no-cycle', rule, {
       errors: [error(`Dependency cycle via ./depth-one:1`)],
     }),
   ],
-})
+});
 // })
diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index d11b7d3b11..d0c89bfd34 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -1,9 +1,9 @@
-import { test } from '../utils'
+import { test } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-default-export')
+    , rule = require('rules/no-default-export');
 
 ruleTester.run('no-default-export', rule, {
   valid: [
@@ -119,4 +119,4 @@ ruleTester.run('no-default-export', rule, {
       }],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index 36a137f7ad..2c84134154 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -1,9 +1,9 @@
-import { test, SYNTAX_CASES, getTSParsers } from '../utils'
+import { test, SYNTAX_CASES, getTSParsers } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-deprecated')
+    , rule = require('rules/no-deprecated');
 
 ruleTester.run('no-deprecated', rule, {
   valid: [
@@ -174,7 +174,7 @@ ruleTester.run('no-deprecated', rule, {
       ],
     }),
   ],
-})
+});
 
 ruleTester.run('no-deprecated: hoisting', rule, {
   valid: [
@@ -196,7 +196,7 @@ ruleTester.run('no-deprecated: hoisting', rule, {
     }),
 
   ],
-})
+});
 
 describe('TypeScript', function () {
   getTSParsers().forEach((parser) => {
@@ -206,7 +206,7 @@ describe('TypeScript', function () {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
-    }
+    };
 
     ruleTester.run(parser, rule, {
       valid: [
@@ -223,6 +223,6 @@ describe('TypeScript', function () {
           ]},
           parserConfig)),
       ],
-    })
-  })
-})
+    });
+  });
+});
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 0137221b03..4579e66744 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -1,14 +1,14 @@
-import * as path from 'path'
-import { test as testUtil, getNonDefaultParsers } from '../utils'
+import * as path from 'path';
+import { test as testUtil, getNonDefaultParsers } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-duplicates')
+    , rule = require('rules/no-duplicates');
 
 const test = process.env.ESLINT_VERSION === '3' || process.env.ESLINT_VERSION === '2'
   ? t => testUtil(Object.assign({}, t, {output: t.code}))
-  : testUtil
+  : testUtil;
 
 ruleTester.run('no-duplicates', rule, {
   valid: [
@@ -398,7 +398,7 @@ ruleTester.run('no-duplicates', rule, {
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
   ],
-})
+});
 
 context('TypeScript', function() {
   getNonDefaultParsers()
@@ -410,7 +410,7 @@ context('TypeScript', function() {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
-    }
+    };
 
     ruleTester.run('no-duplicates', rule, {
       valid: [
@@ -424,7 +424,7 @@ context('TypeScript', function() {
         ),
       ],
       invalid: [],
-    })
-  })
-})
+    });
+  });
+});
 
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index 5846032004..27ebd6fe44 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -1,13 +1,13 @@
-import { test } from '../utils'
+import { test } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-dynamic-require')
+    , rule = require('rules/no-dynamic-require');
 
 const error = {
   message: 'Calls to require() should use string literals',
-}
+};
 
 ruleTester.run('no-dynamic-require', rule, {
   valid: [
@@ -45,4 +45,4 @@ ruleTester.run('no-dynamic-require', rule, {
       errors: [error],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 77de28b339..8940c9be9d 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -1,38 +1,38 @@
-import { getTSParsers, test, testFilePath } from '../utils'
-import typescriptConfig from '../../../config/typescript'
-import path from 'path'
-import fs from 'fs'
-import semver from 'semver'
-import eslintPkg from 'eslint/package.json'
+import { getTSParsers, test, testFilePath } from '../utils';
+import typescriptConfig from '../../../config/typescript';
+import path from 'path';
+import fs from 'fs';
+import semver from 'semver';
+import eslintPkg from 'eslint/package.json';
 
-import { RuleTester } from 'eslint'
-import flatMap from 'array.prototype.flatmap'
+import { RuleTester } from 'eslint';
+import flatMap from 'array.prototype.flatmap';
 
-const ruleTester = new RuleTester()
-const typescriptRuleTester = new RuleTester(typescriptConfig)
-const rule = require('rules/no-extraneous-dependencies')
+const ruleTester = new RuleTester();
+const typescriptRuleTester = new RuleTester(typescriptConfig);
+const rule = require('rules/no-extraneous-dependencies');
 
-const packageDirWithSyntaxError = path.join(__dirname, '../../files/with-syntax-error')
+const packageDirWithSyntaxError = path.join(__dirname, '../../files/with-syntax-error');
 const packageFileWithSyntaxErrorMessage = (() => {
   try {
-    JSON.parse(fs.readFileSync(path.join(packageDirWithSyntaxError, 'package.json')))
+    JSON.parse(fs.readFileSync(path.join(packageDirWithSyntaxError, 'package.json')));
   } catch (error) {
-    return error.message
+    return error.message;
   }
-})()
-const packageDirWithFlowTyped = path.join(__dirname, '../../files/with-flow-typed')
-const packageDirWithTypescriptDevDependencies = path.join(__dirname, '../../files/with-typescript-dev-dependencies')
-const packageDirMonoRepoRoot = path.join(__dirname, '../../files/monorepo')
-const packageDirMonoRepoWithNested = path.join(__dirname, '../../files/monorepo/packages/nested-package')
-const packageDirWithEmpty = path.join(__dirname, '../../files/empty')
-const packageDirBundleDeps = path.join(__dirname, '../../files/bundled-dependencies/as-array-bundle-deps')
-const packageDirBundledDepsAsObject = path.join(__dirname, '../../files/bundled-dependencies/as-object')
-const packageDirBundledDepsRaceCondition = path.join(__dirname, '../../files/bundled-dependencies/race-condition')
+})();
+const packageDirWithFlowTyped = path.join(__dirname, '../../files/with-flow-typed');
+const packageDirWithTypescriptDevDependencies = path.join(__dirname, '../../files/with-typescript-dev-dependencies');
+const packageDirMonoRepoRoot = path.join(__dirname, '../../files/monorepo');
+const packageDirMonoRepoWithNested = path.join(__dirname, '../../files/monorepo/packages/nested-package');
+const packageDirWithEmpty = path.join(__dirname, '../../files/empty');
+const packageDirBundleDeps = path.join(__dirname, '../../files/bundled-dependencies/as-array-bundle-deps');
+const packageDirBundledDepsAsObject = path.join(__dirname, '../../files/bundled-dependencies/as-object');
+const packageDirBundledDepsRaceCondition = path.join(__dirname, '../../files/bundled-dependencies/race-condition');
 
 const {
   dependencies: deps,
   devDependencies: devDeps,
-} = require('../../files/package.json')
+} = require('../../files/package.json');
 
 ruleTester.run('no-extraneous-dependencies', rule, {
   valid: [
@@ -316,7 +316,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       }],
     }),
   ],
-})
+});
 
 describe('TypeScript', function () {
   getTSParsers().forEach((parser) => {
@@ -326,7 +326,7 @@ describe('TypeScript', function () {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
-    }
+    };
 
     if (parser !== require.resolve('typescript-eslint-parser')) {
       ruleTester.run('no-extraneous-dependencies', rule, {
@@ -345,7 +345,7 @@ describe('TypeScript', function () {
             }],
           }, parserConfig)),
         ],
-      })
+      });
     } else {
       ruleTester.run('no-extraneous-dependencies', rule, {
         valid: [],
@@ -365,10 +365,10 @@ describe('TypeScript', function () {
             }],
           }, parserConfig)),
         ],
-      })
+      });
     }
-  })
-})
+  });
+});
 
 if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
   typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', rule, {
@@ -386,5 +386,5 @@ if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
     ],
     invalid: [
     ],
-  })
+  });
 }
diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js
index da9a4ca1a0..1723f7df69 100644
--- a/tests/src/rules/no-internal-modules.js
+++ b/tests/src/rules/no-internal-modules.js
@@ -1,10 +1,10 @@
-import { RuleTester } from 'eslint'
-import flatMap from 'array.prototype.flatmap'
-import rule from 'rules/no-internal-modules'
+import { RuleTester } from 'eslint';
+import flatMap from 'array.prototype.flatmap';
+import rule from 'rules/no-internal-modules';
 
-import { test, testFilePath, getTSParsers } from '../utils'
+import { test, testFilePath, getTSParsers } from '../utils';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 ruleTester.run('no-internal-modules', rule, {
   valid: [
@@ -252,4 +252,4 @@ ruleTester.run('no-internal-modules', rule, {
       ],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-mutable-exports.js b/tests/src/rules/no-mutable-exports.js
index 6d83566b74..a4fd8f4c45 100644
--- a/tests/src/rules/no-mutable-exports.js
+++ b/tests/src/rules/no-mutable-exports.js
@@ -1,8 +1,8 @@
-import {test} from '../utils'
-import {RuleTester} from 'eslint'
-import rule from 'rules/no-mutable-exports'
+import {test} from '../utils';
+import {RuleTester} from 'eslint';
+import rule from 'rules/no-mutable-exports';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 ruleTester.run('no-mutable-exports', rule, {
   valid: [
@@ -77,4 +77,4 @@ ruleTester.run('no-mutable-exports', rule, {
     //   errors: ['Exporting mutable global binding, use \'const\' instead.'],
     // }),
   ],
-})
+});
diff --git a/tests/src/rules/no-named-as-default-member.js b/tests/src/rules/no-named-as-default-member.js
index b5e294d190..4845d7bb26 100644
--- a/tests/src/rules/no-named-as-default-member.js
+++ b/tests/src/rules/no-named-as-default-member.js
@@ -1,8 +1,8 @@
-import { test, SYNTAX_CASES } from '../utils'
-import {RuleTester} from 'eslint'
-import rule from 'rules/no-named-as-default-member'
+import { test, SYNTAX_CASES } from '../utils';
+import {RuleTester} from 'eslint';
+import rule from 'rules/no-named-as-default-member';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 ruleTester.run('no-named-as-default-member', rule, {
   valid: [
@@ -57,4 +57,4 @@ ruleTester.run('no-named-as-default-member', rule, {
       }],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-named-as-default.js b/tests/src/rules/no-named-as-default.js
index a5e0f041f5..ba796cedfa 100644
--- a/tests/src/rules/no-named-as-default.js
+++ b/tests/src/rules/no-named-as-default.js
@@ -1,8 +1,8 @@
-import { test, SYNTAX_CASES } from '../utils'
-import { RuleTester } from 'eslint'
+import { test, SYNTAX_CASES } from '../utils';
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-named-as-default')
+    , rule = require('rules/no-named-as-default');
 
 ruleTester.run('no-named-as-default', rule, {
   valid: [
@@ -58,4 +58,4 @@ ruleTester.run('no-named-as-default', rule, {
       }],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-named-default.js b/tests/src/rules/no-named-default.js
index f9109fa8fd..bffd3dda31 100644
--- a/tests/src/rules/no-named-default.js
+++ b/tests/src/rules/no-named-default.js
@@ -1,8 +1,8 @@
-import { test, SYNTAX_CASES } from '../utils'
-import { RuleTester } from 'eslint'
+import { test, SYNTAX_CASES } from '../utils';
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-named-default')
+    , rule = require('rules/no-named-default');
 
 ruleTester.run('no-named-default', rule, {
   valid: [
@@ -36,4 +36,4 @@ ruleTester.run('no-named-default', rule, {
       }],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-named-export.js b/tests/src/rules/no-named-export.js
index bde92b9e41..a47ad6b7a0 100644
--- a/tests/src/rules/no-named-export.js
+++ b/tests/src/rules/no-named-export.js
@@ -1,8 +1,8 @@
-import { RuleTester } from 'eslint'
-import { test } from '../utils'
+import { RuleTester } from 'eslint';
+import { test } from '../utils';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-named-export')
+    , rule = require('rules/no-named-export');
 
 ruleTester.run('no-named-export', rule, {
   valid: [
@@ -177,4 +177,4 @@ ruleTester.run('no-named-export', rule, {
       }],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-namespace.js b/tests/src/rules/no-namespace.js
index a7cb4dd21f..d7c4c9cf8f 100644
--- a/tests/src/rules/no-namespace.js
+++ b/tests/src/rules/no-namespace.js
@@ -1,11 +1,11 @@
-import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
-import { test } from '../utils'
+import { RuleTester } from 'eslint';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
+import { test } from '../utils';
 
-const ERROR_MESSAGE = 'Unexpected namespace import.'
+const ERROR_MESSAGE = 'Unexpected namespace import.';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 // --fix functionality requires ESLint 5+
 const FIX_TESTS = semver.satisfies(eslintPkg.version, '>5.0.0') ? [
@@ -70,7 +70,7 @@ const FIX_TESTS = semver.satisfies(eslintPkg.version, '>5.0.0') ? [
       message: ERROR_MESSAGE,
     }],
   }),
-] : []
+] : [];
 
 ruleTester.run('no-namespace', require('rules/no-namespace'), {
   valid: [
@@ -110,4 +110,4 @@ ruleTester.run('no-namespace', require('rules/no-namespace'), {
     }),
     ...FIX_TESTS,
   ],
-})
+});
diff --git a/tests/src/rules/no-nodejs-modules.js b/tests/src/rules/no-nodejs-modules.js
index 4be050c63f..32af477dde 100644
--- a/tests/src/rules/no-nodejs-modules.js
+++ b/tests/src/rules/no-nodejs-modules.js
@@ -1,13 +1,13 @@
-import { test } from '../utils'
+import { test } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-nodejs-modules')
+    , rule = require('rules/no-nodejs-modules');
 
 const error = message => ({
   message,
-})
+});
 
 ruleTester.run('no-nodejs-modules', rule, {
   valid: [
@@ -81,4 +81,4 @@ ruleTester.run('no-nodejs-modules', rule, {
       errors: [error('Do not import Node.js builtin module "fs"')],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js
index 05ef9d8bff..d6a47ae373 100644
--- a/tests/src/rules/no-relative-parent-imports.js
+++ b/tests/src/rules/no-relative-parent-imports.js
@@ -1,13 +1,13 @@
-import { RuleTester } from 'eslint'
-import rule from 'rules/no-relative-parent-imports'
-import { test as _test, testFilePath } from '../utils'
+import { RuleTester } from 'eslint';
+import rule from 'rules/no-relative-parent-imports';
+import { test as _test, testFilePath } from '../utils';
 
 const test = def => _test(Object.assign(def, {
   filename: testFilePath('./internal-modules/plugins/plugin2/index.js'),
   parser: require.resolve('babel-eslint'),
-}))
+}));
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 ruleTester.run('no-relative-parent-imports', rule, {
   valid: [
@@ -103,4 +103,4 @@ ruleTester.run('no-relative-parent-imports', rule, {
       }],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index bd5ab29314..826e6408d0 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -1,9 +1,9 @@
-import { RuleTester } from 'eslint'
-import rule from 'rules/no-restricted-paths'
+import { RuleTester } from 'eslint';
+import rule from 'rules/no-restricted-paths';
 
-import { test, testFilePath } from '../utils'
+import { test, testFilePath } from '../utils';
 
-const ruleTester = new RuleTester()
+const ruleTester = new RuleTester();
 
 ruleTester.run('no-restricted-paths', rule, {
   valid: [
@@ -180,4 +180,4 @@ ruleTester.run('no-restricted-paths', rule, {
       } ],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-self-import.js b/tests/src/rules/no-self-import.js
index 281d67107f..6e255a3eb2 100644
--- a/tests/src/rules/no-self-import.js
+++ b/tests/src/rules/no-self-import.js
@@ -1,13 +1,13 @@
-import { test, testFilePath } from '../utils'
+import { test, testFilePath } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-self-import')
+    , rule = require('rules/no-self-import');
 
 const error = {
   message: 'Module imports itself.',
-}
+};
 
 ruleTester.run('no-self-import', rule, {
   valid: [
@@ -117,4 +117,4 @@ ruleTester.run('no-self-import', rule, {
       filename: testFilePath('./no-self-import-folder/index.js'),
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-unassigned-import.js b/tests/src/rules/no-unassigned-import.js
index d4fca8f457..deb43b3262 100644
--- a/tests/src/rules/no-unassigned-import.js
+++ b/tests/src/rules/no-unassigned-import.js
@@ -1,14 +1,14 @@
-import { test } from '../utils'
-import * as path from 'path'
+import { test } from '../utils';
+import * as path from 'path';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-unassigned-import')
+    , rule = require('rules/no-unassigned-import');
 
 const error = {
   message: 'Imported module should be assigned',
-}
+};
 
 ruleTester.run('no-unassigned-import', rule, {
   valid: [
@@ -105,4 +105,4 @@ ruleTester.run('no-unassigned-import', rule, {
       errors: [error],
     }),
   ],
-})
+});
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index cc3aca8844..8bc9ea5922 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -1,13 +1,13 @@
-import * as path from 'path'
+import * as path from 'path';
 
-import { test, SYNTAX_CASES } from '../utils'
+import { test, SYNTAX_CASES } from '../utils';
 
-import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve'
+import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 var ruleTester = new RuleTester()
-  , rule = require('rules/no-unresolved')
+  , rule = require('rules/no-unresolved');
 
 function runResolverTests(resolver) {
   // redefine 'test' to set a resolver
@@ -16,9 +16,9 @@ function runResolverTests(resolver) {
     specs.settings = Object.assign({},
       specs.settings,
       { 'import/resolver': resolver },
-    )
+    );
 
-    return test(specs)
+    return test(specs);
   }
 
   ruleTester.run(`no-unresolved (${resolver})`, rule, {
@@ -188,7 +188,7 @@ function runResolverTests(resolver) {
         }],
       }),
     ],
-  })
+  });
 
   ruleTester.run(`issue #333 (${resolver})`, rule, {
     valid: [
@@ -209,7 +209,7 @@ function runResolverTests(resolver) {
           errors: ["Unable to resolve path to module './foo.json'."],
         }),
     ],
-  })
+  });
 
   if (!CASE_SENSITIVE_FS) {
     ruleTester.run('case sensitivity', rule, {
@@ -231,12 +231,12 @@ function runResolverTests(resolver) {
           errors: [`Casing of ./jsx/MyUncoolComponent.jsx does not match the underlying filesystem.`],
         }),
       ],
-    })
+    });
   }
 
 }
 
-['node', 'webpack'].forEach(runResolverTests)
+['node', 'webpack'].forEach(runResolverTests);
 
 ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
   valid: [
@@ -270,7 +270,7 @@ ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
       errors: [ "Unable to resolve path to module 'jsx-module/foo'." ],
     }),
   ],
-})
+});
 
 ruleTester.run('no-unresolved (webpack-specific)', rule, {
   valid: [
@@ -295,7 +295,7 @@ ruleTester.run('no-unresolved (webpack-specific)', rule, {
       errors: [ "Unable to resolve path to module 'jsx-module/foo'." ],
     }),
   ],
-})
+});
 
 
 ruleTester.run('no-unresolved ignore list', rule, {
@@ -333,7 +333,7 @@ ruleTester.run('no-unresolved ignore list', rule, {
       errors: [ "Unable to resolve path to module './test.png'." ],
     }),
   ],
-})
+});
 
 ruleTester.run('no-unresolved unknown resolver', rule, {
   valid: [],
@@ -361,7 +361,7 @@ ruleTester.run('no-unresolved unknown resolver', rule, {
       ],
     }),
   ],
-})
+});
 
 ruleTester.run('no-unresolved electron', rule, {
   valid: [
@@ -376,9 +376,9 @@ ruleTester.run('no-unresolved electron', rule, {
       errors: [`Unable to resolve path to module 'electron'.`],
     }),
   ],
-})
+});
 
 ruleTester.run('no-unresolved syntax verification', rule, {
   valid: SYNTAX_CASES,
   invalid:[],
-})
+});
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 3e63a6ac9d..99120544b6 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -1,38 +1,38 @@
-import { test, testFilePath, getTSParsers } from '../utils'
-import jsxConfig from '../../../config/react'
-import typescriptConfig from '../../../config/typescript'
+import { test, testFilePath, getTSParsers } from '../utils';
+import jsxConfig from '../../../config/react';
+import typescriptConfig from '../../../config/typescript';
 
-import { RuleTester } from 'eslint'
-import fs from 'fs'
+import { RuleTester } from 'eslint';
+import fs from 'fs';
 
 const ruleTester = new RuleTester()
     , typescriptRuleTester = new RuleTester(typescriptConfig)
     , jsxRuleTester = new RuleTester(jsxConfig)
-    , rule = require('rules/no-unused-modules')
+    , rule = require('rules/no-unused-modules');
 
-const error = message => ({ message })
+const error = message => ({ message });
 
 const missingExportsOptions = [{
   missingExports: true,
-}]
+}];
 
 const unusedExportsOptions = [{
   unusedExports: true,
   src: [testFilePath('./no-unused-modules/**/*.js')],
   ignoreExports: [testFilePath('./no-unused-modules/*ignored*.js')],
-}]
+}];
 
 const unusedExportsTypescriptOptions = [{
   unusedExports: true,
   src: [testFilePath('./no-unused-modules/typescript')],
   ignoreExports: undefined,
-}]
+}];
 
 const unusedExportsJsxOptions = [{
   unusedExports: true,
   src: [testFilePath('./no-unused-modules/jsx')],
   ignoreExports: undefined,
-}]
+}];
 
 // tests for missing exports
 ruleTester.run('no-unused-modules', rule, {
@@ -97,7 +97,7 @@ ruleTester.run('no-unused-modules', rule, {
       errors: [error(`No exports found`)],
     }),
   ],
-})
+});
 
 
 // tests for  exports
@@ -156,7 +156,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-n.js'),
            errors: [error(`exported declaration 'default' not used within other modules`)]}),
   ],
-})
+});
 
 // test for unused exports
 ruleTester.run('no-unused-modules', rule, {
@@ -194,7 +194,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-k.js'),
            errors: [error(`exported declaration 'k' not used within other modules`)]}),
   ],
-})
+});
 
 // // test for export from
 ruleTester.run('no-unused-modules', rule, {
@@ -209,7 +209,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-j.js'),
            errors: [error(`exported declaration 'k' not used within other modules`)]}),
   ],
-})
+});
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [
@@ -218,7 +218,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-k.js')}),
   ],
   invalid: [],
-})
+});
 
 // test for ignored files
 ruleTester.run('no-unused-modules', rule, {
@@ -243,7 +243,7 @@ ruleTester.run('no-unused-modules', rule, {
       filename: testFilePath('./no-unused-modules/file-ignored-l.js')}),
     ],
   invalid: [],
-})
+});
 
 // add named import for file with default export
 ruleTester.run('no-unused-modules', rule, {
@@ -258,7 +258,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-f.js'),
            errors: [error(`exported declaration 'default' not used within other modules`)]}),
     ],
-})
+});
 
 // add default import for file with default export
 ruleTester.run('no-unused-modules', rule, {
@@ -271,7 +271,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-f.js')}),
     ],
   invalid: [],
-})
+});
 
 // add default import for file with named export
 ruleTester.run('no-unused-modules', rule, {
@@ -285,7 +285,7 @@ ruleTester.run('no-unused-modules', rule, {
             code: 'export const g = 2',
             filename: testFilePath('./no-unused-modules/file-g.js'),
             errors: [error(`exported declaration 'g' not used within other modules`)]})],
-})
+});
 
 // add named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
@@ -298,7 +298,7 @@ ruleTester.run('no-unused-modules', rule, {
             filename: testFilePath('./no-unused-modules/file-g.js')}),
     ],
   invalid: [],
-})
+});
 
 // add different named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
@@ -313,7 +313,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-b.js'),
            errors: [error(`exported declaration 'b' not used within other modules`)]}),
   ],
-})
+});
 
 // add renamed named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
@@ -326,7 +326,7 @@ ruleTester.run('no-unused-modules', rule, {
             filename: testFilePath('./no-unused-modules/file-g.js')}),
     ],
   invalid: [],
-})
+});
 
 // add different renamed named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
@@ -341,7 +341,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-g.js'),
            errors: [error(`exported declaration 'g' not used within other modules`)]}),
   ],
-})
+});
 
 // remove default import for file with default export
 ruleTester.run('no-unused-modules', rule, {
@@ -356,7 +356,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-a.js'),
            errors: [error(`exported declaration 'default' not used within other modules`)]}),
   ],
-})
+});
 
 // add namespace import for file with unused exports
 ruleTester.run('no-unused-modules', rule, {
@@ -371,7 +371,7 @@ ruleTester.run('no-unused-modules', rule, {
              error(`exported declaration 'default' not used within other modules`),
           ]}),
   ],
-})
+});
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
@@ -382,7 +382,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-m.js')}),
   ],
   invalid: [],
-})
+});
 
 // remove all exports
 ruleTester.run('no-unused-modules', rule, {
@@ -401,7 +401,7 @@ ruleTester.run('no-unused-modules', rule, {
         error(`exported declaration 'default' not used within other modules`),
      ]}),
   ],
-})
+});
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [
@@ -410,7 +410,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-0.js')}),
   ],
   invalid: [],
-})
+});
 ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
@@ -419,7 +419,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-m.js'),
            errors: [error(`exported declaration 'default' not used within other modules`)]}),
   ],
-})
+});
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [],
@@ -436,7 +436,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-m.js'),
            errors: [error(`exported declaration 'default' not used within other modules`)]}),
   ],
-})
+});
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [
@@ -457,7 +457,7 @@ ruleTester.run('no-unused-modules', rule, {
            filename: testFilePath('./no-unused-modules/file-m.js'),
            errors: [error(`exported declaration 'm' not used within other modules`)]}),
   ],
-})
+});
 
 // Test that import and export in the same file both counts as usage
 ruleTester.run('no-unused-modules', rule, {
@@ -468,7 +468,7 @@ ruleTester.run('no-unused-modules', rule, {
         }),
   ],
   invalid: [],
-})
+});
 
 describe('renameDefault', () => {
   ruleTester.run('no-unused-modules', rule, {
@@ -481,7 +481,7 @@ describe('renameDefault', () => {
         filename: testFilePath('./no-unused-modules/renameDefault/Component.js')}),
     ],
     invalid: [],
-  })
+  });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
@@ -492,13 +492,13 @@ describe('renameDefault', () => {
         filename: testFilePath('./no-unused-modules/renameDefault-2/ComponentA.js')}),
     ],
     invalid: [],
-  })
-})
+  });
+});
 
 describe('test behaviour for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', {encoding: 'utf8'})
-  })
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', {encoding: 'utf8'});
+  });
 
   // add import in newly created file
   ruleTester.run('no-unused-modules', rule, {
@@ -511,7 +511,7 @@ describe('test behaviour for new file', () => {
              filename: testFilePath('./no-unused-modules/file-m.js')}),
     ],
     invalid: [],
-  })
+  });
 
   // add export for newly created file
   ruleTester.run('no-unused-modules', rule, {
@@ -522,7 +522,7 @@ describe('test behaviour for new file', () => {
              filename: testFilePath('./no-unused-modules/file-added-0.js'),
              errors: [error(`exported declaration 'default' not used within other modules`)]}),
       ],
-  })
+  });
 
   ruleTester.run('no-unused-modules', rule, {
     valid: [
@@ -534,7 +534,7 @@ describe('test behaviour for new file', () => {
              filename: testFilePath('./no-unused-modules/file-added-0.js')}),
     ],
     invalid: [],
-  })
+  });
 
   // export * only considers named imports. default imports still need to be reported
   ruleTester.run('no-unused-modules', rule, {
@@ -554,7 +554,7 @@ describe('test behaviour for new file', () => {
              filename: testFilePath('./no-unused-modules/file-added-0.js'),
              errors: [error(`exported declaration 'default' not used within other modules`)]}),
     ],
-  })
+  });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
@@ -562,7 +562,7 @@ describe('test behaviour for new file', () => {
              filename: testFilePath('./no-unused-modules/file-added-0.js')}),
     ],
     invalid: [],
-  })
+  });
 
   // remove export *. all exports need to be reported
   ruleTester.run('no-unused-modules', rule, {
@@ -580,13 +580,13 @@ describe('test behaviour for new file', () => {
                error(`exported declaration 'default' not used within other modules`),
             ]}),
     ],
-  })
+  });
 
 
   describe('test behaviour for new file', () => {
     before(() => {
-      fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', {encoding: 'utf8'})
-    })
+      fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', {encoding: 'utf8'});
+    });
     ruleTester.run('no-unused-modules', rule, {
       valid: [
         test({ options: unusedExportsOptions,
@@ -599,25 +599,25 @@ describe('test behaviour for new file', () => {
                filename: testFilePath('./no-unused-modules/file-added-1.js'),
                errors: [error(`exported declaration 'default' not used within other modules`)]}),
       ],
-    })
+    });
     after(() => {
       if (fs.existsSync(testFilePath('./no-unused-modules/file-added-1.js'))) {
-        fs.unlinkSync(testFilePath('./no-unused-modules/file-added-1.js'))
+        fs.unlinkSync(testFilePath('./no-unused-modules/file-added-1.js'));
       }
-    })
-  })
+    });
+  });
 
   after(() => {
     if (fs.existsSync(testFilePath('./no-unused-modules/file-added-0.js'))) {
-      fs.unlinkSync(testFilePath('./no-unused-modules/file-added-0.js'))
+      fs.unlinkSync(testFilePath('./no-unused-modules/file-added-0.js'));
     }
-  })
-})
+  });
+});
 
 describe('test behaviour for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', {encoding: 'utf8'})
-  })
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', {encoding: 'utf8'});
+  });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
@@ -628,18 +628,18 @@ describe('test behaviour for new file', () => {
              filename: testFilePath('./no-unused-modules/file-added-2.js')}),
     ],
     invalid: [],
-  })
+  });
   after(() => {
     if (fs.existsSync(testFilePath('./no-unused-modules/file-added-2.js'))) {
-      fs.unlinkSync(testFilePath('./no-unused-modules/file-added-2.js'))
+      fs.unlinkSync(testFilePath('./no-unused-modules/file-added-2.js'));
     }
-  })
-})
+  });
+});
 
 describe('test behaviour for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', {encoding: 'utf8'})
-  })
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', {encoding: 'utf8'});
+  });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
@@ -650,18 +650,18 @@ describe('test behaviour for new file', () => {
              filename: testFilePath('./no-unused-modules/file-added-3.js')}),
     ],
     invalid: [],
-  })
+  });
   after(() => {
     if (fs.existsSync(testFilePath('./no-unused-modules/file-added-3.js'))) {
-      fs.unlinkSync(testFilePath('./no-unused-modules/file-added-3.js'))
+      fs.unlinkSync(testFilePath('./no-unused-modules/file-added-3.js'));
     }
-  })
-})
+  });
+});
 
 describe('test behaviour for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', {encoding: 'utf8'})
-  })
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', {encoding: 'utf8'});
+  });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
@@ -672,13 +672,13 @@ describe('test behaviour for new file', () => {
              filename: testFilePath('./no-unused-modules/file-added-4.js.js')}),
     ],
     invalid: [],
-  })
+  });
   after(() => {
     if (fs.existsSync(testFilePath('./no-unused-modules/file-added-4.js.js'))) {
-      fs.unlinkSync(testFilePath('./no-unused-modules/file-added-4.js.js'))
+      fs.unlinkSync(testFilePath('./no-unused-modules/file-added-4.js.js'));
     }
-  })
-})
+  });
+});
 
 describe('do not report missing export for ignored file', () => {
   ruleTester.run('no-unused-modules', rule, {
@@ -692,8 +692,8 @@ describe('do not report missing export for ignored file', () => {
              filename: testFilePath('./no-unused-modules/file-ignored-a.js')}),
     ],
     invalid: [],
-  })
-})
+  });
+});
 
 // lint file not available in `src`
 ruleTester.run('no-unused-modules', rule, {
@@ -703,7 +703,7 @@ ruleTester.run('no-unused-modules', rule, {
             filename: testFilePath('../jsx/named.jsx')}),
   ],
   invalid: [],
-})
+});
 
 describe('do not report unused export for files mentioned in package.json', () => {
   ruleTester.run('no-unused-modules', rule, {
@@ -730,8 +730,8 @@ describe('do not report unused export for files mentioned in package.json', () =
              filename: testFilePath('./no-unused-modules/privatePkg/index.js'),
              errors: [error(`exported declaration 'privatePkg' not used within other modules`)]}),
     ],
-  })
-})
+  });
+});
 
 describe('Avoid errors if re-export all from umd compiled library', () => {
   ruleTester.run('no-unused-modules', rule, {
@@ -741,8 +741,8 @@ describe('Avoid errors if re-export all from umd compiled library', () => {
         filename: testFilePath('./no-unused-modules/main/index.js')}),
     ],
     invalid: [],
-  })
-})
+  });
+});
 
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
@@ -866,9 +866,9 @@ context('TypeScript', function () {
           ],
         }),
       ],
-    })
-  })
-})
+    });
+  });
+});
 
 describe('correctly work with JSX only files', () => {
   jsxRuleTester.run('no-unused-modules', rule, {
@@ -891,8 +891,8 @@ describe('correctly work with JSX only files', () => {
         ],
       }),
     ],
-  })
-})
+  });
+});
 
 describe('ignore flow types', () => {
   ruleTester.run('no-unused-modules', rule, {
@@ -938,6 +938,6 @@ describe('ignore flow types', () => {
       }),
     ],
     invalid: [],
-  })
-})
+  });
+});
 
diff --git a/tests/src/rules/no-useless-path-segments.js b/tests/src/rules/no-useless-path-segments.js
index 2a864d0b6c..33b1ff5b5b 100644
--- a/tests/src/rules/no-useless-path-segments.js
+++ b/tests/src/rules/no-useless-path-segments.js
@@ -1,8 +1,8 @@
-import { test } from '../utils'
-import { RuleTester } from 'eslint'
+import { test } from '../utils';
+import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-const rule = require('rules/no-useless-path-segments')
+const ruleTester = new RuleTester();
+const rule = require('rules/no-useless-path-segments');
 
 function runResolverTests(resolver) {
   ruleTester.run(`no-useless-path-segments (${resolver})`, rule, {
@@ -247,7 +247,7 @@ function runResolverTests(resolver) {
         parser: require.resolve('babel-eslint'),
       }),
     ],
-  })
+  });
 }
 
-['node', 'webpack'].forEach(runResolverTests)
+['node', 'webpack'].forEach(runResolverTests);
diff --git a/tests/src/rules/no-webpack-loader-syntax.js b/tests/src/rules/no-webpack-loader-syntax.js
index a56e142e71..86026e8d1c 100644
--- a/tests/src/rules/no-webpack-loader-syntax.js
+++ b/tests/src/rules/no-webpack-loader-syntax.js
@@ -1,11 +1,11 @@
-import { test, getTSParsers } from '../utils'
+import { test, getTSParsers } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/no-webpack-loader-syntax')
+    , rule = require('rules/no-webpack-loader-syntax');
 
-const message = 'Do not use import syntax to configure webpack loaders.'
+const message = 'Do not use import syntax to configure webpack loaders.';
 
 ruleTester.run('no-webpack-loader-syntax', rule, {
   valid: [
@@ -71,7 +71,7 @@ ruleTester.run('no-webpack-loader-syntax', rule, {
       ],
     }),
   ],
-})
+});
 
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
@@ -81,7 +81,7 @@ context('TypeScript', function () {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
-    }
+    };
     ruleTester.run('no-webpack-loader-syntax', rule, {
       valid: [
         test(Object.assign({
@@ -92,6 +92,6 @@ context('TypeScript', function () {
         }, parserConfig)),
       ],
       invalid: [],
-    })
-  })
-})
+    });
+  });
+});
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 497911ffbe..3023be2db2 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,15 +1,15 @@
-import { test, getTSParsers, getNonDefaultParsers } from '../utils'
+import { test, getTSParsers, getNonDefaultParsers } from '../utils';
 
-import { RuleTester } from 'eslint'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
-import flatMap from 'array.prototype.flatmap'
+import { RuleTester } from 'eslint';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
+import flatMap from 'array.prototype.flatmap';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/order')
+    , rule = require('rules/order');
 
 function withoutAutofixOutput(test) {
-  return Object.assign({}, test, { output: test.code })
+  return Object.assign({}, test, { output: test.code });
 }
 
 ruleTester.run('order', rule, {
@@ -2181,7 +2181,7 @@ ruleTester.run('order', rule, {
       }),
     ],
   ].filter((t) => !!t),
-})
+});
 
 
 context('TypeScript', function () {
@@ -2194,7 +2194,7 @@ context('TypeScript', function () {
           'import/parsers': { [parser]: ['.ts'] },
           'import/resolver': { 'eslint-import-resolver-typescript': true },
         },
-      }
+      };
 
       ruleTester.run('order', rule, {
         valid: [
@@ -2319,6 +2319,6 @@ context('TypeScript', function () {
             parserConfig,
           ),
         ],
-      })
-    })
-})
+      });
+    });
+});
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index e948b9f9e0..0989125661 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -1,9 +1,9 @@
-import { test, getNonDefaultParsers } from '../utils'
+import { test, getNonDefaultParsers } from '../utils';
 
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('../../../src/rules/prefer-default-export')
+    , rule = require('../../../src/rules/prefer-default-export');
 
 ruleTester.run('prefer-default-export', rule, {
   valid: [
@@ -146,7 +146,7 @@ ruleTester.run('prefer-default-export', rule, {
       }],
     }),
   ],
-})
+});
 
 context('TypeScript', function() {
   getNonDefaultParsers().forEach((parser) => {
@@ -156,7 +156,7 @@ context('TypeScript', function() {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
-    }
+    };
 
     ruleTester.run('prefer-default-export', rule, {
       valid: [
@@ -209,6 +209,6 @@ context('TypeScript', function() {
         ),
       ],
       invalid: [],
-    })
-  })
-})
+    });
+  });
+});
diff --git a/tests/src/rules/unambiguous.js b/tests/src/rules/unambiguous.js
index 705ce79d10..8e7a9a3ae1 100644
--- a/tests/src/rules/unambiguous.js
+++ b/tests/src/rules/unambiguous.js
@@ -1,7 +1,7 @@
-import { RuleTester } from 'eslint'
+import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester()
-    , rule = require('rules/unambiguous')
+    , rule = require('rules/unambiguous');
 
 ruleTester.run('unambiguous', rule, {
   valid: [
@@ -54,4 +54,4 @@ ruleTester.run('unambiguous', rule, {
       errors: ['This module could be parsed as a valid script.'],
     },
   ],
-})
+});
diff --git a/tests/src/utils.js b/tests/src/utils.js
index 0f45e7bf28..f1a9e54c29 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -1,34 +1,34 @@
-import path from 'path'
-import eslintPkg from 'eslint/package.json'
-import semver from 'semver'
+import path from 'path';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
 // warms up the module cache. this import takes a while (>500ms)
-import 'babel-eslint'
+import 'babel-eslint';
 
 export function testFilePath(relativePath) {
-  return path.join(process.cwd(), './tests/files', relativePath)
+  return path.join(process.cwd(), './tests/files', relativePath);
 }
 
 export function getTSParsers() {
-  const parsers = []
+  const parsers = [];
   if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
-    parsers.push(require.resolve('typescript-eslint-parser'))
+    parsers.push(require.resolve('typescript-eslint-parser'));
   }
 
   if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-    parsers.push(require.resolve('@typescript-eslint/parser'))
+    parsers.push(require.resolve('@typescript-eslint/parser'));
   }
-  return parsers
+  return parsers;
 }
 
 export function getNonDefaultParsers() {
-  return getTSParsers().concat(require.resolve('babel-eslint'))
+  return getTSParsers().concat(require.resolve('babel-eslint'));
 }
 
-export const FILENAME = testFilePath('foo.js')
+export const FILENAME = testFilePath('foo.js');
 
 export function testVersion(specifier, t) {
-  return semver.satisfies(eslintPkg.version, specifier) && test(t())
+  return semver.satisfies(eslintPkg.version, specifier) && test(t());
 }
 
 export function test(t) {
@@ -39,16 +39,16 @@ export function test(t) {
       sourceType: 'module',
       ecmaVersion: 9,
     }, t.parserOptions),
-  })
+  });
 }
 
 export function testContext(settings) {
-  return { getFilename: function () { return FILENAME }
-         , settings: settings || {} }
+  return { getFilename: function () { return FILENAME; }
+         , settings: settings || {} };
 }
 
 export function getFilename(file) {
-  return path.join(__dirname, '..', 'files', file || 'foo.js')
+  return path.join(__dirname, '..', 'files', file || 'foo.js');
 }
 
 /**
@@ -116,4 +116,4 @@ export const SYNTAX_CASES = [
     code: 'import { foo } from "./ignore.invalid.extension"',
   }),
 
-]
+];
diff --git a/utils/ModuleCache.js b/utils/ModuleCache.js
index b910a5810a..a06616de9b 100644
--- a/utils/ModuleCache.js
+++ b/utils/ModuleCache.js
@@ -1,11 +1,11 @@
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
-const log = require('debug')('eslint-module-utils:ModuleCache')
+const log = require('debug')('eslint-module-utils:ModuleCache');
 
 class ModuleCache {
   constructor(map) {
-    this.map = map || new Map()
+    this.map = map || new Map();
   }
 
   /**
@@ -14,19 +14,19 @@ class ModuleCache {
    * @param {[type]} result   [description]
    */
   set(cacheKey, result) {
-    this.map.set(cacheKey, { result, lastSeen: process.hrtime() })
-    log('setting entry for', cacheKey)
-    return result
+    this.map.set(cacheKey, { result, lastSeen: process.hrtime() });
+    log('setting entry for', cacheKey);
+    return result;
   }
 
   get(cacheKey, settings) {
     if (this.map.has(cacheKey)) {
-      const f = this.map.get(cacheKey)
+      const f = this.map.get(cacheKey);
       // check freshness
-      if (process.hrtime(f.lastSeen)[0] < settings.lifetime) return f.result
-    } else log('cache miss for', cacheKey)
+      if (process.hrtime(f.lastSeen)[0] < settings.lifetime) return f.result;
+    } else log('cache miss for', cacheKey);
     // cache miss
-    return undefined
+    return undefined;
   }
 
 }
@@ -34,14 +34,14 @@ class ModuleCache {
 ModuleCache.getSettings = function (settings) {
   const cacheSettings = Object.assign({
     lifetime: 30,  // seconds
-  }, settings['import/cache'])
+  }, settings['import/cache']);
 
   // parse infinity
   if (cacheSettings.lifetime === '∞' || cacheSettings.lifetime === 'Infinity') {
-    cacheSettings.lifetime = Infinity
+    cacheSettings.lifetime = Infinity;
   }
 
-  return cacheSettings
-}
+  return cacheSettings;
+};
 
-exports.default = ModuleCache
+exports.default = ModuleCache;
diff --git a/utils/declaredScope.js b/utils/declaredScope.js
index 904279ad79..00005946b7 100644
--- a/utils/declaredScope.js
+++ b/utils/declaredScope.js
@@ -1,14 +1,14 @@
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
 exports.default = function declaredScope(context, name) {
   let references = context.getScope().references
-    , i
+    , i;
   for (i = 0; i < references.length; i++) {
     if (references[i].identifier.name === name) {
-      break
+      break;
     }
   }
-  if (!references[i]) return undefined
-  return references[i].resolved.scope.type
-}
+  if (!references[i]) return undefined;
+  return references[i].resolved.scope.type;
+};
diff --git a/utils/hash.js b/utils/hash.js
index d69dd4df5f..ae7e885b68 100644
--- a/utils/hash.js
+++ b/utils/hash.js
@@ -2,58 +2,58 @@
  * utilities for hashing config objects.
  * basically iteratively updates hash with a JSON-like format
  */
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
-const createHash = require('crypto').createHash
+const createHash = require('crypto').createHash;
 
-const stringify = JSON.stringify
+const stringify = JSON.stringify;
 
 function hashify(value, hash) {
-  if (!hash) hash = createHash('sha256')
+  if (!hash) hash = createHash('sha256');
 
   if (value instanceof Array) {
-    hashArray(value, hash)
+    hashArray(value, hash);
   } else if (value instanceof Object) {
-    hashObject(value, hash)
+    hashObject(value, hash);
   } else {
-    hash.update(stringify(value) || 'undefined')
+    hash.update(stringify(value) || 'undefined');
   }
 
-  return hash
+  return hash;
 }
-exports.default = hashify
+exports.default = hashify;
 
 function hashArray(array, hash) {
-  if (!hash) hash = createHash('sha256')
+  if (!hash) hash = createHash('sha256');
 
-  hash.update('[')
+  hash.update('[');
   for (let i = 0; i < array.length; i++) {
-    hashify(array[i], hash)
-    hash.update(',')
+    hashify(array[i], hash);
+    hash.update(',');
   }
-  hash.update(']')
+  hash.update(']');
 
-  return hash
+  return hash;
 }
-hashify.array = hashArray
-exports.hashArray = hashArray
+hashify.array = hashArray;
+exports.hashArray = hashArray;
 
 function hashObject(object, hash) {
-  if (!hash) hash = createHash('sha256')
+  if (!hash) hash = createHash('sha256');
 
-  hash.update('{')
+  hash.update('{');
   Object.keys(object).sort().forEach(key => {
-    hash.update(stringify(key))
-    hash.update(':')
-    hashify(object[key], hash)
-    hash.update(',')
-  })
-  hash.update('}')
-
-  return hash
+    hash.update(stringify(key));
+    hash.update(':');
+    hashify(object[key], hash);
+    hash.update(',');
+  });
+  hash.update('}');
+
+  return hash;
 }
-hashify.object = hashObject
-exports.hashObject = hashObject
+hashify.object = hashObject;
+exports.hashObject = hashObject;
 
 
diff --git a/utils/ignore.js b/utils/ignore.js
index 47af8122dd..46e0cd4162 100644
--- a/utils/ignore.js
+++ b/utils/ignore.js
@@ -1,60 +1,60 @@
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
-const extname = require('path').extname
+const extname = require('path').extname;
 
-const log = require('debug')('eslint-plugin-import:utils:ignore')
+const log = require('debug')('eslint-plugin-import:utils:ignore');
 
 // one-shot memoized
-let cachedSet, lastSettings
+let cachedSet, lastSettings;
 function validExtensions(context) {
   if (cachedSet && context.settings === lastSettings) {
-    return cachedSet
+    return cachedSet;
   }
 
-  lastSettings = context.settings
-  cachedSet = makeValidExtensionSet(context.settings)
-  return cachedSet
+  lastSettings = context.settings;
+  cachedSet = makeValidExtensionSet(context.settings);
+  return cachedSet;
 }
 
 function makeValidExtensionSet(settings) {
   // start with explicit JS-parsed extensions
-  const exts = new Set(settings['import/extensions'] || [ '.js' ])
+  const exts = new Set(settings['import/extensions'] || [ '.js' ]);
 
   // all alternate parser extensions are also valid
   if ('import/parsers' in settings) {
     for (let parser in settings['import/parsers']) {
-      const parserSettings = settings['import/parsers'][parser]
+      const parserSettings = settings['import/parsers'][parser];
       if (!Array.isArray(parserSettings)) {
-        throw new TypeError('"settings" for ' + parser + ' must be an array')
+        throw new TypeError('"settings" for ' + parser + ' must be an array');
       }
-      parserSettings.forEach(ext => exts.add(ext))
+      parserSettings.forEach(ext => exts.add(ext));
     }
   }
 
-  return exts
+  return exts;
 }
-exports.getFileExtensions = makeValidExtensionSet
+exports.getFileExtensions = makeValidExtensionSet;
 
 exports.default = function ignore(path, context) {
   // check extension whitelist first (cheap)
-  if (!hasValidExtension(path, context)) return true
+  if (!hasValidExtension(path, context)) return true;
 
-  if (!('import/ignore' in context.settings)) return false
-  const ignoreStrings = context.settings['import/ignore']
+  if (!('import/ignore' in context.settings)) return false;
+  const ignoreStrings = context.settings['import/ignore'];
 
   for (let i = 0; i < ignoreStrings.length; i++) {
-    const regex = new RegExp(ignoreStrings[i])
+    const regex = new RegExp(ignoreStrings[i]);
     if (regex.test(path)) {
-      log(`ignoring ${path}, matched pattern /${ignoreStrings[i]}/`)
-      return true
+      log(`ignoring ${path}, matched pattern /${ignoreStrings[i]}/`);
+      return true;
     }
   }
 
-  return false
-}
+  return false;
+};
 
 function hasValidExtension(path, context) {
-  return validExtensions(context).has(extname(path))
+  return validExtensions(context).has(extname(path));
 }
-exports.hasValidExtension = hasValidExtension
+exports.hasValidExtension = hasValidExtension;
diff --git a/utils/module-require.js b/utils/module-require.js
index 689450658c..70e5510621 100644
--- a/utils/module-require.js
+++ b/utils/module-require.js
@@ -1,30 +1,30 @@
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
-const Module = require('module')
-const path = require('path')
+const Module = require('module');
+const path = require('path');
 
 // borrowed from babel-eslint
 function createModule(filename) {
-  const mod = new Module(filename)
-  mod.filename = filename
-  mod.paths = Module._nodeModulePaths(path.dirname(filename))
-  return mod
+  const mod = new Module(filename);
+  mod.filename = filename;
+  mod.paths = Module._nodeModulePaths(path.dirname(filename));
+  return mod;
 }
 
 exports.default = function moduleRequire(p) {
   try {
     // attempt to get espree relative to eslint
-    const eslintPath = require.resolve('eslint')
-    const eslintModule = createModule(eslintPath)
-    return require(Module._resolveFilename(p, eslintModule))
+    const eslintPath = require.resolve('eslint');
+    const eslintModule = createModule(eslintPath);
+    return require(Module._resolveFilename(p, eslintModule));
   } catch(err) { /* ignore */ }
 
   try {
     // try relative to entry point
-    return require.main.require(p)
+    return require.main.require(p);
   } catch(err) { /* ignore */ }
 
   // finally, try from here
-  return require(p)
-}
+  return require(p);
+};
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index bc8c91b0af..6eaccb331c 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -1,5 +1,5 @@
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
 /**
  * Returns an object of node visitors that will call
@@ -12,95 +12,95 @@ exports.__esModule = true
  */
 exports.default = function visitModules(visitor, options) {
   // if esmodule is not explicitly disabled, it is assumed to be enabled
-  options = Object.assign({ esmodule: true }, options)
+  options = Object.assign({ esmodule: true }, options);
 
-  let ignoreRegExps = []
+  let ignoreRegExps = [];
   if (options.ignore != null) {
-    ignoreRegExps = options.ignore.map(p => new RegExp(p))
+    ignoreRegExps = options.ignore.map(p => new RegExp(p));
   }
 
   function checkSourceValue(source, importer) {
-    if (source == null) return //?
+    if (source == null) return; //?
 
     // handle ignore
-    if (ignoreRegExps.some(re => re.test(source.value))) return
+    if (ignoreRegExps.some(re => re.test(source.value))) return;
 
     // fire visitor
-    visitor(source, importer)
+    visitor(source, importer);
   }
 
   // for import-y declarations
   function checkSource(node) {
-    checkSourceValue(node.source, node)
+    checkSourceValue(node.source, node);
   }
 
   // for esmodule dynamic `import()` calls
   function checkImportCall(node) {
-    if (node.callee.type !== 'Import') return
-    if (node.arguments.length !== 1) return
+    if (node.callee.type !== 'Import') return;
+    if (node.arguments.length !== 1) return;
 
-    const modulePath = node.arguments[0]
-    if (modulePath.type !== 'Literal') return
-    if (typeof modulePath.value !== 'string') return
+    const modulePath = node.arguments[0];
+    if (modulePath.type !== 'Literal') return;
+    if (typeof modulePath.value !== 'string') return;
 
-    checkSourceValue(modulePath, node)
+    checkSourceValue(modulePath, node);
   }
 
   // for CommonJS `require` calls
   // adapted from @mctep: http://git.io/v4rAu
   function checkCommon(call) {
-    if (call.callee.type !== 'Identifier') return
-    if (call.callee.name !== 'require') return
-    if (call.arguments.length !== 1) return
+    if (call.callee.type !== 'Identifier') return;
+    if (call.callee.name !== 'require') return;
+    if (call.arguments.length !== 1) return;
 
-    const modulePath = call.arguments[0]
-    if (modulePath.type !== 'Literal') return
-    if (typeof modulePath.value !== 'string') return
+    const modulePath = call.arguments[0];
+    if (modulePath.type !== 'Literal') return;
+    if (typeof modulePath.value !== 'string') return;
 
-    checkSourceValue(modulePath, call)
+    checkSourceValue(modulePath, call);
   }
 
   function checkAMD(call) {
-    if (call.callee.type !== 'Identifier') return
+    if (call.callee.type !== 'Identifier') return;
     if (call.callee.name !== 'require' &&
-        call.callee.name !== 'define') return
-    if (call.arguments.length !== 2) return
+        call.callee.name !== 'define') return;
+    if (call.arguments.length !== 2) return;
 
-    const modules = call.arguments[0]
-    if (modules.type !== 'ArrayExpression') return
+    const modules = call.arguments[0];
+    if (modules.type !== 'ArrayExpression') return;
 
     for (let element of modules.elements) {
-      if (element.type !== 'Literal') continue
-      if (typeof element.value !== 'string') continue
+      if (element.type !== 'Literal') continue;
+      if (typeof element.value !== 'string') continue;
 
       if (element.value === 'require' ||
-          element.value === 'exports') continue // magic modules: http://git.io/vByan
+          element.value === 'exports') continue; // magic modules: http://git.io/vByan
 
-      checkSourceValue(element, element)
+      checkSourceValue(element, element);
     }
   }
 
-  const visitors = {}
+  const visitors = {};
   if (options.esmodule) {
     Object.assign(visitors, {
       'ImportDeclaration': checkSource,
       'ExportNamedDeclaration': checkSource,
       'ExportAllDeclaration': checkSource,
       'CallExpression': checkImportCall,
-    })
+    });
   }
 
   if (options.commonjs || options.amd) {
-    const currentCallExpression = visitors['CallExpression']
+    const currentCallExpression = visitors['CallExpression'];
     visitors['CallExpression'] = function (call) {
-      if (currentCallExpression) currentCallExpression(call)
-      if (options.commonjs) checkCommon(call)
-      if (options.amd) checkAMD(call)
-    }
+      if (currentCallExpression) currentCallExpression(call);
+      if (options.commonjs) checkCommon(call);
+      if (options.amd) checkAMD(call);
+    };
   }
 
-  return visitors
-}
+  return visitors;
+};
 
 /**
  * make an options schema for the module visitor, optionally
@@ -121,21 +121,21 @@ function makeOptionsSchema(additionalProperties) {
       },
     },
     'additionalProperties': false,
-  }
+  };
 
   if (additionalProperties){
     for (let key in additionalProperties) {
-      base.properties[key] = additionalProperties[key]
+      base.properties[key] = additionalProperties[key];
     }
   }
 
-  return base
+  return base;
 }
-exports.makeOptionsSchema = makeOptionsSchema
+exports.makeOptionsSchema = makeOptionsSchema;
 
 /**
  * json schema object for options parameter. can be used to build
  * rule options schema object.
  * @type {Object}
  */
-exports.optionsSchema = makeOptionsSchema()
+exports.optionsSchema = makeOptionsSchema();
diff --git a/utils/parse.js b/utils/parse.js
index 8f3104bf90..735e83a806 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -1,82 +1,82 @@
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
-const moduleRequire = require('./module-require').default
-const extname = require('path').extname
+const moduleRequire = require('./module-require').default;
+const extname = require('path').extname;
 
-const log = require('debug')('eslint-plugin-import:parse')
+const log = require('debug')('eslint-plugin-import:parse');
 
 exports.default = function parse(path, content, context) {
 
-  if (context == null) throw new Error('need context to parse properly')
+  if (context == null) throw new Error('need context to parse properly');
 
-  let parserOptions = context.parserOptions
-  const parserPath = getParserPath(path, context)
+  let parserOptions = context.parserOptions;
+  const parserPath = getParserPath(path, context);
 
-  if (!parserPath) throw new Error('parserPath is required!')
+  if (!parserPath) throw new Error('parserPath is required!');
 
   // hack: espree blows up with frozen options
-  parserOptions = Object.assign({}, parserOptions)
-  parserOptions.ecmaFeatures = Object.assign({}, parserOptions.ecmaFeatures)
+  parserOptions = Object.assign({}, parserOptions);
+  parserOptions.ecmaFeatures = Object.assign({}, parserOptions.ecmaFeatures);
 
   // always include comments and tokens (for doc parsing)
-  parserOptions.comment = true
-  parserOptions.attachComment = true  // keeping this for backward-compat with  older parsers
-  parserOptions.tokens = true
+  parserOptions.comment = true;
+  parserOptions.attachComment = true;  // keeping this for backward-compat with  older parsers
+  parserOptions.tokens = true;
 
   // attach node locations
-  parserOptions.loc = true
-  parserOptions.range = true
+  parserOptions.loc = true;
+  parserOptions.range = true;
 
   // provide the `filePath` like eslint itself does, in `parserOptions`
   // https://github.com/eslint/eslint/blob/3ec436ee/lib/linter.js#L637
-  parserOptions.filePath = path
+  parserOptions.filePath = path;
 
   // @typescript-eslint/parser will parse the entire project with typechecking if you provide
   // "project" or "projects" in parserOptions. Removing these options means the parser will
   // only parse one file in isolate mode, which is much, much faster.
   // https://github.com/benmosher/eslint-plugin-import/issues/1408#issuecomment-509298962
-  delete parserOptions.project
-  delete parserOptions.projects
+  delete parserOptions.project;
+  delete parserOptions.projects;
 
   // require the parser relative to the main module (i.e., ESLint)
-  const parser = moduleRequire(parserPath)
+  const parser = moduleRequire(parserPath);
 
   if (typeof parser.parseForESLint === 'function') {
-    let ast
+    let ast;
     try {
-      ast = parser.parseForESLint(content, parserOptions).ast
+      ast = parser.parseForESLint(content, parserOptions).ast;
     } catch (e) {
-      console.warn()
-      console.warn('Error while parsing ' + parserOptions.filePath)
-      console.warn('Line ' + e.lineNumber + ', column ' + e.column + ': ' + e.message)
+      console.warn();
+      console.warn('Error while parsing ' + parserOptions.filePath);
+      console.warn('Line ' + e.lineNumber + ', column ' + e.column + ': ' + e.message);
     }
     if (!ast || typeof ast !== 'object') {
       console.warn(
         '`parseForESLint` from parser `' +
           parserPath +
           '` is invalid and will just be ignored'
-      )
+      );
     } else {
-      return ast
+      return ast;
     }
   }
 
-  return parser.parse(content, parserOptions)
-}
+  return parser.parse(content, parserOptions);
+};
 
 function getParserPath(path, context) {
-  const parsers = context.settings['import/parsers']
+  const parsers = context.settings['import/parsers'];
   if (parsers != null) {
-    const extension = extname(path)
+    const extension = extname(path);
     for (let parserPath in parsers) {
       if (parsers[parserPath].indexOf(extension) > -1) {
         // use this alternate parser
-        log('using alt parser:', parserPath)
-        return parserPath
+        log('using alt parser:', parserPath);
+        return parserPath;
       }
     }
   }
   // default to use ESLint parser
-  return context.parserPath
+  return context.parserPath;
 }
diff --git a/utils/resolve.js b/utils/resolve.js
index fc8f85de9a..24fc265fc4 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -1,211 +1,211 @@
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
-const pkgDir = require('pkg-dir')
+const pkgDir = require('pkg-dir');
 
-const fs = require('fs')
-const Module = require('module')
-const path = require('path')
+const fs = require('fs');
+const Module = require('module');
+const path = require('path');
 
 const hashObject = require('./hash').hashObject
-    , ModuleCache = require('./ModuleCache').default
+    , ModuleCache = require('./ModuleCache').default;
 
-const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname.toUpperCase(), 'reSOLVE.js'))
-exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS
+const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname.toUpperCase(), 'reSOLVE.js'));
+exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS;
 
-const ERROR_NAME = 'EslintPluginImportResolveError'
+const ERROR_NAME = 'EslintPluginImportResolveError';
 
-const fileExistsCache = new ModuleCache()
+const fileExistsCache = new ModuleCache();
 
 // Polyfill Node's `Module.createRequireFromPath` if not present (added in Node v10.12.0)
 // Use `Module.createRequire` if available (added in Node v12.2.0)
 const createRequire = Module.createRequire || Module.createRequireFromPath || function (filename) {
-  const mod = new Module(filename, null)
-  mod.filename = filename
-  mod.paths = Module._nodeModulePaths(path.dirname(filename))
+  const mod = new Module(filename, null);
+  mod.filename = filename;
+  mod.paths = Module._nodeModulePaths(path.dirname(filename));
 
-  mod._compile(`module.exports = require;`, filename)
+  mod._compile(`module.exports = require;`, filename);
 
-  return mod.exports
-}
+  return mod.exports;
+};
 
 function tryRequire(target, sourceFile) {
-  let resolved
+  let resolved;
   try {
     // Check if the target exists
     if (sourceFile != null) {
       try {
-        resolved = createRequire(path.resolve(sourceFile)).resolve(target)
+        resolved = createRequire(path.resolve(sourceFile)).resolve(target);
       } catch (e) {
-        resolved = require.resolve(target)
+        resolved = require.resolve(target);
       }
     } else {
-      resolved = require.resolve(target)
+      resolved = require.resolve(target);
     }
   } catch(e) {
     // If the target does not exist then just return undefined
-    return undefined
+    return undefined;
   }
 
   // If the target exists then return the loaded module
-  return require(resolved)
+  return require(resolved);
 }
 
 // http://stackoverflow.com/a/27382838
 exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings) {
   // don't care if the FS is case-sensitive
-  if (CASE_SENSITIVE_FS) return true
+  if (CASE_SENSITIVE_FS) return true;
 
   // null means it resolved to a builtin
-  if (filepath === null) return true
-  if (filepath.toLowerCase() === process.cwd().toLowerCase()) return true
+  if (filepath === null) return true;
+  if (filepath.toLowerCase() === process.cwd().toLowerCase()) return true;
   const parsedPath = path.parse(filepath)
-      , dir = parsedPath.dir
+      , dir = parsedPath.dir;
 
-  let result = fileExistsCache.get(filepath, cacheSettings)
-  if (result != null) return result
+  let result = fileExistsCache.get(filepath, cacheSettings);
+  if (result != null) return result;
 
   // base case
   if (dir === '' || parsedPath.root === filepath) {
-    result = true
+    result = true;
   } else {
-    const filenames = fs.readdirSync(dir)
+    const filenames = fs.readdirSync(dir);
     if (filenames.indexOf(parsedPath.base) === -1) {
-      result = false
+      result = false;
     } else {
-      result = fileExistsWithCaseSync(dir, cacheSettings)
+      result = fileExistsWithCaseSync(dir, cacheSettings);
     }
   }
-  fileExistsCache.set(filepath, result)
-  return result
-}
+  fileExistsCache.set(filepath, result);
+  return result;
+};
 
 function relative(modulePath, sourceFile, settings) {
-  return fullResolve(modulePath, sourceFile, settings).path
+  return fullResolve(modulePath, sourceFile, settings).path;
 }
 
 function fullResolve(modulePath, sourceFile, settings) {
   // check if this is a bonus core module
-  const coreSet = new Set(settings['import/core-modules'])
-  if (coreSet.has(modulePath)) return { found: true, path: null }
+  const coreSet = new Set(settings['import/core-modules']);
+  if (coreSet.has(modulePath)) return { found: true, path: null };
 
   const sourceDir = path.dirname(sourceFile)
-      , cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath
+      , cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath;
 
-  const cacheSettings = ModuleCache.getSettings(settings)
+  const cacheSettings = ModuleCache.getSettings(settings);
 
-  const cachedPath = fileExistsCache.get(cacheKey, cacheSettings)
-  if (cachedPath !== undefined) return { found: true, path: cachedPath }
+  const cachedPath = fileExistsCache.get(cacheKey, cacheSettings);
+  if (cachedPath !== undefined) return { found: true, path: cachedPath };
 
   function cache(resolvedPath) {
-    fileExistsCache.set(cacheKey, resolvedPath)
+    fileExistsCache.set(cacheKey, resolvedPath);
   }
 
   function withResolver(resolver, config) {
 
     function v1() {
       try {
-        const resolved = resolver.resolveImport(modulePath, sourceFile, config)
-        if (resolved === undefined) return { found: false }
-        return { found: true, path: resolved }
+        const resolved = resolver.resolveImport(modulePath, sourceFile, config);
+        if (resolved === undefined) return { found: false };
+        return { found: true, path: resolved };
       } catch (err) {
-        return { found: false }
+        return { found: false };
       }
     }
 
     function v2() {
-      return resolver.resolve(modulePath, sourceFile, config)
+      return resolver.resolve(modulePath, sourceFile, config);
     }
 
     switch (resolver.interfaceVersion) {
       case 2:
-        return v2()
+        return v2();
 
       default:
       case 1:
-        return v1()
+        return v1();
     }
   }
 
   const configResolvers = (settings['import/resolver']
-    || { 'node': settings['import/resolve'] }) // backward compatibility
+    || { 'node': settings['import/resolve'] }); // backward compatibility
 
-  const resolvers = resolverReducer(configResolvers, new Map())
+  const resolvers = resolverReducer(configResolvers, new Map());
 
   for (let pair of resolvers) {
     let name = pair[0]
-      , config = pair[1]
+      , config = pair[1];
     const resolver = requireResolver(name, sourceFile)
-        , resolved = withResolver(resolver, config)
+        , resolved = withResolver(resolver, config);
 
-    if (!resolved.found) continue
+    if (!resolved.found) continue;
 
     // else, counts
-    cache(resolved.path)
-    return resolved
+    cache(resolved.path);
+    return resolved;
   }
 
   // failed
   // cache(undefined)
-  return { found: false }
+  return { found: false };
 }
-exports.relative = relative
+exports.relative = relative;
 
 function resolverReducer(resolvers, map) {
   if (resolvers instanceof Array) {
-    resolvers.forEach(r => resolverReducer(r, map))
-    return map
+    resolvers.forEach(r => resolverReducer(r, map));
+    return map;
   }
 
   if (typeof resolvers === 'string') {
-    map.set(resolvers, null)
-    return map
+    map.set(resolvers, null);
+    return map;
   }
 
   if (typeof resolvers === 'object') {
     for (let key in resolvers) {
-      map.set(key, resolvers[key])
+      map.set(key, resolvers[key]);
     }
-    return map
+    return map;
   }
 
-  const err = new Error('invalid resolver config')
-  err.name = ERROR_NAME
-  throw err
+  const err = new Error('invalid resolver config');
+  err.name = ERROR_NAME;
+  throw err;
 }
 
 function getBaseDir(sourceFile) {
-  return pkgDir.sync(sourceFile) || process.cwd()
+  return pkgDir.sync(sourceFile) || process.cwd();
 }
 function requireResolver(name, sourceFile) {
   // Try to resolve package with conventional name
   let resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile) ||
     tryRequire(name, sourceFile) ||
-    tryRequire(path.resolve(getBaseDir(sourceFile), name))
+    tryRequire(path.resolve(getBaseDir(sourceFile), name));
 
   if (!resolver) {
-    const err = new Error(`unable to load resolver "${name}".`)
-    err.name = ERROR_NAME
-    throw err
+    const err = new Error(`unable to load resolver "${name}".`);
+    err.name = ERROR_NAME;
+    throw err;
   }
   if (!isResolverValid(resolver)) {
-    const err = new Error(`${name} with invalid interface loaded as resolver`)
-    err.name = ERROR_NAME
-    throw err
+    const err = new Error(`${name} with invalid interface loaded as resolver`);
+    err.name = ERROR_NAME;
+    throw err;
   }
 
-  return resolver
+  return resolver;
 }
 
 function isResolverValid(resolver) {
   if (resolver.interfaceVersion === 2) {
-    return resolver.resolve && typeof resolver.resolve === 'function'
+    return resolver.resolve && typeof resolver.resolve === 'function';
   } else {
-    return resolver.resolveImport && typeof resolver.resolveImport === 'function'
+    return resolver.resolveImport && typeof resolver.resolveImport === 'function';
   }
 }
 
-const erroredContexts = new Set()
+const erroredContexts = new Set();
 
 /**
  * Given
@@ -220,22 +220,22 @@ function resolve(p, context) {
     return relative( p
                    , context.getFilename()
                    , context.settings
-                   )
+                   );
   } catch (err) {
     if (!erroredContexts.has(context)) {
       // The `err.stack` string starts with `err.name` followed by colon and `err.message`.
       // We're filtering out the default `err.name` because it adds little value to the message.
-      let errMessage = err.message
+      let errMessage = err.message;
       if (err.name !== ERROR_NAME && err.stack) {
-        errMessage = err.stack.replace(/^Error: /, '')
+        errMessage = err.stack.replace(/^Error: /, '');
       }
       context.report({
         message: `Resolve error: ${errMessage}`,
         loc: { line: 1, column: 0 },
-      })
-      erroredContexts.add(context)
+      });
+      erroredContexts.add(context);
     }
   }
 }
-resolve.relative = relative
-exports.default = resolve
+resolve.relative = relative;
+exports.default = resolve;
diff --git a/utils/unambiguous.js b/utils/unambiguous.js
index 1dae1d6167..1446632f39 100644
--- a/utils/unambiguous.js
+++ b/utils/unambiguous.js
@@ -1,8 +1,8 @@
-'use strict'
-exports.__esModule = true
+'use strict';
+exports.__esModule = true;
 
 
-const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))/m
+const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))/m;
 /**
  * detect possible imports/exports without a full parse.
  *
@@ -14,11 +14,11 @@ const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))/m
  * @type {RegExp}
  */
 exports.test = function isMaybeUnambiguousModule(content) {
-  return pattern.test(content)
-}
+  return pattern.test(content);
+};
 
 // future-/Babel-proof at the expense of being a little loose
-const unambiguousNodeType = /^(?:(?:Exp|Imp)ort.*Declaration|TSExportAssignment)$/
+const unambiguousNodeType = /^(?:(?:Exp|Imp)ort.*Declaration|TSExportAssignment)$/;
 
 /**
  * Given an AST, return true if the AST unambiguously represents a module.
@@ -26,5 +26,5 @@ const unambiguousNodeType = /^(?:(?:Exp|Imp)ort.*Declaration|TSExportAssignment)
  * @return {Boolean}
  */
 exports.isModule = function isUnambiguousModule(ast) {
-  return ast.body.some(node => unambiguousNodeType.test(node.type))
-}
+  return ast.body.some(node => unambiguousNodeType.test(node.type));
+};

From 6c8981d9a523158a29ef05a18167522372d10d08 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 17 Jan 2021 10:08:55 -0800
Subject: [PATCH 226/767] [meta] enable `no-var` and `prefer-const`

---
 .eslintrc                              |   2 +
 config/typescript.js                   |   2 +-
 resolvers/node/index.js                |   6 +-
 resolvers/node/test/paths.js           |   8 +-
 resolvers/webpack/index.js             | 118 ++++++++++++-------------
 resolvers/webpack/test/alias.js        |   8 +-
 resolvers/webpack/test/config.js       |  34 +++----
 resolvers/webpack/test/example.js      |   8 +-
 resolvers/webpack/test/extensions.js   |   6 +-
 resolvers/webpack/test/externals.js    |  14 +--
 resolvers/webpack/test/fallback.js     |   6 +-
 resolvers/webpack/test/loaders.js      |   6 +-
 resolvers/webpack/test/modules.js      |   6 +-
 resolvers/webpack/test/packageMains.js |   6 +-
 resolvers/webpack/test/plugins.js      |   8 +-
 resolvers/webpack/test/root.js         |   8 +-
 scripts/copyMetafiles.js               |  10 +--
 scripts/testAll.js                     |   6 +-
 src/ExportMap.js                       |  23 ++---
 src/importDeclaration.js               |   2 +-
 src/rules/default.js                   |   2 +-
 src/rules/export.js                    |   8 +-
 src/rules/first.js                     |  18 ++--
 src/rules/group-exports.js             |   2 +-
 src/rules/namespace.js                 |  10 +--
 src/rules/newline-after-import.js      |   2 +-
 src/rules/no-commonjs.js               |   2 +-
 src/rules/no-cycle.js                  |   2 +-
 src/rules/no-deprecated.js             |   4 +-
 src/rules/no-mutable-exports.js        |   6 +-
 src/rules/no-named-as-default.js       |   4 +-
 src/rules/no-unused-modules.js         |   2 +-
 src/rules/no-useless-path-segments.js  |   2 +-
 src/rules/order.js                     |   6 +-
 tests/src/core/getExports.js           |  10 +--
 tests/src/package.js                   |  14 +--
 tests/src/rules/default.js             |   2 +-
 tests/src/rules/export.js              |   2 +-
 tests/src/rules/named.js               |   2 +-
 tests/src/rules/namespace.js           |   2 +-
 tests/src/rules/no-amd.js              |   2 +-
 tests/src/rules/no-unresolved.js       |   2 +-
 utils/declaredScope.js                 |  13 +--
 utils/ignore.js                        |   2 +-
 utils/moduleVisitor.js                 |   4 +-
 utils/parse.js                         |   2 +-
 utils/resolve.js                       |   8 +-
 47 files changed, 210 insertions(+), 212 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 16bd77655d..b62ebc2987 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -24,6 +24,8 @@
         "eqeqeq": [2, "allow-null"],
         "max-len": [1, 99, 2],
         "no-shadow": 1,
+        "no-var": 2,
+        "prefer-const": 2,
         "quotes": [2, "single", {
             "allowTemplateLiterals": true,
             "avoidEscape": true,
diff --git a/config/typescript.js b/config/typescript.js
index 0138d6378c..01b59f06b9 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -2,7 +2,7 @@
  * Adds `.jsx`, `.ts` and `.tsx` as an extension, and enables JSX/TSX parsing.
  */
 
-var allExtensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx'];
+const allExtensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx'];
 
 module.exports = {
 
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index 3d6d85ee7c..5d7db3cb52 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -1,13 +1,13 @@
-var resolve = require('resolve')
+const resolve = require('resolve')
   , path = require('path');
 
-var log = require('debug')('eslint-plugin-import:resolver:node');
+const log = require('debug')('eslint-plugin-import:resolver:node');
 
 exports.interfaceVersion = 2;
 
 exports.resolve = function (source, file, config) {
   log('Resolving:', source, 'from:', file);
-  var resolvedPath;
+  let resolvedPath;
 
   if (resolve.isCore(source)) {
     log('resolved to core');
diff --git a/resolvers/node/test/paths.js b/resolvers/node/test/paths.js
index ace7cc1ef8..81d8fb8448 100644
--- a/resolvers/node/test/paths.js
+++ b/resolvers/node/test/paths.js
@@ -1,7 +1,7 @@
-var expect = require('chai').expect;
+const expect = require('chai').expect;
 
-var path = require('path');
-var node = require('../index.js');
+const path = require('path');
+const node = require('../index.js');
 
 describe("paths", function () {
   it("handles base path relative to CWD", function () {
@@ -14,7 +14,7 @@ describe("paths", function () {
 
 describe("core", function () {
   it("returns found, but null path, for core Node modules", function () {
-    var resolved = node.resolve('fs', "./test/file.js");
+    const resolved = node.resolve('fs', "./test/file.js");
     expect(resolved).has.property("found", true);
     expect(resolved).has.property("path", null);
   });
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index e9bf38a492..e75eb3d0dd 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -1,4 +1,4 @@
-var findRoot = require('find-root')
+const findRoot = require('find-root')
   , path = require('path')
   , get = require('lodash/get')
   , isEqual = require('lodash/isEqual')
@@ -10,7 +10,7 @@ var findRoot = require('find-root')
   , semver = require('semver')
   , has = require('has');
 
-var log = require('debug')('eslint-plugin-import:resolver:webpack');
+const log = require('debug')('eslint-plugin-import:resolver:webpack');
 
 exports.interfaceVersion = 2;
 
@@ -35,31 +35,31 @@ exports.interfaceVersion = 2;
 exports.resolve = function (source, file, settings) {
 
   // strip loaders
-  var finalBang = source.lastIndexOf('!');
+  const finalBang = source.lastIndexOf('!');
   if (finalBang >= 0) {
     source = source.slice(finalBang + 1);
   }
 
   // strip resource query
-  var finalQuestionMark = source.lastIndexOf('?');
+  const finalQuestionMark = source.lastIndexOf('?');
   if (finalQuestionMark >= 0) {
     source = source.slice(0, finalQuestionMark);
   }
 
-  var webpackConfig;
+  let webpackConfig;
 
-  var _configPath = get(settings, 'config')
+  const _configPath = get(settings, 'config');
     /**
      * Attempt to set the current working directory.
      * If none is passed, default to the `cwd` where the config is located.
      */
-    , cwd = get(settings, 'cwd')
-    , configIndex = get(settings, 'config-index')
-    , env = get(settings, 'env')
-    , argv = get(settings, 'argv', {})
-    , packageDir;
+  const cwd = get(settings, 'cwd');
+  const configIndex = get(settings, 'config-index');
+  const env = get(settings, 'env');
+  const argv = get(settings, 'argv', {});
+  let packageDir;
 
-  var configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
+  let configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
     ? path.resolve(_configPath)
     : _configPath;
 
@@ -137,7 +137,7 @@ exports.resolve = function (source, file, settings) {
   }
 
   // otherwise, resolve "normally"
-  var resolveSync = getResolveSync(configPath, webpackConfig, cwd);
+  const resolveSync = getResolveSync(configPath, webpackConfig, cwd);
 
   try {
     return { found: true, path: resolveSync(path.dirname(file), source) };
@@ -151,11 +151,11 @@ exports.resolve = function (source, file, settings) {
   }
 };
 
-var MAX_CACHE = 10;
-var _cache = [];
+const MAX_CACHE = 10;
+const _cache = [];
 function getResolveSync(configPath, webpackConfig, cwd) {
-  var cacheKey = { configPath: configPath, webpackConfig: webpackConfig };
-  var cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
+  const cacheKey = { configPath: configPath, webpackConfig: webpackConfig };
+  let cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
   if (!cached) {
     cached = {
       key: cacheKey,
@@ -170,7 +170,7 @@ function getResolveSync(configPath, webpackConfig, cwd) {
 }
 
 function createResolveSync(configPath, webpackConfig, cwd) {
-  var webpackRequire
+  let webpackRequire
     , basedir = null;
 
   if (typeof configPath === 'string') {
@@ -181,8 +181,8 @@ function createResolveSync(configPath, webpackConfig, cwd) {
 
   try {
     // Attempt to resolve webpack from the given `basedir`
-    var webpackFilename = resolve.sync('webpack', { basedir, preserveSymlinks: false });
-    var webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false };
+    const webpackFilename = resolve.sync('webpack', { basedir, preserveSymlinks: false });
+    const webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false };
 
     webpackRequire = function (id) {
       return require(resolve.sync(id, webpackResolveOpts));
@@ -194,11 +194,11 @@ function createResolveSync(configPath, webpackConfig, cwd) {
     webpackRequire = require;
   }
 
-  var enhancedResolvePackage = webpackRequire('enhanced-resolve/package.json');
-  var enhancedResolveVersion = enhancedResolvePackage.version;
+  const enhancedResolvePackage = webpackRequire('enhanced-resolve/package.json');
+  const enhancedResolveVersion = enhancedResolvePackage.version;
   log('enhanced-resolve version:', enhancedResolveVersion);
 
-  var resolveConfig = webpackConfig.resolve || {};
+  const resolveConfig = webpackConfig.resolve || {};
 
   if (semver.major(enhancedResolveVersion) >= 2) {
     return createWebpack2ResolveSync(webpackRequire, resolveConfig);
@@ -207,18 +207,12 @@ function createResolveSync(configPath, webpackConfig, cwd) {
   return createWebpack1ResolveSync(webpackRequire, resolveConfig, webpackConfig.plugins);
 }
 
-function createWebpack2ResolveSync(webpackRequire, resolveConfig) {
-  var EnhancedResolve = webpackRequire('enhanced-resolve');
-
-  return EnhancedResolve.create.sync(Object.assign({}, webpack2DefaultResolveConfig, resolveConfig));
-}
-
 /**
  * webpack 2 defaults:
  * https://github.com/webpack/webpack/blob/v2.1.0-beta.20/lib/WebpackOptionsDefaulter.js#L72-L87
  * @type {Object}
  */
-var webpack2DefaultResolveConfig = {
+const webpack2DefaultResolveConfig = {
   unsafeCache: true, // Probably a no-op, since how can we cache anything at all here?
   modules: ['node_modules'],
   extensions: ['.js', '.json'],
@@ -226,28 +220,42 @@ var webpack2DefaultResolveConfig = {
   mainFields: ['browser', 'module', 'main'],
 };
 
+function createWebpack2ResolveSync(webpackRequire, resolveConfig) {
+  const EnhancedResolve = webpackRequire('enhanced-resolve');
+
+  return EnhancedResolve.create.sync(Object.assign({}, webpack2DefaultResolveConfig, resolveConfig));
+}
+
+/**
+ * webpack 1 defaults: http://webpack.github.io/docs/configuration.html#resolve-packagemains
+ * @type {Array}
+ */
+const webpack1DefaultMains = [
+  'webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main',
+];
+
 // adapted from tests &
 // https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L322
 function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
-  var Resolver = webpackRequire('enhanced-resolve/lib/Resolver');
-  var SyncNodeJsInputFileSystem = webpackRequire('enhanced-resolve/lib/SyncNodeJsInputFileSystem');
+  const Resolver = webpackRequire('enhanced-resolve/lib/Resolver');
+  const SyncNodeJsInputFileSystem = webpackRequire('enhanced-resolve/lib/SyncNodeJsInputFileSystem');
 
-  var ModuleAliasPlugin = webpackRequire('enhanced-resolve/lib/ModuleAliasPlugin');
-  var ModulesInDirectoriesPlugin =
+  const ModuleAliasPlugin = webpackRequire('enhanced-resolve/lib/ModuleAliasPlugin');
+  const ModulesInDirectoriesPlugin =
     webpackRequire('enhanced-resolve/lib/ModulesInDirectoriesPlugin');
-  var ModulesInRootPlugin = webpackRequire('enhanced-resolve/lib/ModulesInRootPlugin');
-  var ModuleAsFilePlugin = webpackRequire('enhanced-resolve/lib/ModuleAsFilePlugin');
-  var ModuleAsDirectoryPlugin = webpackRequire('enhanced-resolve/lib/ModuleAsDirectoryPlugin');
-  var DirectoryDescriptionFilePlugin =
+  const ModulesInRootPlugin = webpackRequire('enhanced-resolve/lib/ModulesInRootPlugin');
+  const ModuleAsFilePlugin = webpackRequire('enhanced-resolve/lib/ModuleAsFilePlugin');
+  const ModuleAsDirectoryPlugin = webpackRequire('enhanced-resolve/lib/ModuleAsDirectoryPlugin');
+  const DirectoryDescriptionFilePlugin =
     webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFilePlugin');
-  var DirectoryDefaultFilePlugin =
+  const DirectoryDefaultFilePlugin =
     webpackRequire('enhanced-resolve/lib/DirectoryDefaultFilePlugin');
-  var FileAppendPlugin = webpackRequire('enhanced-resolve/lib/FileAppendPlugin');
-  var ResultSymlinkPlugin = webpackRequire('enhanced-resolve/lib/ResultSymlinkPlugin');
-  var DirectoryDescriptionFileFieldAliasPlugin =
+  const FileAppendPlugin = webpackRequire('enhanced-resolve/lib/FileAppendPlugin');
+  const ResultSymlinkPlugin = webpackRequire('enhanced-resolve/lib/ResultSymlinkPlugin');
+  const DirectoryDescriptionFileFieldAliasPlugin =
     webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFileFieldAliasPlugin');
 
-  var resolver = new Resolver(new SyncNodeJsInputFileSystem());
+  const resolver = new Resolver(new SyncNodeJsInputFileSystem());
 
   resolver.apply(
     resolveConfig.packageAlias
@@ -272,7 +280,7 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
   );
 
 
-  var resolvePlugins = [];
+  const resolvePlugins = [];
 
   // support webpack.ResolverPlugin
   if (plugins) {
@@ -326,7 +334,7 @@ function findExternal(source, externals, context) {
   }
 
   if (typeof externals === 'function') {
-    var functionExternalFound = false;
+    let functionExternalFound = false;
     externals.call(null, context, source, function(err, value) {
       if (err) {
         functionExternalFound = false;
@@ -338,26 +346,18 @@ function findExternal(source, externals, context) {
   }
 
   // else, vanilla object
-  for (var key in externals) {
+  for (const key in externals) {
     if (!has(externals, key)) continue;
     if (source === key) return true;
   }
   return false;
 }
 
-/**
- * webpack 1 defaults: http://webpack.github.io/docs/configuration.html#resolve-packagemains
- * @type {Array}
- */
-var webpack1DefaultMains = [
-  'webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main',
-];
-
 function findConfigPath(configPath, packageDir) {
-  var extensions = Object.keys(interpret.extensions).sort(function(a, b) {
+  const extensions = Object.keys(interpret.extensions).sort(function(a, b) {
     return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length;
-  })
-    , extension;
+  });
+  let extension;
 
 
   if (configPath) {
@@ -383,7 +383,7 @@ function findConfigPath(configPath, packageDir) {
         return;
       }
 
-      var maybePath = path.resolve(
+      const maybePath = path.resolve(
         path.join(packageDir, 'webpack.config' + maybeExtension)
       );
       if (fs.existsSync(maybePath)) {
@@ -404,7 +404,7 @@ function registerCompiler(moduleDescriptor) {
     } else if(!Array.isArray(moduleDescriptor)) {
       moduleDescriptor.register(require(moduleDescriptor.module));
     } else {
-      for(var i = 0; i < moduleDescriptor.length; i++) {
+      for(let i = 0; i < moduleDescriptor.length; i++) {
         try {
           registerCompiler(moduleDescriptor[i]);
           break;
diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js
index 2cacda9984..ac43733ffe 100644
--- a/resolvers/webpack/test/alias.js
+++ b/resolvers/webpack/test/alias.js
@@ -1,13 +1,13 @@
-var chai = require('chai')
+const chai = require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var webpack = require('../index');
+const webpack = require('../index');
 
-var file = path.join(__dirname, 'files', 'dummy.js');
+const file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("resolve.alias", function () {
-  var resolved;
+  let resolved;
   before(function () { resolved = webpack.resolve('foo', file); });
 
   it("is found", function () { expect(resolved).to.have.property('found', true); });
diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index 4edb969639..aa69c7f6a9 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -1,13 +1,13 @@
-var chai =  require('chai')
+const chai =  require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var resolve = require('../index').resolve;
+const resolve = require('../index').resolve;
 
-var file = path.join(__dirname, 'files', 'src', 'jsx', 'dummy.js');
-var extensionFile = path.join(__dirname, 'config-extensions', 'src', 'dummy.js');
+const file = path.join(__dirname, 'files', 'src', 'jsx', 'dummy.js');
+const extensionFile = path.join(__dirname, 'config-extensions', 'src', 'dummy.js');
 
-var absoluteSettings = {
+const absoluteSettings = {
   config: path.join(__dirname, 'files', 'some', 'absolute.path.webpack.config.js'),
 };
 
@@ -23,7 +23,7 @@ describe("config", function () {
   });
 
   it("finds compile-to-js configs", function () {
-    var settings = {
+    const settings = {
       config: path.join(__dirname, './files/webpack.config.babel.js'),
     };
 
@@ -39,7 +39,7 @@ describe("config", function () {
   });
 
   it("finds the first config with a resolve section", function () {
-    var settings = {
+    const settings = {
       config: path.join(__dirname, './files/webpack.config.multiple.js'),
     };
 
@@ -48,7 +48,7 @@ describe("config", function () {
   });
 
   it("finds the config at option config-index", function () {
-    var settings = {
+    const settings = {
       config: path.join(__dirname, './files/webpack.config.multiple.js'),
       'config-index': 2,
     };
@@ -58,14 +58,14 @@ describe("config", function () {
   });
 
   it("doesn't swallow config load errors (#435)", function () {
-    var settings = {
+    const settings = {
       config: path.join(__dirname, './files/webpack.config.garbage.js'),
     };
     expect(function () { resolve('foo', file, settings); }).to.throw(Error);
   });
 
   it("finds config object when config is an object", function () {
-    var settings = {
+    const settings = {
       config: require(path.join(__dirname, 'files', 'some', 'absolute.path.webpack.config.js')),
     };
     expect(resolve('foo', file, settings)).to.have.property('path')
@@ -73,7 +73,7 @@ describe("config", function () {
   });
 
   it("finds config object when config uses a path relative to working dir", function () {
-    var settings = {
+    const settings = {
       config: './test/files/some/absolute.path.webpack.config.js',
     };
     expect(resolve('foo', file, settings)).to.have.property('path')
@@ -81,7 +81,7 @@ describe("config", function () {
   });
 
   it("finds the first config with a resolve section when config is an array of config objects", function () {
-    var settings = {
+    const settings = {
       config: require(path.join(__dirname, './files/webpack.config.multiple.js')),
     };
 
@@ -90,7 +90,7 @@ describe("config", function () {
   });
 
   it("finds the config at option config-index when config is an array of config objects", function () {
-    var settings = {
+    const settings = {
       config: require(path.join(__dirname, './files/webpack.config.multiple.js')),
       'config-index': 2,
     };
@@ -100,7 +100,7 @@ describe("config", function () {
   });
 
   it('finds the config at option env when config is a function', function() {
-    var settings = {
+    const settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
       env: {
         dummy: true,
@@ -112,7 +112,7 @@ describe("config", function () {
   });
 
   it('finds the config at option env when config is an array of functions', function() {
-    var settings = {
+    const settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.multiple.js')),
       env: {
         dummy: true,
@@ -124,7 +124,7 @@ describe("config", function () {
   });
 
   it('passes argv to config when it is a function', function() {
-    var settings = {
+    const settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
       argv: {
         mode: 'test',
@@ -136,7 +136,7 @@ describe("config", function () {
   });
 
   it('passes a default empty argv object to config when it is a function', function() {
-    var settings = {
+    const settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
       argv: undefined,
     };
diff --git a/resolvers/webpack/test/example.js b/resolvers/webpack/test/example.js
index c99ddffa4d..a36b5bb246 100644
--- a/resolvers/webpack/test/example.js
+++ b/resolvers/webpack/test/example.js
@@ -1,9 +1,9 @@
-var path = require('path');
+const path = require('path');
 
-var resolve = require('../index').resolve;
+const resolve = require('../index').resolve;
 
-var file = path.join(__dirname, 'files', 'src', 'dummy.js');
+const file = path.join(__dirname, 'files', 'src', 'dummy.js');
 
-var webpackDir = path.join(__dirname, "different-package-location");
+const webpackDir = path.join(__dirname, "different-package-location");
 
 console.log(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir}));
diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js
index a62cb3284c..0ed123835a 100644
--- a/resolvers/webpack/test/extensions.js
+++ b/resolvers/webpack/test/extensions.js
@@ -1,11 +1,11 @@
-var chai =  require('chai')
+const chai =  require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var resolve = require('../index').resolve;
+const resolve = require('../index').resolve;
 
 
-var file = path.join(__dirname, 'files', 'dummy.js')
+const file = path.join(__dirname, 'files', 'dummy.js')
   , extensions = path.join(__dirname, 'custom-extensions', 'dummy.js');
 
 describe("extensions", function () {
diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js
index 7840a85178..97df9fe483 100644
--- a/resolvers/webpack/test/externals.js
+++ b/resolvers/webpack/test/externals.js
@@ -1,32 +1,32 @@
-var chai = require('chai')
+const chai = require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var webpack = require('../index');
+const webpack = require('../index');
 
-var file = path.join(__dirname, 'files', 'dummy.js');
+const file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("externals", function () {
   it("works on just a string", function () {
-    var resolved = webpack.resolve('bootstrap', file);
+    const resolved = webpack.resolve('bootstrap', file);
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
   });
 
   it("works on object-map", function () {
-    var resolved = webpack.resolve('jquery', file);
+    const resolved = webpack.resolve('jquery', file);
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
   });
 
   it("works on a function", function () {
-    var resolved = webpack.resolve('underscore', file);
+    const resolved = webpack.resolve('underscore', file);
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
   });
 
   it("returns null for core modules", function () {
-    var resolved = webpack.resolve('fs', file);
+    const resolved = webpack.resolve('fs', file);
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
   });
diff --git a/resolvers/webpack/test/fallback.js b/resolvers/webpack/test/fallback.js
index 76976573fd..c6d0335aa4 100644
--- a/resolvers/webpack/test/fallback.js
+++ b/resolvers/webpack/test/fallback.js
@@ -1,11 +1,11 @@
-var chai =  require('chai')
+const chai =  require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var resolve = require('../index').resolve;
+const resolve = require('../index').resolve;
 
 
-var file = path.join(__dirname, 'files', 'src', 'dummy.js');
+const file = path.join(__dirname, 'files', 'src', 'dummy.js');
 
 describe("fallback", function () {
   it("works", function () {
diff --git a/resolvers/webpack/test/loaders.js b/resolvers/webpack/test/loaders.js
index 4f7c48ccb5..9e157e0460 100644
--- a/resolvers/webpack/test/loaders.js
+++ b/resolvers/webpack/test/loaders.js
@@ -1,11 +1,11 @@
-var chai =  require('chai')
+const chai =  require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var resolve = require('../index').resolve;
+const resolve = require('../index').resolve;
 
 
-var file = path.join(__dirname, 'files', 'dummy.js');
+const file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("inline loader syntax", function () {
 
diff --git a/resolvers/webpack/test/modules.js b/resolvers/webpack/test/modules.js
index ea7d35d1e0..ed7dc46094 100644
--- a/resolvers/webpack/test/modules.js
+++ b/resolvers/webpack/test/modules.js
@@ -1,10 +1,10 @@
-var chai =  require('chai')
+const chai =  require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var resolve = require('../index').resolve;
+const resolve = require('../index').resolve;
 
-var file = path.join(__dirname, 'files', 'dummy.js');
+const file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("resolve.moduleDirectories", function () {
 
diff --git a/resolvers/webpack/test/packageMains.js b/resolvers/webpack/test/packageMains.js
index 50db032d80..9d6b46232a 100644
--- a/resolvers/webpack/test/packageMains.js
+++ b/resolvers/webpack/test/packageMains.js
@@ -1,10 +1,10 @@
-var chai = require('chai')
+const chai = require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var webpack = require('../');
+const webpack = require('../');
 
-var file = path.join(__dirname, 'package-mains', 'dummy.js');
+const file = path.join(__dirname, 'package-mains', 'dummy.js');
 
 
 describe("packageMains", function () {
diff --git a/resolvers/webpack/test/plugins.js b/resolvers/webpack/test/plugins.js
index 3f11e92efe..5d5bdee93d 100644
--- a/resolvers/webpack/test/plugins.js
+++ b/resolvers/webpack/test/plugins.js
@@ -1,13 +1,13 @@
-var chai = require('chai')
+const chai = require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var webpack = require('../index');
+const webpack = require('../index');
 
-var file = path.join(__dirname, 'files', 'dummy.js');
+const file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("plugins", function () {
-  var resolved, aliasResolved;
+  let resolved, aliasResolved;
 
   before(function () {
     resolved = webpack.resolve('./some/bar', file);
diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js
index 48d918498a..42719d5d15 100644
--- a/resolvers/webpack/test/root.js
+++ b/resolvers/webpack/test/root.js
@@ -1,12 +1,12 @@
-var chai =  require('chai')
+const chai =  require('chai')
   , expect = chai.expect
   , path = require('path');
 
-var resolve = require('../index').resolve;
+const resolve = require('../index').resolve;
 
 
-var file = path.join(__dirname, 'files', 'src', 'dummy.js');
-var webpackDir = path.join(__dirname, "different-package-location");
+const file = path.join(__dirname, 'files', 'src', 'dummy.js');
+const webpackDir = path.join(__dirname, "different-package-location");
 
 describe("root", function () {
   it("works", function () {
diff --git a/scripts/copyMetafiles.js b/scripts/copyMetafiles.js
index a58c8e10ac..7518d4a5ba 100644
--- a/scripts/copyMetafiles.js
+++ b/scripts/copyMetafiles.js
@@ -2,20 +2,20 @@ import path from 'path';
 import copyFileSync from 'fs-copy-file-sync';
 import resolverDirectories from './resolverDirectories';
 
-let files = [
+const files = [
     'LICENSE',
     '.npmrc',
 ];
 
-let directories = [
+const directories = [
     'memo-parser',
     ...resolverDirectories,
     'utils',
 ];
 
-for (let directory of directories) {
-    for (let file of files) {
-        let destination = path.join(directory, file);
+for (const directory of directories) {
+    for (const file of files) {
+        const destination = path.join(directory, file);
         copyFileSync(file, destination);
         console.log(`${file} -> ${destination}`);
     }
diff --git a/scripts/testAll.js b/scripts/testAll.js
index 843ffa5778..3a9f474ae7 100644
--- a/scripts/testAll.js
+++ b/scripts/testAll.js
@@ -2,8 +2,8 @@ import { spawnSync } from 'child_process';
 import npmWhich from 'npm-which';
 import resolverDirectories from './resolverDirectories';
 
-let npmPath = npmWhich(__dirname).sync('npm');
-let spawnOptions = {
+const npmPath = npmWhich(__dirname).sync('npm');
+const spawnOptions = {
     stdio: 'inherit',
 };
 
@@ -12,7 +12,7 @@ spawnSync(
     ['test'],
     Object.assign({ cwd: __dirname }, spawnOptions));
 
-for (let resolverDir of resolverDirectories) {
+for (const resolverDir of resolverDirectories) {
     spawnSync(
         npmPath,
         ['test'],
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 1d35ded187..1924ecc025 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -68,8 +68,8 @@ export default class ExportMap {
 
     // default exports must be explicitly re-exported (#328)
     if (name !== 'default') {
-      for (let dep of this.dependencies) {
-        let innerMap = dep();
+      for (const dep of this.dependencies) {
+        const innerMap = dep();
 
         // todo: report as unresolved?
         if (!innerMap) continue;
@@ -110,8 +110,8 @@ export default class ExportMap {
 
     // default exports must be explicitly re-exported (#328)
     if (name !== 'default') {
-      for (let dep of this.dependencies) {
-        let innerMap = dep();
+      for (const dep of this.dependencies) {
+        const innerMap = dep();
         if (innerMap == null) return { found: true, path: [this] };
         // todo: report as unresolved?
         if (!innerMap) continue;
@@ -119,7 +119,7 @@ export default class ExportMap {
         // safeguard against cycles
         if (innerMap.path === this.path) continue;
 
-        let innerValue = innerMap.hasDeep(name);
+        const innerValue = innerMap.hasDeep(name);
         if (innerValue.found) {
           innerValue.path.unshift(this);
           return innerValue;
@@ -148,15 +148,15 @@ export default class ExportMap {
 
     // default exports must be explicitly re-exported (#328)
     if (name !== 'default') {
-      for (let dep of this.dependencies) {
-        let innerMap = dep();
+      for (const dep of this.dependencies) {
+        const innerMap = dep();
         // todo: report as unresolved?
         if (!innerMap) continue;
 
         // safeguard against cycles
         if (innerMap.path === this.path) continue;
 
-        let innerValue = innerMap.get(name);
+        const innerValue = innerMap.get(name);
         if (innerValue !== undefined) return innerValue;
       }
     }
@@ -218,7 +218,7 @@ function captureDoc(source, docStyleParsers, ...nodes) {
 
       if (!leadingComments || leadingComments.length === 0) return false;
 
-      for (let name in docStyleParsers) {
+      for (const name in docStyleParsers) {
         const doc = docStyleParsers[name](leadingComments);
         if (doc) {
           metadata.doc = doc;
@@ -347,10 +347,11 @@ ExportMap.for = function (context) {
 
 
 ExportMap.parse = function (path, content, context) {
-  var m = new ExportMap(path);
+  const m = new ExportMap(path);
 
+  let ast;
   try {
-    var ast = parse(path, content, context);
+    ast = parse(path, content, context);
   } catch (err) {
     log('parse error:', path, err);
     m.errors.push(err);
diff --git a/src/importDeclaration.js b/src/importDeclaration.js
index fd3a73253c..0d5e1870a7 100644
--- a/src/importDeclaration.js
+++ b/src/importDeclaration.js
@@ -1,4 +1,4 @@
 export default function importDeclaration(context) {
-  var ancestors = context.getAncestors();
+  const ancestors = context.getAncestors();
   return ancestors[ancestors.length - 1];
 }
diff --git a/src/rules/default.js b/src/rules/default.js
index b686974a86..797519a64c 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -19,7 +19,7 @@ module.exports = {
       );
 
       if (!defaultSpecifier) return;
-      var imports = Exports.get(node.source.value, context);
+      const imports = Exports.get(node.source.value, context);
       if (imports == null) return;
 
       if (imports.errors.length) {
diff --git a/src/rules/export.js b/src/rules/export.js
index fcc649fcdc..203bb7d3b8 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -112,7 +112,7 @@ module.exports = {
         }
 
         if (node.declaration.declarations != null) {
-          for (let declaration of node.declaration.declarations) {
+          for (const declaration of node.declaration.declarations) {
             recursivePatternCapture(declaration.id, v =>
               addNamed(v.name, v, parent, isTypeVariableDecl));
           }
@@ -150,13 +150,13 @@ module.exports = {
       },
 
       'Program:exit': function () {
-        for (let [, named] of namespace) {
-          for (let [name, nodes] of named) {
+        for (const [, named] of namespace) {
+          for (const [name, nodes] of named) {
             if (nodes.size <= 1) continue;
 
             if (isTypescriptFunctionOverloads(nodes)) continue;
 
-            for (let node of nodes) {
+            for (const node of nodes) {
               if (name === 'default') {
                 context.report(node, 'Multiple default exports.');
               } else {
diff --git a/src/rules/first.js b/src/rules/first.js
index eea9d9e138..5018544473 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -29,13 +29,13 @@ module.exports = {
             , message = 'Import in body of module; reorder to top.'
             , sourceCode = context.getSourceCode()
             , originSourceCode = sourceCode.getText();
-        let nonImportCount = 0
-          , anyExpressions = false
-          , anyRelative = false
-          , lastLegalImp = null
-          , errorInfos = []
-          , shouldSort = true
-          , lastSortNodesIndex = 0;
+        let nonImportCount = 0;
+        let anyExpressions = false;
+        let anyRelative = false;
+        let lastLegalImp = null;
+        const errorInfos = [];
+        let shouldSort = true;
+        let lastSortNodesIndex = 0;
         body.forEach(function (node, index){
           if (!anyExpressions && isPossibleDirective(node)) {
             return;
@@ -55,11 +55,11 @@ module.exports = {
               }
             }
             if (nonImportCount > 0) {
-              for (let variable of context.getDeclaredVariables(node)) {
+              for (const variable of context.getDeclaredVariables(node)) {
                 if (!shouldSort) break;
                 const references = variable.references;
                 if (references.length) {
-                  for (let reference of references) {
+                  for (const reference of references) {
                     if (reference.identifier.range[0] < node.range[1]) {
                       shouldSort = false;
                       break;
diff --git a/src/rules/group-exports.js b/src/rules/group-exports.js
index a022eb6447..e9fc432977 100644
--- a/src/rules/group-exports.js
+++ b/src/rules/group-exports.js
@@ -61,7 +61,7 @@ function create(context) {
 
   return {
     ExportNamedDeclaration(node) {
-      let target = node.exportKind === 'type' ? nodes.types : nodes.modules;
+      const target = node.exportKind === 'type' ? nodes.types : nodes.modules;
       if (!node.source) {
         target.set.add(node);
       } else if (Array.isArray(target.sources[node.source.value])) {
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 6d0c367e77..579c1bfb2c 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -83,9 +83,9 @@ module.exports = {
 
       // same as above, but does not add names to local map
       ExportNamespaceSpecifier(namespace) {
-        var declaration = importDeclaration(context);
+        const declaration = importDeclaration(context);
 
-        var imports = Exports.get(declaration.source.value, context);
+        const imports = Exports.get(declaration.source.value, context);
         if (imports == null) return null;
 
         if (imports.errors.length) {
@@ -116,8 +116,8 @@ module.exports = {
         }
 
         // go deep
-        var namespace = namespaces.get(dereference.object.name);
-        var namepath = [dereference.object.name];
+        let namespace = namespaces.get(dereference.object.name);
+        const namepath = [dereference.object.name];
         // while property is namespace and parent is member expression, keep validating
         while (namespace instanceof Exports && dereference.type === 'MemberExpression') {
 
@@ -204,7 +204,7 @@ module.exports = {
 
       JSXMemberExpression({object, property}) {
          if (!namespaces.has(object.name)) return;
-         var namespace = namespaces.get(object.name);
+         const namespace = namespaces.get(object.name);
          if (!namespace.has(property.name)) {
            context.report({
              node: property,
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index c1fc363b1a..05c7e24273 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -73,7 +73,7 @@ module.exports = {
 
     function checkForNewLine(node, nextNode, type) {
       if (isExportDefaultClass(nextNode)) {
-        let classNode = nextNode.declaration;
+        const classNode = nextNode.declaration;
 
         if (isClassWithDecorator(classNode)) {
           nextNode = classNode.decorators[0];
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index 7c40f47cb6..c88c602720 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -114,7 +114,7 @@ module.exports = {
         if (call.callee.name !== 'require') return;
 
         if (call.arguments.length !== 1) return;
-        var module = call.arguments[0];
+        const module = call.arguments[0];
 
         if (module.type !== 'Literal') return;
         if (typeof module.value !== 'string') return;
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 5c11e26259..cbc8dad8ac 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -70,7 +70,7 @@ module.exports = {
         if (traversed.has(m.path)) return;
         traversed.add(m.path);
 
-        for (let [path, { getter, source }] of m.imports) {
+        for (const [path, { getter, source }] of m.imports) {
           if (path === myPath) return true;
           if (traversed.has(path)) continue;
           if (ignoreModule(source.value)) continue;
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index 38c0253c5d..e9788f27c0 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -114,8 +114,8 @@ module.exports = {
         if (declaredScope(context, dereference.object.name) !== 'module') return;
 
         // go deep
-        var namespace = namespaces.get(dereference.object.name);
-        var namepath = [dereference.object.name];
+        let namespace = namespaces.get(dereference.object.name);
+        const namepath = [dereference.object.name];
         // while property is namespace and parent is member expression, keep validating
         while (namespace instanceof Exports &&
                dereference.type === 'MemberExpression') {
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index ae334783ca..7c35638f98 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -18,9 +18,9 @@ module.exports = {
     }
 
     function checkDeclarationsInScope({variables}, name) {
-      for (let variable of variables) {
+      for (const variable of variables) {
         if (variable.name === name) {
-          for (let def of variable.defs) {
+          for (const def of variable.defs) {
             if (def.type === 'Variable' && def.parent) {
               checkDeclaration(def.parent);
             }
@@ -43,7 +43,7 @@ module.exports = {
       if (node.declaration)  {
         checkDeclaration(node.declaration);
       } else if (!node.source) {
-        for (let specifier of node.specifiers) {
+        for (const specifier of node.specifiers) {
           checkDeclarationsInScope(scope, specifier.local.name);
         }
       }
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index cbc85952b4..7313e61268 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -16,9 +16,9 @@ module.exports = {
       // #566: default is a valid specifier
       if (defaultSpecifier[nameKey].name === 'default') return;
 
-      var declaration = importDeclaration(context);
+      const declaration = importDeclaration(context);
 
-      var imports = Exports.get(declaration.source.value, context);
+      const imports = Exports.get(declaration.source.value, context);
       if (imports == null) return;
 
       if (imports.errors.length) {
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index cb60784c7c..596613889d 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -601,7 +601,7 @@ module.exports = {
       });
 
       // preserve information about namespace imports
-      let exportAll = exports.get(EXPORT_ALL_DECLARATION);
+      const exportAll = exports.get(EXPORT_ALL_DECLARATION);
       let namespaceImports = exports.get(IMPORT_NAMESPACE_SPECIFIER);
 
       if (typeof namespaceImports === 'undefined') {
diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index 6bb12f4e0d..b22aa94788 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -97,7 +97,7 @@ module.exports = {
 
         // Try to find ambiguous imports
         if (parentDirectory !== '.' && parentDirectory !== '..') {
-          for (let fileExtension of fileExtensions) {
+          for (const fileExtension of fileExtensions) {
             if (resolve(`${parentDirectory}${fileExtension}`, context)) {
               return reportWithProposedPath(`${parentDirectory}/`);
             }
diff --git a/src/rules/order.js b/src/rules/order.js
index ef1eb75ed9..2532a21de3 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -93,7 +93,7 @@ function findRootNode(node) {
 
 function findEndOfLineWithComments(sourceCode, node) {
   const tokensToEndOfLine = takeTokensAfterWhile(sourceCode, node, commentOnSameLineAs(node));
-  let endOfTokens = tokensToEndOfLine.length > 0
+  const endOfTokens = tokensToEndOfLine.length > 0
     ? tokensToEndOfLine[tokensToEndOfLine.length - 1].range[1]
     : node.range[1];
   let result = endOfTokens;
@@ -118,7 +118,7 @@ function commentOnSameLineAs(node) {
 
 function findStartOfLineWithComments(sourceCode, node) {
   const tokensToEndOfLine = takeTokensBeforeWhile(sourceCode, node, commentOnSameLineAs(node));
-  let startOfTokens = tokensToEndOfLine.length > 0 ? tokensToEndOfLine[0].range[0] : node.range[0];
+  const startOfTokens = tokensToEndOfLine.length > 0 ? tokensToEndOfLine[0].range[0] : node.range[0];
   let result = startOfTokens;
   for (let i = startOfTokens - 1; i > 0; i--) {
     if (sourceCode.text[i] !== ' ' && sourceCode.text[i] !== '\t') {
@@ -168,7 +168,7 @@ function canReorderItems(firstNode, secondNode) {
     parent.body.indexOf(secondNode),
   ].sort();
   const nodesBetween = parent.body.slice(firstIndex, secondIndex + 1);
-  for (var nodeBetween of nodesBetween) {
+  for (const nodeBetween of nodesBetween) {
     if (!canCrossNodeWhileReorder(nodeBetween)) {
       return false;
     }
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 60abcbf9ad..33ef05c473 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -16,7 +16,7 @@ describe('ExportMap', function () {
   };
 
   it('handles ExportAllDeclaration', function () {
-    var imports;
+    let imports;
     expect(function () {
       imports = ExportMap.get('./export-all', fakeContext);
     }).not.to.throw(Error);
@@ -59,7 +59,7 @@ describe('ExportMap', function () {
   });
 
   it('does not throw for a missing file', function () {
-    var imports;
+    let imports;
     expect(function () {
       imports = ExportMap.get('./does-not-exist', fakeContext);
     }).not.to.throw(Error);
@@ -69,7 +69,7 @@ describe('ExportMap', function () {
   });
 
   it('exports explicit names for a missing file in exports', function () {
-    var imports;
+    let imports;
     expect(function () {
       imports = ExportMap.get('./exports-missing', fakeContext);
     }).not.to.throw(Error);
@@ -82,7 +82,7 @@ describe('ExportMap', function () {
   it('finds exports for an ES7 module with babel-eslint', function () {
     const path = getFilename('jsx/FooES7.js')
         , contents = fs.readFileSync(path, { encoding: 'utf8' });
-    var imports = ExportMap.parse(
+    const imports = ExportMap.parse(
       path,
       contents,
       { parserPath: 'babel-eslint', settings: {} },
@@ -403,7 +403,7 @@ describe('ExportMap', function () {
       ['common.js', false],
     ];
 
-    for (let [testFile, expectedRegexResult] of testFiles) {
+    for (const [testFile, expectedRegexResult] of testFiles) {
       it(`works for ${testFile} (${expectedRegexResult})`, function () {
         const content = fs.readFileSync('./tests/files/' + testFile, 'utf8');
         expect(unambiguous.test(content)).to.equal(expectedRegexResult);
diff --git a/tests/src/package.js b/tests/src/package.js
index a7a60e2531..01f7097242 100644
--- a/tests/src/package.js
+++ b/tests/src/package.js
@@ -1,6 +1,6 @@
-var expect = require('chai').expect;
+const expect = require('chai').expect;
 
-var path = require('path')
+const path = require('path')
   , fs = require('fs');
 
 function isJSFile(f) {
@@ -8,8 +8,8 @@ function isJSFile(f) {
 }
 
 describe('package', function () {
-  let pkg = path.join(process.cwd(), 'src')
-    , module;
+  const pkg = path.join(process.cwd(), 'src');
+  let module;
 
   before('is importable', function () {
     module = require(pkg);
@@ -47,10 +47,10 @@ describe('package', function () {
   });
 
   it('has configs only for rules that exist', function () {
-    for (let configFile in module.configs) {
-      let preamble = 'import/';
+    for (const configFile in module.configs) {
+      const preamble = 'import/';
 
-      for (let rule in module.configs[configFile].rules) {
+      for (const rule in module.configs[configFile].rules) {
         expect(() => require(getRulePath(rule.slice(preamble.length))))
           .not.to.throw(Error);
       }
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index f80957a442..8fc66bc2ef 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -4,7 +4,7 @@ import { RuleTester } from 'eslint';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
-var ruleTester = new RuleTester()
+const ruleTester = new RuleTester()
   , rule = require('rules/default');
 
 ruleTester.run('default', rule, {
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index cee5e5ccb5..da3b25d95a 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -4,7 +4,7 @@ import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
-var ruleTester = new RuleTester()
+const ruleTester = new RuleTester()
   , rule = require('rules/export');
 
 ruleTester.run('export', rule, {
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 3a23e3e93d..fce805c890 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -4,7 +4,7 @@ import { RuleTester } from 'eslint';
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
 
-var ruleTester = new RuleTester()
+const ruleTester = new RuleTester()
   , rule = require('rules/named');
 
 function error(name, module) {
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 63192228b6..291960dbf5 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -2,7 +2,7 @@ import { test, SYNTAX_CASES, getTSParsers } from '../utils';
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
 
-var ruleTester = new RuleTester({ env: { es6: true }})
+const ruleTester = new RuleTester({ env: { es6: true }})
   , rule = require('rules/namespace');
 
 
diff --git a/tests/src/rules/no-amd.js b/tests/src/rules/no-amd.js
index b7f7793842..1371244006 100644
--- a/tests/src/rules/no-amd.js
+++ b/tests/src/rules/no-amd.js
@@ -2,7 +2,7 @@ import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
-var ruleTester = new RuleTester();
+const ruleTester = new RuleTester();
 
 ruleTester.run('no-amd', require('rules/no-amd'), {
   valid: [
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 8bc9ea5922..61b03de5c2 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -6,7 +6,7 @@ import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
 import { RuleTester } from 'eslint';
 
-var ruleTester = new RuleTester()
+const ruleTester = new RuleTester()
   , rule = require('rules/no-unresolved');
 
 function runResolverTests(resolver) {
diff --git a/utils/declaredScope.js b/utils/declaredScope.js
index 00005946b7..ded2131e49 100644
--- a/utils/declaredScope.js
+++ b/utils/declaredScope.js
@@ -2,13 +2,8 @@
 exports.__esModule = true;
 
 exports.default = function declaredScope(context, name) {
-  let references = context.getScope().references
-    , i;
-  for (i = 0; i < references.length; i++) {
-    if (references[i].identifier.name === name) {
-      break;
-    }
-  }
-  if (!references[i]) return undefined;
-  return references[i].resolved.scope.type;
+  const references = context.getScope().references;
+  const reference = references.find(x => x.identifier.name === name);
+  if (!reference) return undefined;
+  return reference.resolved.scope.type;
 };
diff --git a/utils/ignore.js b/utils/ignore.js
index 46e0cd4162..2a775b5da0 100644
--- a/utils/ignore.js
+++ b/utils/ignore.js
@@ -23,7 +23,7 @@ function makeValidExtensionSet(settings) {
 
   // all alternate parser extensions are also valid
   if ('import/parsers' in settings) {
-    for (let parser in settings['import/parsers']) {
+    for (const parser in settings['import/parsers']) {
       const parserSettings = settings['import/parsers'][parser];
       if (!Array.isArray(parserSettings)) {
         throw new TypeError('"settings" for ' + parser + ' must be an array');
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index 6eaccb331c..d801515bce 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -69,7 +69,7 @@ exports.default = function visitModules(visitor, options) {
     const modules = call.arguments[0];
     if (modules.type !== 'ArrayExpression') return;
 
-    for (let element of modules.elements) {
+    for (const element of modules.elements) {
       if (element.type !== 'Literal') continue;
       if (typeof element.value !== 'string') continue;
 
@@ -124,7 +124,7 @@ function makeOptionsSchema(additionalProperties) {
   };
 
   if (additionalProperties){
-    for (let key in additionalProperties) {
+    for (const key in additionalProperties) {
       base.properties[key] = additionalProperties[key];
     }
   }
diff --git a/utils/parse.js b/utils/parse.js
index 735e83a806..9cc2380b3a 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -69,7 +69,7 @@ function getParserPath(path, context) {
   const parsers = context.settings['import/parsers'];
   if (parsers != null) {
     const extension = extname(path);
-    for (let parserPath in parsers) {
+    for (const parserPath in parsers) {
       if (parsers[parserPath].indexOf(extension) > -1) {
         // use this alternate parser
         log('using alt parser:', parserPath);
diff --git a/utils/resolve.js b/utils/resolve.js
index 24fc265fc4..d1881a83f9 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -132,8 +132,8 @@ function fullResolve(modulePath, sourceFile, settings) {
 
   const resolvers = resolverReducer(configResolvers, new Map());
 
-  for (let pair of resolvers) {
-    let name = pair[0]
+  for (const pair of resolvers) {
+    const name = pair[0]
       , config = pair[1];
     const resolver = requireResolver(name, sourceFile)
         , resolved = withResolver(resolver, config);
@@ -163,7 +163,7 @@ function resolverReducer(resolvers, map) {
   }
 
   if (typeof resolvers === 'object') {
-    for (let key in resolvers) {
+    for (const key in resolvers) {
       map.set(key, resolvers[key]);
     }
     return map;
@@ -179,7 +179,7 @@ function getBaseDir(sourceFile) {
 }
 function requireResolver(name, sourceFile) {
   // Try to resolve package with conventional name
-  let resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile) ||
+  const resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile) ||
     tryRequire(name, sourceFile) ||
     tryRequire(path.resolve(getBaseDir(sourceFile), name));
 

From 39fe6e9af975cb0daad7271a65da915b7801d83e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 17 Jan 2021 10:10:05 -0800
Subject: [PATCH 227/767] [meta] enable `comma-style`, `func-call-spacing`,
 `indent`, `object-curly-spacing`, `one-var` (autofix)

---
 .eslintrc                                     |   5 +
 config/errors.js                              |  12 +-
 memo-parser/index.js                          |   6 +-
 resolvers/node/index.js                       |  26 +-
 resolvers/webpack/index.js                    |  72 +--
 resolvers/webpack/test/alias.js               |   6 +-
 resolvers/webpack/test/config.js              |  28 +-
 resolvers/webpack/test/example.js             |   2 +-
 resolvers/webpack/test/extensions.js          |  10 +-
 resolvers/webpack/test/externals.js           |   6 +-
 resolvers/webpack/test/fallback.js            |   6 +-
 resolvers/webpack/test/loaders.js             |   6 +-
 resolvers/webpack/test/modules.js             |   6 +-
 resolvers/webpack/test/packageMains.js        |   6 +-
 resolvers/webpack/test/plugins.js             |   8 +-
 resolvers/webpack/test/root.js                |  10 +-
 scripts/copyMetafiles.js                      |  20 +-
 scripts/testAll.js                            |  16 +-
 src/ExportMap.js                              | 136 +++---
 src/rules/extensions.js                       |  64 +--
 src/rules/first.js                            |  52 +-
 src/rules/max-dependencies.js                 |   2 +-
 src/rules/named.js                            |  14 +-
 src/rules/namespace.js                        |  60 +--
 src/rules/newline-after-import.js             |  42 +-
 src/rules/no-commonjs.js                      |   4 +-
 src/rules/no-cycle.js                         |   4 +-
 src/rules/no-default-export.js                |   8 +-
 src/rules/no-deprecated.js                    |  34 +-
 src/rules/no-extraneous-dependencies.js       |   4 +-
 src/rules/no-mutable-exports.js               |   4 +-
 src/rules/no-named-as-default-member.js       |   4 +-
 src/rules/no-named-export.js                  |   6 +-
 src/rules/no-restricted-paths.js              |  66 +--
 src/rules/no-self-import.js                   |   4 +-
 src/rules/no-unused-modules.js                |  20 +-
 src/rules/order.js                            |   4 +-
 tests/src/core/getExports.js                  |  28 +-
 tests/src/core/importType.js                  |   2 +-
 tests/src/core/parse.js                       |   4 +-
 tests/src/core/resolve.js                     |  72 +--
 tests/src/package.js                          |   6 +-
 tests/src/rules/default.js                    | 240 ++++-----
 tests/src/rules/export.js                     |   8 +-
 tests/src/rules/extensions.js                 |  62 +--
 tests/src/rules/first.js                      |  76 ++-
 tests/src/rules/group-exports.js              |   6 +-
 tests/src/rules/max-dependencies.js           |   6 +-
 tests/src/rules/named.js                      |  74 +--
 tests/src/rules/namespace.js                  |  42 +-
 tests/src/rules/newline-after-import.js       |  24 +-
 tests/src/rules/no-absolute-path.js           |  32 +-
 tests/src/rules/no-amd.js                     |  16 +-
 .../src/rules/no-anonymous-default-export.js  |  92 ++--
 tests/src/rules/no-commonjs.js                |   6 +-
 tests/src/rules/no-cycle.js                   |   6 +-
 tests/src/rules/no-default-export.js          |   4 +-
 tests/src/rules/no-deprecated.js              |   8 +-
 tests/src/rules/no-duplicates.js              |  68 +--
 tests/src/rules/no-dynamic-require.js         |  26 +-
 tests/src/rules/no-extraneous-dependencies.js |  89 ++--
 tests/src/rules/no-mutable-exports.js         |  40 +-
 tests/src/rules/no-named-as-default-member.js |  12 +-
 tests/src/rules/no-named-as-default.js        |  36 +-
 tests/src/rules/no-named-default.js           |   8 +-
 tests/src/rules/no-named-export.js            |   4 +-
 tests/src/rules/no-nodejs-modules.js          |  32 +-
 tests/src/rules/no-restricted-paths.js        |   6 +-
 tests/src/rules/no-self-import.js             |   4 +-
 tests/src/rules/no-unassigned-import.js       |  34 +-
 tests/src/rules/no-unresolved.js              | 156 +++---
 tests/src/rules/no-unused-modules.js          | 458 +++++++++---------
 tests/src/rules/no-useless-path-segments.js   |  12 +-
 tests/src/rules/no-webpack-loader-syntax.js   |  26 +-
 tests/src/rules/order.js                      |  82 ++--
 tests/src/rules/prefer-default-export.js      |  38 +-
 tests/src/rules/unambiguous.js                |   4 +-
 tests/src/utils.js                            |   4 +-
 utils/ignore.js                               |   2 +-
 utils/resolve.js                              |  36 +-
 80 files changed, 1387 insertions(+), 1387 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index b62ebc2987..5ad4ffcec3 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -19,12 +19,17 @@
     },
     "rules": {
         "comma-dangle": [2, "always-multiline"],
+        "comma-style": [2, "last"],
         "curly": [2, "multi-line"],
         "eol-last": [2, "always"],
         "eqeqeq": [2, "allow-null"],
+        "func-call-spacing": 2,
+        "indent": [2, 2],
         "max-len": [1, 99, 2],
         "no-shadow": 1,
         "no-var": 2,
+        "object-curly-spacing": [2, "always"],
+        "one-var": [2, "never"],
         "prefer-const": 2,
         "quotes": [2, "single", {
             "allowTemplateLiterals": true,
diff --git a/config/errors.js b/config/errors.js
index d13ef4ba09..127c29a0cc 100644
--- a/config/errors.js
+++ b/config/errors.js
@@ -5,10 +5,10 @@
  */
 module.exports = {
   plugins: ['import'],
-  rules: { 'import/no-unresolved': 2
-         , 'import/named': 2
-         , 'import/namespace': 2
-         , 'import/default': 2
-         , 'import/export': 2,
-         },
+  rules: { 'import/no-unresolved': 2,
+    'import/named': 2,
+    'import/namespace': 2,
+    'import/default': 2,
+    'import/export': 2,
+  },
 };
diff --git a/memo-parser/index.js b/memo-parser/index.js
index 1460f8ff38..de558ffa3e 100644
--- a/memo-parser/index.js
+++ b/memo-parser/index.js
@@ -1,8 +1,8 @@
 'use strict';
 
-const crypto = require('crypto')
-    , moduleRequire = require('eslint-module-utils/module-require').default
-    , hashObject = require('eslint-module-utils/hash').hashObject;
+const crypto = require('crypto');
+const moduleRequire = require('eslint-module-utils/module-require').default;
+const hashObject = require('eslint-module-utils/hash').hashObject;
 
 const cache = new Map();
 
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index 5d7db3cb52..3686cb5e6a 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -1,5 +1,5 @@
-const resolve = require('resolve')
-  , path = require('path');
+const resolve = require('resolve');
+const path = require('path');
 
 const log = require('debug')('eslint-plugin-import:resolver:node');
 
@@ -26,17 +26,17 @@ exports.resolve = function (source, file, config) {
 
 function opts(file, config) {
   return Object.assign({
-      // more closely matches Node (#333)
-      // plus 'mjs' for native modules! (#939)
-      extensions: ['.mjs', '.js', '.json', '.node'],
-    },
-    config,
-    {
-      // path.resolve will handle paths relative to CWD
-      basedir: path.dirname(path.resolve(file)),
-      packageFilter: packageFilter,
-
-    });
+    // more closely matches Node (#333)
+    // plus 'mjs' for native modules! (#939)
+    extensions: ['.mjs', '.js', '.json', '.node'],
+  },
+  config,
+  {
+    // path.resolve will handle paths relative to CWD
+    basedir: path.dirname(path.resolve(file)),
+    packageFilter: packageFilter,
+
+  });
 }
 
 function packageFilter(pkg) {
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index e75eb3d0dd..cd489005f7 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -1,14 +1,14 @@
-const findRoot = require('find-root')
-  , path = require('path')
-  , get = require('lodash/get')
-  , isEqual = require('lodash/isEqual')
-  , find = require('array-find')
-  , interpret = require('interpret')
-  , fs = require('fs')
-  , isCore = require('is-core-module')
-  , resolve = require('resolve')
-  , semver = require('semver')
-  , has = require('has');
+const findRoot = require('find-root');
+const path = require('path');
+const get = require('lodash/get');
+const isEqual = require('lodash/isEqual');
+const find = require('array-find');
+const interpret = require('interpret');
+const fs = require('fs');
+const isCore = require('is-core-module');
+const resolve = require('resolve');
+const semver = require('semver');
+const has = require('has');
 
 const log = require('debug')('eslint-plugin-import:resolver:webpack');
 
@@ -49,7 +49,7 @@ exports.resolve = function (source, file, settings) {
   let webpackConfig;
 
   const _configPath = get(settings, 'config');
-    /**
+  /**
      * Attempt to set the current working directory.
      * If none is passed, default to the `cwd` where the config is located.
      */
@@ -68,32 +68,32 @@ exports.resolve = function (source, file, settings) {
   // see if we've got a config path, a config object, an array of config objects or a config function
   if (!configPath || typeof configPath === 'string') {
 
-      // see if we've got an absolute path
-      if (!configPath || !path.isAbsolute(configPath)) {
-        // if not, find ancestral package.json and use its directory as base for the path
-        packageDir = findRoot(path.resolve(file));
-        if (!packageDir) throw new Error('package not found above ' + file);
-      }
+    // see if we've got an absolute path
+    if (!configPath || !path.isAbsolute(configPath)) {
+      // if not, find ancestral package.json and use its directory as base for the path
+      packageDir = findRoot(path.resolve(file));
+      if (!packageDir) throw new Error('package not found above ' + file);
+    }
 
-      configPath = findConfigPath(configPath, packageDir);
+    configPath = findConfigPath(configPath, packageDir);
 
-      log('Config path resolved to:', configPath);
-      if (configPath) {
-        try {
-          webpackConfig = require(configPath);
-        } catch(e) {
-          console.log('Error resolving webpackConfig', e);
-          throw e;
-        }
-      } else {
-        log('No config path found relative to', file, '; using {}');
-        webpackConfig = {};
+    log('Config path resolved to:', configPath);
+    if (configPath) {
+      try {
+        webpackConfig = require(configPath);
+      } catch(e) {
+        console.log('Error resolving webpackConfig', e);
+        throw e;
       }
+    } else {
+      log('No config path found relative to', file, '; using {}');
+      webpackConfig = {};
+    }
 
-      if (webpackConfig && webpackConfig.default) {
-        log('Using ES6 module "default" key instead of module.exports.');
-        webpackConfig = webpackConfig.default;
-      }
+    if (webpackConfig && webpackConfig.default) {
+      log('Using ES6 module "default" key instead of module.exports.');
+      webpackConfig = webpackConfig.default;
+    }
 
   } else {
     webpackConfig = configPath;
@@ -170,8 +170,8 @@ function getResolveSync(configPath, webpackConfig, cwd) {
 }
 
 function createResolveSync(configPath, webpackConfig, cwd) {
-  let webpackRequire
-    , basedir = null;
+  let webpackRequire;
+  let basedir = null;
 
   if (typeof configPath === 'string') {
     // This can be changed via the settings passed in when defining the resolver
diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js
index ac43733ffe..a70155f5cf 100644
--- a/resolvers/webpack/test/alias.js
+++ b/resolvers/webpack/test/alias.js
@@ -1,6 +1,6 @@
-const chai = require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai = require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const webpack = require('../index');
 
diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index aa69c7f6a9..a8b025ddca 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -1,6 +1,6 @@
-const chai =  require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai =  require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const resolve = require('../index').resolve;
 
@@ -14,12 +14,12 @@ const absoluteSettings = {
 describe("config", function () {
   it("finds webpack.config.js in parent directories", function () {
     expect(resolve('main-module', file)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
   it("finds absolute webpack.config.js files", function () {
     expect(resolve('foo', file, absoluteSettings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
+      .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
   });
 
   it("finds compile-to-js configs", function () {
@@ -44,7 +44,7 @@ describe("config", function () {
     };
 
     expect(resolve('main-module', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
   it("finds the config at option config-index", function () {
@@ -54,7 +54,7 @@ describe("config", function () {
     };
 
     expect(resolve('foo', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
+      .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
   });
 
   it("doesn't swallow config load errors (#435)", function () {
@@ -69,7 +69,7 @@ describe("config", function () {
       config: require(path.join(__dirname, 'files', 'some', 'absolute.path.webpack.config.js')),
     };
     expect(resolve('foo', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
+      .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
   });
 
   it("finds config object when config uses a path relative to working dir", function () {
@@ -77,7 +77,7 @@ describe("config", function () {
       config: './test/files/some/absolute.path.webpack.config.js',
     };
     expect(resolve('foo', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
+      .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
   });
 
   it("finds the first config with a resolve section when config is an array of config objects", function () {
@@ -86,7 +86,7 @@ describe("config", function () {
     };
 
     expect(resolve('main-module', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
+      .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
   it("finds the config at option config-index when config is an array of config objects", function () {
@@ -96,7 +96,7 @@ describe("config", function () {
     };
 
     expect(resolve('foo', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
+      .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
   });
 
   it('finds the config at option env when config is a function', function() {
@@ -108,7 +108,7 @@ describe("config", function () {
     };
 
     expect(resolve('bar', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
+      .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
   });
 
   it('finds the config at option env when config is an array of functions', function() {
@@ -120,7 +120,7 @@ describe("config", function () {
     };
 
     expect(resolve('bar', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
+      .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
   });
 
   it('passes argv to config when it is a function', function() {
@@ -132,7 +132,7 @@ describe("config", function () {
     };
 
     expect(resolve('baz', file, settings)).to.have.property('path')
-        .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'));
+      .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'));
   });
 
   it('passes a default empty argv object to config when it is a function', function() {
diff --git a/resolvers/webpack/test/example.js b/resolvers/webpack/test/example.js
index a36b5bb246..c311bc58c2 100644
--- a/resolvers/webpack/test/example.js
+++ b/resolvers/webpack/test/example.js
@@ -6,4 +6,4 @@ const file = path.join(__dirname, 'files', 'src', 'dummy.js');
 
 const webpackDir = path.join(__dirname, "different-package-location");
 
-console.log(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir}));
+console.log(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir }));
diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js
index 0ed123835a..da27e0b2eb 100644
--- a/resolvers/webpack/test/extensions.js
+++ b/resolvers/webpack/test/extensions.js
@@ -1,12 +1,12 @@
-const chai =  require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai =  require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const resolve = require('../index').resolve;
 
 
-const file = path.join(__dirname, 'files', 'dummy.js')
-  , extensions = path.join(__dirname, 'custom-extensions', 'dummy.js');
+const file = path.join(__dirname, 'files', 'dummy.js');
+const extensions = path.join(__dirname, 'custom-extensions', 'dummy.js');
 
 describe("extensions", function () {
   it("respects the defaults", function () {
diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js
index 97df9fe483..c7e7375e30 100644
--- a/resolvers/webpack/test/externals.js
+++ b/resolvers/webpack/test/externals.js
@@ -1,6 +1,6 @@
-const chai = require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai = require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const webpack = require('../index');
 
diff --git a/resolvers/webpack/test/fallback.js b/resolvers/webpack/test/fallback.js
index c6d0335aa4..6f21ebb58e 100644
--- a/resolvers/webpack/test/fallback.js
+++ b/resolvers/webpack/test/fallback.js
@@ -1,6 +1,6 @@
-const chai =  require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai =  require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const resolve = require('../index').resolve;
 
diff --git a/resolvers/webpack/test/loaders.js b/resolvers/webpack/test/loaders.js
index 9e157e0460..7e6576a7c6 100644
--- a/resolvers/webpack/test/loaders.js
+++ b/resolvers/webpack/test/loaders.js
@@ -1,6 +1,6 @@
-const chai =  require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai =  require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const resolve = require('../index').resolve;
 
diff --git a/resolvers/webpack/test/modules.js b/resolvers/webpack/test/modules.js
index ed7dc46094..777032fded 100644
--- a/resolvers/webpack/test/modules.js
+++ b/resolvers/webpack/test/modules.js
@@ -1,6 +1,6 @@
-const chai =  require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai =  require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const resolve = require('../index').resolve;
 
diff --git a/resolvers/webpack/test/packageMains.js b/resolvers/webpack/test/packageMains.js
index 9d6b46232a..f73665ebaa 100644
--- a/resolvers/webpack/test/packageMains.js
+++ b/resolvers/webpack/test/packageMains.js
@@ -1,6 +1,6 @@
-const chai = require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai = require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const webpack = require('../');
 
diff --git a/resolvers/webpack/test/plugins.js b/resolvers/webpack/test/plugins.js
index 5d5bdee93d..d052a57925 100644
--- a/resolvers/webpack/test/plugins.js
+++ b/resolvers/webpack/test/plugins.js
@@ -1,13 +1,13 @@
-const chai = require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai = require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const webpack = require('../index');
 
 const file = path.join(__dirname, 'files', 'dummy.js');
 
 describe("plugins", function () {
-  let resolved, aliasResolved;
+  let resolved; let aliasResolved;
 
   before(function () {
     resolved = webpack.resolve('./some/bar', file);
diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js
index 42719d5d15..3c938654a6 100644
--- a/resolvers/webpack/test/root.js
+++ b/resolvers/webpack/test/root.js
@@ -1,6 +1,6 @@
-const chai =  require('chai')
-  , expect = chai.expect
-  , path = require('path');
+const chai =  require('chai');
+const expect = chai.expect;
+const path = require('path');
 
 const resolve = require('../index').resolve;
 
@@ -35,10 +35,10 @@ describe("root", function () {
   });
   it("supports passing a different directory to load webpack from", function () {
     // Webpack should still be able to resolve the config here
-    expect(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir}))
+    expect(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
-    expect(resolve('typeahead', file, { config: "webpack.config.js", cwd: webpackDir}))
+    expect(resolve('typeahead', file, { config: "webpack.config.js", cwd: webpackDir }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
   });
diff --git a/scripts/copyMetafiles.js b/scripts/copyMetafiles.js
index 7518d4a5ba..b2aa03f313 100644
--- a/scripts/copyMetafiles.js
+++ b/scripts/copyMetafiles.js
@@ -3,20 +3,20 @@ import copyFileSync from 'fs-copy-file-sync';
 import resolverDirectories from './resolverDirectories';
 
 const files = [
-    'LICENSE',
-    '.npmrc',
+  'LICENSE',
+  '.npmrc',
 ];
 
 const directories = [
-    'memo-parser',
-    ...resolverDirectories,
-    'utils',
+  'memo-parser',
+  ...resolverDirectories,
+  'utils',
 ];
 
 for (const directory of directories) {
-    for (const file of files) {
-        const destination = path.join(directory, file);
-        copyFileSync(file, destination);
-        console.log(`${file} -> ${destination}`);
-    }
+  for (const file of files) {
+    const destination = path.join(directory, file);
+    copyFileSync(file, destination);
+    console.log(`${file} -> ${destination}`);
+  }
 }
diff --git a/scripts/testAll.js b/scripts/testAll.js
index 3a9f474ae7..fc30b1ac7d 100644
--- a/scripts/testAll.js
+++ b/scripts/testAll.js
@@ -4,17 +4,17 @@ import resolverDirectories from './resolverDirectories';
 
 const npmPath = npmWhich(__dirname).sync('npm');
 const spawnOptions = {
-    stdio: 'inherit',
+  stdio: 'inherit',
 };
 
 spawnSync(
-    npmPath,
-    ['test'],
-    Object.assign({ cwd: __dirname }, spawnOptions));
+  npmPath,
+  ['test'],
+  Object.assign({ cwd: __dirname }, spawnOptions));
 
 for (const resolverDir of resolverDirectories) {
-    spawnSync(
-        npmPath,
-        ['test'],
-        Object.assign({ cwd: resolverDir }, spawnOptions));
+  spawnSync(
+    npmPath,
+    ['test'],
+    Object.assign({ cwd: resolverDir }, spawnOptions));
 }
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 1924ecc025..45c92d8336 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -90,8 +90,8 @@ export default class ExportMap {
     if (this.namespace.has(name)) return { found: true, path: [this] };
 
     if (this.reexports.has(name)) {
-      const reexports = this.reexports.get(name)
-          , imported = reexports.getImport();
+      const reexports = this.reexports.get(name);
+      const imported = reexports.getImport();
 
       // if import is ignored, return explicit 'null'
       if (imported == null) return { found: true, path: [this] };
@@ -134,8 +134,8 @@ export default class ExportMap {
     if (this.namespace.has(name)) return this.namespace.get(name);
 
     if (this.reexports.has(name)) {
-      const reexports = this.reexports.get(name)
-          , imported = reexports.getImport();
+      const reexports = this.reexports.get(name);
+      const imported = reexports.getImport();
 
       // if import is ignored, return explicit 'null'
       if (imported == null) return null;
@@ -191,8 +191,8 @@ export default class ExportMap {
       node: declaration.source,
       message: `Parse errors in imported module '${declaration.source.value}': ` +
                   `${this.errors
-                        .map(e => `${e.message} (${e.lineNumber}:${e.column})`)
-                        .join(', ')}`,
+                    .map(e => `${e.message} (${e.lineNumber}:${e.column})`)
+                    .join(', ')}`,
     });
   }
 }
@@ -462,7 +462,7 @@ ExportMap.parse = function (path, content, context) {
         const jsonText = fs.readFileSync(tsConfigInfo.tsConfigPath).toString();
         if (!parseConfigFileTextToJson) {
           // this is because projects not using TypeScript won't have typescript installed
-          ({parseConfigFileTextToJson} = require('typescript'));
+          ({ parseConfigFileTextToJson } = require('typescript'));
         }
         const tsConfig = parseConfigFileTextToJson(tsConfigInfo.tsConfigPath, jsonText).config;
         return tsConfig.compilerOptions.esModuleInterop;
@@ -502,24 +502,24 @@ ExportMap.parse = function (path, content, context) {
       // capture declaration
       if (n.declaration != null) {
         switch (n.declaration.type) {
-          case 'FunctionDeclaration':
-          case 'ClassDeclaration':
-          case 'TypeAlias': // flowtype with babel-eslint parser
-          case 'InterfaceDeclaration':
-          case 'DeclareFunction':
-          case 'TSDeclareFunction':
-          case 'TSEnumDeclaration':
-          case 'TSTypeAliasDeclaration':
-          case 'TSInterfaceDeclaration':
-          case 'TSAbstractClassDeclaration':
-          case 'TSModuleDeclaration':
-            m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n));
-            break;
-          case 'VariableDeclaration':
-            n.declaration.declarations.forEach((d) =>
-              recursivePatternCapture(d.id,
-                id => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n))));
-            break;
+        case 'FunctionDeclaration':
+        case 'ClassDeclaration':
+        case 'TypeAlias': // flowtype with babel-eslint parser
+        case 'InterfaceDeclaration':
+        case 'DeclareFunction':
+        case 'TSDeclareFunction':
+        case 'TSEnumDeclaration':
+        case 'TSTypeAliasDeclaration':
+        case 'TSInterfaceDeclaration':
+        case 'TSAbstractClassDeclaration':
+        case 'TSModuleDeclaration':
+          m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n));
+          break;
+        case 'VariableDeclaration':
+          n.declaration.declarations.forEach((d) =>
+            recursivePatternCapture(d.id,
+              id => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n))));
+          break;
         }
       }
 
@@ -529,24 +529,24 @@ ExportMap.parse = function (path, content, context) {
         let local;
 
         switch (s.type) {
-          case 'ExportDefaultSpecifier':
-            if (!n.source) return;
-            local = 'default';
-            break;
-          case 'ExportNamespaceSpecifier':
-            m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
-              get() { return resolveImport(nsource); },
-            }));
+        case 'ExportDefaultSpecifier':
+          if (!n.source) return;
+          local = 'default';
+          break;
+        case 'ExportNamespaceSpecifier':
+          m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
+            get() { return resolveImport(nsource); },
+          }));
+          return;
+        case 'ExportSpecifier':
+          if (!n.source) {
+            m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local));
             return;
-          case 'ExportSpecifier':
-            if (!n.source) {
-              m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local));
-              return;
-            }
-            // else falls through
-          default:
-            local = s.local.name;
-            break;
+          }
+          // else falls through
+        default:
+          local = s.local.name;
+          break;
         }
 
         // todo: JSDoc
@@ -645,34 +645,34 @@ function thunkFor(p, context) {
  */
 export function recursivePatternCapture(pattern, callback) {
   switch (pattern.type) {
-    case 'Identifier': // base case
-      callback(pattern);
-      break;
-
-    case 'ObjectPattern':
-      pattern.properties.forEach(p => {
-        if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
-          callback(p.argument);
-          return;
-        }
-        recursivePatternCapture(p.value, callback);
-      });
-      break;
+  case 'Identifier': // base case
+    callback(pattern);
+    break;
+
+  case 'ObjectPattern':
+    pattern.properties.forEach(p => {
+      if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
+        callback(p.argument);
+        return;
+      }
+      recursivePatternCapture(p.value, callback);
+    });
+    break;
 
-    case 'ArrayPattern':
-      pattern.elements.forEach((element) => {
-        if (element == null) return;
-        if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
-          callback(element.argument);
-          return;
-        }
-        recursivePatternCapture(element, callback);
-      });
-      break;
+  case 'ArrayPattern':
+    pattern.elements.forEach((element) => {
+      if (element == null) return;
+      if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
+        callback(element.argument);
+        return;
+      }
+      recursivePatternCapture(element, callback);
+    });
+    break;
 
-    case 'AssignmentPattern':
-      callback(pattern.left);
-      break;
+  case 'AssignmentPattern':
+    callback(pattern.left);
+    break;
   }
 }
 
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 473d8b603a..d6a469a255 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -19,43 +19,43 @@ const properties = {
 
 function buildProperties(context) {
 
-    const result = {
-      defaultConfig: 'never',
-      pattern: {},
-      ignorePackages: false,
-    };
-
-    context.options.forEach(obj => {
-
-      // If this is a string, set defaultConfig to its value
-      if (typeof obj === 'string') {
-        result.defaultConfig = obj;
-        return;
-      }
-
-      // If this is not the new structure, transfer all props to result.pattern
-      if (obj.pattern === undefined && obj.ignorePackages === undefined) {
-        Object.assign(result.pattern, obj);
-        return;
-      }
+  const result = {
+    defaultConfig: 'never',
+    pattern: {},
+    ignorePackages: false,
+  };
+
+  context.options.forEach(obj => {
+
+    // If this is a string, set defaultConfig to its value
+    if (typeof obj === 'string') {
+      result.defaultConfig = obj;
+      return;
+    }
 
-      // If pattern is provided, transfer all props
-      if (obj.pattern !== undefined) {
-        Object.assign(result.pattern, obj.pattern);
-      }
+    // If this is not the new structure, transfer all props to result.pattern
+    if (obj.pattern === undefined && obj.ignorePackages === undefined) {
+      Object.assign(result.pattern, obj);
+      return;
+    }
 
-      // If ignorePackages is provided, transfer it to result
-      if (obj.ignorePackages !== undefined) {
-        result.ignorePackages = obj.ignorePackages;
-      }
-    });
+    // If pattern is provided, transfer all props
+    if (obj.pattern !== undefined) {
+      Object.assign(result.pattern, obj.pattern);
+    }
 
-    if (result.defaultConfig === 'ignorePackages') {
-      result.defaultConfig = 'always';
-      result.ignorePackages = true;
+    // If ignorePackages is provided, transfer it to result
+    if (obj.ignorePackages !== undefined) {
+      result.ignorePackages = obj.ignorePackages;
     }
+  });
+
+  if (result.defaultConfig === 'ignorePackages') {
+    result.defaultConfig = 'always';
+    result.ignorePackages = true;
+  }
 
-    return result;
+  return result;
 }
 
 module.exports = {
diff --git a/src/rules/first.js b/src/rules/first.js
index 5018544473..4d909bea3e 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -24,11 +24,11 @@ module.exports = {
 
     return {
       'Program': function (n) {
-        const body = n.body
-            , absoluteFirst = context.options[0] === 'absolute-first'
-            , message = 'Import in body of module; reorder to top.'
-            , sourceCode = context.getSourceCode()
-            , originSourceCode = sourceCode.getText();
+        const body = n.body;
+        const absoluteFirst = context.options[0] === 'absolute-first';
+        const message = 'Import in body of module; reorder to top.';
+        const sourceCode = context.getSourceCode();
+        const originSourceCode = sourceCode.getText();
         let nonImportCount = 0;
         let anyExpressions = false;
         let anyRelative = false;
@@ -81,11 +81,11 @@ module.exports = {
         });
         if (!errorInfos.length) return;
         errorInfos.forEach(function (errorInfo, index) {
-          const node = errorInfo.node
-              , infos = {
-                node,
-                message,
-              };
+          const node = errorInfo.node;
+          const infos = {
+            node,
+            message,
+          };
           if (index < lastSortNodesIndex) {
             infos.fix = function (fixer) {
               return fixer.insertTextAfter(node, '');
@@ -94,27 +94,27 @@ module.exports = {
             const sortNodes = errorInfos.slice(0, lastSortNodesIndex + 1);
             infos.fix = function (fixer) {
               const removeFixers = sortNodes.map(function (_errorInfo) {
-                    return fixer.removeRange(_errorInfo.range);
-                  })
-                  , range = [0, removeFixers[removeFixers.length - 1].range[1]];
+                return fixer.removeRange(_errorInfo.range);
+              });
+              const range = [0, removeFixers[removeFixers.length - 1].range[1]];
               let insertSourceCode = sortNodes.map(function (_errorInfo) {
-                    const nodeSourceCode = String.prototype.slice.apply(
-                      originSourceCode, _errorInfo.range
-                    );
-                    if (/\S/.test(nodeSourceCode[0])) {
-                      return '\n' + nodeSourceCode;
-                    }
-                    return nodeSourceCode;
-                  }).join('')
-                , insertFixer = null
-                , replaceSourceCode = '';
+                const nodeSourceCode = String.prototype.slice.apply(
+                  originSourceCode, _errorInfo.range
+                );
+                if (/\S/.test(nodeSourceCode[0])) {
+                  return '\n' + nodeSourceCode;
+                }
+                return nodeSourceCode;
+              }).join('');
+              let insertFixer = null;
+              let replaceSourceCode = '';
               if (!lastLegalImp) {
-                  insertSourceCode =
+                insertSourceCode =
                     insertSourceCode.trim() + insertSourceCode.match(/^(\s+)/)[0];
               }
               insertFixer = lastLegalImp ?
-                            fixer.insertTextAfter(lastLegalImp, insertSourceCode) :
-                            fixer.insertTextBefore(body[0], insertSourceCode);
+                fixer.insertTextAfter(lastLegalImp, insertSourceCode) :
+                fixer.insertTextBefore(body[0], insertSourceCode);
               const fixers = [insertFixer].concat(removeFixers);
               fixers.forEach(function (computedFixer, i) {
                 replaceSourceCode += (originSourceCode.slice(
diff --git a/src/rules/max-dependencies.js b/src/rules/max-dependencies.js
index 74b125ec5c..4efff26824 100644
--- a/src/rules/max-dependencies.js
+++ b/src/rules/max-dependencies.js
@@ -4,7 +4,7 @@ import docsUrl from '../docsUrl';
 const DEFAULT_MAX = 10;
 
 const countDependencies = (dependencies, lastNode, context) => {
-  const {max} = context.options[0] || { max: DEFAULT_MAX };
+  const { max } = context.options[0] || { max: DEFAULT_MAX };
 
   if (dependencies.size > max) {
     context.report(
diff --git a/src/rules/named.js b/src/rules/named.js
index b1c2699c1a..c4ce5ea915 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -20,7 +20,7 @@ module.exports = {
       }
 
       if (!node.specifiers
-            .some(function (im) { return im.type === type; })) {
+        .some(function (im) { return im.type === type; })) {
         return; // no named imports/exports
       }
 
@@ -58,14 +58,14 @@ module.exports = {
 
     return {
       'ImportDeclaration': checkSpecifiers.bind( null
-                                               , 'imported'
-                                               , 'ImportSpecifier'
-                                               ),
+        , 'imported'
+        , 'ImportSpecifier'
+      ),
 
       'ExportNamedDeclaration': checkSpecifiers.bind( null
-                                                    , 'local'
-                                                    , 'ExportSpecifier'
-                                                    ),
+        , 'local'
+        , 'ExportSpecifier'
+      ),
     };
 
   },
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 579c1bfb2c..a23cfeac88 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -56,25 +56,25 @@ module.exports = {
 
           for (const specifier of declaration.specifiers) {
             switch (specifier.type) {
-              case 'ImportNamespaceSpecifier':
-                if (!imports.size) {
-                  context.report(
-                    specifier,
-                    `No exported names found in module '${declaration.source.value}'.`
-                  );
-                }
-                namespaces.set(specifier.local.name, imports);
-                break;
-              case 'ImportDefaultSpecifier':
-              case 'ImportSpecifier': {
-                const meta = imports.get(
-                  // default to 'default' for default http://i.imgur.com/nj6qAWy.jpg
-                  specifier.imported ? specifier.imported.name : 'default'
+            case 'ImportNamespaceSpecifier':
+              if (!imports.size) {
+                context.report(
+                  specifier,
+                  `No exported names found in module '${declaration.source.value}'.`
                 );
-                if (!meta || !meta.namespace) { break; }
-                namespaces.set(specifier.local.name, meta.namespace);
-                break;
               }
+              namespaces.set(specifier.local.name, imports);
+              break;
+            case 'ImportDefaultSpecifier':
+            case 'ImportSpecifier': {
+              const meta = imports.get(
+                // default to 'default' for default http://i.imgur.com/nj6qAWy.jpg
+                specifier.imported ? specifier.imported.name : 'default'
+              );
+              if (!meta || !meta.namespace) { break; }
+              namespaces.set(specifier.local.name, meta.namespace);
+              break;
+            }
             }
           }
         }
@@ -109,10 +109,10 @@ module.exports = {
         if (declaredScope(context, dereference.object.name) !== 'module') return;
 
         if (dereference.parent.type === 'AssignmentExpression' && dereference.parent.left === dereference) {
-            context.report(
-              dereference.parent,
-              `Assignment to member of namespace '${dereference.object.name}'.`
-            );
+          context.report(
+            dereference.parent,
+            `Assignment to member of namespace '${dereference.object.name}'.`
+          );
         }
 
         // go deep
@@ -202,15 +202,15 @@ module.exports = {
         testKey(id, namespaces.get(init.name));
       },
 
-      JSXMemberExpression({object, property}) {
-         if (!namespaces.has(object.name)) return;
-         const namespace = namespaces.get(object.name);
-         if (!namespace.has(property.name)) {
-           context.report({
-             node: property,
-             message: makeMessage(property, [object.name]),
-           });
-         }
+      JSXMemberExpression({ object, property }) {
+        if (!namespaces.has(object.name)) return;
+        const namespace = namespaces.get(object.name);
+        if (!namespace.has(property.name)) {
+          context.report({
+            node: property,
+            message: makeMessage(property, [object.name]),
+          });
+        }
       },
     };
   },
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 05c7e24273..1e698f13e5 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -14,25 +14,25 @@ const log = debug('eslint-plugin-import:rules:newline-after-import');
 //------------------------------------------------------------------------------
 
 function containsNodeOrEqual(outerNode, innerNode) {
-    return outerNode.range[0] <= innerNode.range[0] && outerNode.range[1] >= innerNode.range[1];
+  return outerNode.range[0] <= innerNode.range[0] && outerNode.range[1] >= innerNode.range[1];
 }
 
 function getScopeBody(scope) {
-    if (scope.block.type === 'SwitchStatement') {
-      log('SwitchStatement scopes not supported');
-      return null;
-    }
+  if (scope.block.type === 'SwitchStatement') {
+    log('SwitchStatement scopes not supported');
+    return null;
+  }
 
-    const { body } = scope.block;
-    if (body && body.type === 'BlockStatement') {
-        return body.body;
-    }
+  const { body } = scope.block;
+  if (body && body.type === 'BlockStatement') {
+    return body.body;
+  }
 
-    return body;
+  return body;
 }
 
 function findNodeIndexInScopeBody(body, nodeToFind) {
-    return body.findIndex((node) => containsNodeOrEqual(node, nodeToFind));
+  return body.findIndex((node) => containsNodeOrEqual(node, nodeToFind));
 }
 
 function getLineDifference(node, nextNode) {
@@ -116,18 +116,18 @@ after ${type} statement not followed by another ${type}.`,
     }
 
     function checkImport(node) {
-        const { parent } = node;
-        const nodePosition = parent.body.indexOf(node);
-        const nextNode = parent.body[nodePosition + 1];
+      const { parent } = node;
+      const nodePosition = parent.body.indexOf(node);
+      const nextNode = parent.body[nodePosition + 1];
         
-        // skip "export import"s
-        if (node.type === 'TSImportEqualsDeclaration' && node.isExport) {
-          return;
-        }
+      // skip "export import"s
+      if (node.type === 'TSImportEqualsDeclaration' && node.isExport) {
+        return;
+      }
 
-        if (nextNode && nextNode.type !== 'ImportDeclaration' && (nextNode.type !== 'TSImportEqualsDeclaration' || nextNode.isExport)) {
-          checkForNewLine(node, nextNode, 'import');
-        }
+      if (nextNode && nextNode.type !== 'ImportDeclaration' && (nextNode.type !== 'TSImportEqualsDeclaration' || nextNode.isExport)) {
+        checkForNewLine(node, nextNode, 'import');
+      }
     }
 
     return {
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index c88c602720..7b38739ec8 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -5,8 +5,8 @@
 
 import docsUrl from '../docsUrl';
 
-const EXPORT_MESSAGE = 'Expected "export" or "export default"'
-    , IMPORT_MESSAGE = 'Expected "import" instead of "require()"';
+const EXPORT_MESSAGE = 'Expected "export" or "export default"';
+const IMPORT_MESSAGE = 'Expected "import" instead of "require()"';
 
 function normalizeLegacyOptions(options) {
   if (options.indexOf('allow-primitive-modules') >= 0) {
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index cbc8dad8ac..21a428179d 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -62,9 +62,9 @@ module.exports = {
         return;  // no-self-import territory
       }
 
-      const untraversed = [{mget: () => imported, route:[]}];
+      const untraversed = [{ mget: () => imported, route:[] }];
       const traversed = new Set();
-      function detectCycle({mget, route}) {
+      function detectCycle({ mget, route }) {
         const m = mget();
         if (m == null) return;
         if (traversed.has(m.path)) return;
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index b597c320f6..cb7c0bb724 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -16,23 +16,23 @@ module.exports = {
     }
 
     const preferNamed = 'Prefer named exports.';
-    const noAliasDefault = ({local}) =>
+    const noAliasDefault = ({ local }) =>
       `Do not alias \`${local.name}\` as \`default\`. Just export ` +
       `\`${local.name}\` itself instead.`;
 
     return {
       ExportDefaultDeclaration(node) {
-        context.report({node, message: preferNamed});
+        context.report({ node, message: preferNamed });
       },
 
       ExportNamedDeclaration(node) {
         node.specifiers.forEach(specifier => {
           if (specifier.type === 'ExportDefaultSpecifier' &&
               specifier.exported.name === 'default') {
-            context.report({node, message: preferNamed});
+            context.report({ node, message: preferNamed });
           } else if (specifier.type === 'ExportSpecifier' &&
               specifier.exported.name === 'default') {
-            context.report({node, message: noAliasDefault(specifier)});
+            context.report({ node, message: noAliasDefault(specifier) });
           }
         });
       },
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index e9788f27c0..4360ee787b 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -25,8 +25,8 @@ module.exports = {
   },
 
   create: function (context) {
-    const deprecated = new Map()
-        , namespaces = new Map();
+    const deprecated = new Map();
+    const namespaces = new Map();
 
     function checkSpecifiers(node) {
       if (node.type !== 'ImportDeclaration') return;
@@ -47,27 +47,27 @@ module.exports = {
       }
 
       node.specifiers.forEach(function (im) {
-        let imported, local;
+        let imported; let local;
         switch (im.type) {
 
 
-          case 'ImportNamespaceSpecifier':{
-            if (!imports.size) return;
-            namespaces.set(im.local.name, imports);
-            return;
-          }
+        case 'ImportNamespaceSpecifier':{
+          if (!imports.size) return;
+          namespaces.set(im.local.name, imports);
+          return;
+        }
 
-          case 'ImportDefaultSpecifier':
-            imported = 'default';
-            local = im.local.name;
-            break;
+        case 'ImportDefaultSpecifier':
+          imported = 'default';
+          local = im.local.name;
+          break;
 
-          case 'ImportSpecifier':
-            imported = im.imported.name;
-            local = im.local.name;
-            break;
+        case 'ImportSpecifier':
+          imported = im.imported.name;
+          local = im.local.name;
+          break;
 
-          default: return; // can't handle this one
+        default: return; // can't handle this one
         }
 
         // unknown thing can't be deprecated
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 7777596718..af8bcb87db 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -68,7 +68,7 @@ function getDependencies(context, packageDir) {
       Object.assign(
         packageContent,
         extractDepFields(
-          readPkgUp.sync({cwd: context.getFilename(), normalize: false}).pkg
+          readPkgUp.sync({ cwd: context.getFilename(), normalize: false }).pkg
         )
       );
     }
@@ -209,6 +209,6 @@ module.exports = {
 
     return moduleVisitor(node => {
       reportIfMissing(context, deps, depsOptions, node, node.value);
-    }, {commonjs: true});
+    }, { commonjs: true });
   },
 };
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index 7c35638f98..a1635bb7ae 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -11,13 +11,13 @@ module.exports = {
 
   create: function (context) {
     function checkDeclaration(node) {
-      const {kind} = node;
+      const { kind } = node;
       if (kind === 'var' || kind === 'let') {
         context.report(node, `Exporting mutable '${kind}' binding, use 'const' instead.`);
       }
     }
 
-    function checkDeclarationsInScope({variables}, name) {
+    function checkDeclarationsInScope({ variables }, name) {
       for (const variable of variables) {
         if (variable.name === name) {
           for (const def of variable.defs) {
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index 754359a124..09bb5e34a3 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -44,7 +44,7 @@ module.exports = {
 
     function storePropertyLookup(objectName, propName, node) {
       const lookups = allPropertyLookups.get(objectName) || [];
-      lookups.push({node, propName});
+      lookups.push({ node, propName });
       allPropertyLookups.set(objectName, lookups);
     }
 
@@ -74,7 +74,7 @@ module.exports = {
         const fileImport = fileImports.get(objectName);
         if (fileImport == null) return;
 
-        for (const {propName, node} of lookups) {
+        for (const { propName, node } of lookups) {
           // the default import can have a "default" property
           if (propName === 'default') continue;
           if (!fileImport.exportMap.namespace.has(propName)) continue;
diff --git a/src/rules/no-named-export.js b/src/rules/no-named-export.js
index c6e3ca57e3..bb586ead00 100644
--- a/src/rules/no-named-export.js
+++ b/src/rules/no-named-export.js
@@ -17,17 +17,17 @@ module.exports = {
 
     return {
       ExportAllDeclaration(node) {
-        context.report({node, message});
+        context.report({ node, message });
       },
 
       ExportNamedDeclaration(node) {
         if (node.specifiers.length === 0) {
-          return context.report({node, message});
+          return context.report({ node, message });
         }
 
         const someNamed = node.specifiers.some(specifier => specifier.exported.name !== 'default');
         if (someNamed) {
-          context.report({node, message});
+          context.report({ node, message });
         }
       },
     };
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 71732437eb..55acfc930e 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -69,44 +69,44 @@ module.exports = {
     }
 
     function checkForRestrictedImportPath(importPath, node) {
-        const absoluteImportPath = resolve(importPath, context);
+      const absoluteImportPath = resolve(importPath, context);
 
-        if (!absoluteImportPath) {
+      if (!absoluteImportPath) {
+        return;
+      }
+
+      matchingZones.forEach((zone) => {
+        const exceptionPaths = zone.except || [];
+        const absoluteFrom = path.resolve(basePath, zone.from);
+
+        if (!containsPath(absoluteImportPath, absoluteFrom)) {
+          return;
+        }
+
+        const absoluteExceptionPaths = exceptionPaths.map((exceptionPath) =>
+          path.resolve(absoluteFrom, exceptionPath)
+        );
+        const hasValidExceptionPaths = absoluteExceptionPaths
+          .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
+
+        if (!hasValidExceptionPaths) {
+          reportInvalidExceptionPath(node);
           return;
         }
 
-        matchingZones.forEach((zone) => {
-          const exceptionPaths = zone.except || [];
-          const absoluteFrom = path.resolve(basePath, zone.from);
-
-          if (!containsPath(absoluteImportPath, absoluteFrom)) {
-            return;
-          }
-
-          const absoluteExceptionPaths = exceptionPaths.map((exceptionPath) =>
-            path.resolve(absoluteFrom, exceptionPath)
-          );
-          const hasValidExceptionPaths = absoluteExceptionPaths
-            .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
-
-          if (!hasValidExceptionPaths) {
-            reportInvalidExceptionPath(node);
-            return;
-          }
-
-          const pathIsExcepted = absoluteExceptionPaths
-            .some((absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath));
-
-          if (pathIsExcepted) {
-            return;
-          }
-
-          context.report({
-            node,
-            message: `Unexpected path "{{importPath}}" imported in restricted zone.${zone.message ? ` ${zone.message}` : ''}`,
-            data: { importPath },
-          });
+        const pathIsExcepted = absoluteExceptionPaths
+          .some((absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath));
+
+        if (pathIsExcepted) {
+          return;
+        }
+
+        context.report({
+          node,
+          message: `Unexpected path "{{importPath}}" imported in restricted zone.${zone.message ? ` ${zone.message}` : ''}`,
+          data: { importPath },
         });
+      });
     }
 
     return {
diff --git a/src/rules/no-self-import.js b/src/rules/no-self-import.js
index a90ba13fbe..6285c28c04 100644
--- a/src/rules/no-self-import.js
+++ b/src/rules/no-self-import.js
@@ -13,8 +13,8 @@ function isImportingSelf(context, node, requireName) {
   // If the input is from stdin, this test can't fail
   if (filePath !== '<text>' && filePath === resolve(requireName, context)) {
     context.report({
-        node,
-        message: 'Module imports itself.',
+      node,
+      message: 'Module imports itself.',
     });
   }
 }
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 596613889d..16299ac564 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -324,20 +324,20 @@ const newDefaultImportExists = specifiers =>
   specifiers.some(({ type }) => type === IMPORT_DEFAULT_SPECIFIER);
 
 const fileIsInPkg = file => {
-  const { path, pkg } = readPkgUp.sync({cwd: file, normalize: false});
+  const { path, pkg } = readPkgUp.sync({ cwd: file, normalize: false });
   const basePath = dirname(path);
 
   const checkPkgFieldString = pkgField => {
     if (join(basePath, pkgField) === file) {
-        return true;
-      }
+      return true;
+    }
   };
 
   const checkPkgFieldObject = pkgField => {
-      const pkgFieldFiles = values(pkgField).map(value => join(basePath, value));
-      if (includes(pkgFieldFiles, file)) {
-        return true;
-      }
+    const pkgFieldFiles = values(pkgField).map(value => join(basePath, value));
+    if (includes(pkgFieldFiles, file)) {
+      return true;
+    }
   };
 
   const checkPkgField = pkgField => {
@@ -652,8 +652,8 @@ module.exports = {
         value.forEach(val => {
           if (val !== IMPORT_NAMESPACE_SPECIFIER &&
               val !== IMPORT_DEFAULT_SPECIFIER) {
-               oldImports.set(val, key);
-             }
+            oldImports.set(val, key);
+          }
         });
       });
 
@@ -892,7 +892,7 @@ module.exports = {
       },
       'ExportNamedDeclaration': node => {
         node.specifiers.forEach(specifier => {
-            checkUsage(node, specifier.exported.name);
+          checkUsage(node, specifier.exported.name);
         });
         forEachDeclarationIdentifier(node.declaration, (name) => {
           checkUsage(node, name);
diff --git a/src/rules/order.js b/src/rules/order.js
index 2532a21de3..bad382945c 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -340,7 +340,7 @@ function isModuleLevelRequire(node) {
   while ( 
     (n.parent.type === 'MemberExpression' && n.parent.object === n) ||
     (n.parent.type === 'CallExpression' && n.parent.callee === n)
-   ) {
+  ) {
     n = n.parent;
   }
   return (
@@ -500,7 +500,7 @@ function getAlphabetizeConfig(options) {
   const order = alphabetize.order || 'ignore';
   const caseInsensitive = alphabetize.caseInsensitive || false;
 
-  return {order, caseInsensitive};
+  return { order, caseInsensitive };
 }
 
 module.exports = {
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 33ef05c473..523b0ef4cf 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -80,8 +80,8 @@ describe('ExportMap', function () {
   });
 
   it('finds exports for an ES7 module with babel-eslint', function () {
-    const path = getFilename('jsx/FooES7.js')
-        , contents = fs.readFileSync(path, { encoding: 'utf8' });
+    const path = getFilename('jsx/FooES7.js');
+    const contents = fs.readFileSync(path, { encoding: 'utf8' });
     const imports = ExportMap.parse(
       path,
       contents,
@@ -100,8 +100,8 @@ describe('ExportMap', function () {
       context('deprecated imports', function () {
         let imports;
         before('parse file', function () {
-          const path = getFilename('deprecated.js')
-              , contents = fs.readFileSync(path, { encoding: 'utf8' }).replace(/[\r]\n/g, lineEnding);
+          const path = getFilename('deprecated.js');
+          const contents = fs.readFileSync(path, { encoding: 'utf8' }).replace(/[\r]\n/g, lineEnding);
           imports = ExportMap.parse(path, contents, parseContext);
 
           // sanity checks
@@ -169,8 +169,8 @@ describe('ExportMap', function () {
       context('full module', function () {
         let imports;
         before('parse file', function () {
-          const path = getFilename('deprecated-file.js')
-              , contents = fs.readFileSync(path, { encoding: 'utf8' });
+          const path = getFilename('deprecated-file.js');
+          const contents = fs.readFileSync(path, { encoding: 'utf8' });
           imports = ExportMap.parse(path, contents, parseContext);
 
           // sanity checks
@@ -231,8 +231,8 @@ describe('ExportMap', function () {
     const babelContext = { parserPath: 'babel-eslint', parserOptions: { ecmaVersion: 2015, sourceType: 'module' }, settings: {} };
 
     it('works with espree & traditional namespace exports', function () {
-      const path = getFilename('deep/a.js')
-          , contents = fs.readFileSync(path, { encoding: 'utf8' });
+      const path = getFilename('deep/a.js');
+      const contents = fs.readFileSync(path, { encoding: 'utf8' });
       const a = ExportMap.parse(path, contents, espreeContext);
       expect(a.errors).to.be.empty;
       expect(a.get('b').namespace).to.exist;
@@ -240,8 +240,8 @@ describe('ExportMap', function () {
     });
 
     it('captures namespace exported as default', function () {
-      const path = getFilename('deep/default.js')
-          , contents = fs.readFileSync(path, { encoding: 'utf8' });
+      const path = getFilename('deep/default.js');
+      const contents = fs.readFileSync(path, { encoding: 'utf8' });
       const def = ExportMap.parse(path, contents, espreeContext);
       expect(def.errors).to.be.empty;
       expect(def.get('default').namespace).to.exist;
@@ -249,8 +249,8 @@ describe('ExportMap', function () {
     });
 
     it('works with babel-eslint & ES7 namespace exports', function () {
-      const path = getFilename('deep-es7/a.js')
-          , contents = fs.readFileSync(path, { encoding: 'utf8' });
+      const path = getFilename('deep-es7/a.js');
+      const contents = fs.readFileSync(path, { encoding: 'utf8' });
       const a = ExportMap.parse(path, contents, babelContext);
       expect(a.errors).to.be.empty;
       expect(a.get('b').namespace).to.exist;
@@ -266,8 +266,8 @@ describe('ExportMap', function () {
       fs.writeFileSync(getFilename('deep/cache-2.js'),
         fs.readFileSync(getFilename('deep/cache-2a.js')));
 
-      const path = getFilename('deep/cache-1.js')
-          , contents = fs.readFileSync(path, { encoding: 'utf8' });
+      const path = getFilename('deep/cache-1.js');
+      const contents = fs.readFileSync(path, { encoding: 'utf8' });
       a = ExportMap.parse(path, contents, espreeContext);
       expect(a.errors).to.be.empty;
 
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index ddac19c9c2..5eb655e552 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -1,7 +1,7 @@
 import { expect } from 'chai';
 import * as path from 'path';
 
-import importType, {isExternalModule, isScopedModule} from 'core/importType';
+import importType, { isExternalModule, isScopedModule } from 'core/importType';
 
 import { testContext, testFilePath } from '../utils';
 
diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index 4535a7d933..a9c9ba5849 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -37,8 +37,8 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
     expect(parseSpy.args[0][1], 'custom parser to clone the parserOptions object').to.not.equal(parserOptions);
     expect(parseSpy.args[0][1], 'custom parser to get ecmaFeatures in parserOptions which is a clone of ecmaFeatures passed in')
       .to.have.property('ecmaFeatures')
-        .that.is.eql(parserOptions.ecmaFeatures)
-        .and.is.not.equal(parserOptions.ecmaFeatures);
+      .that.is.eql(parserOptions.ecmaFeatures)
+      .and.is.not.equal(parserOptions.ecmaFeatures);
     expect(parseSpy.args[0][1], 'custom parser to get parserOptions.attachComment equal to true').to.have.property('attachComment', true);
     expect(parseSpy.args[0][1], 'custom parser to get parserOptions.tokens equal to true').to.have.property('tokens', true);
     expect(parseSpy.args[0][1], 'custom parser to get parserOptions.range equal to true').to.have.property('range', true);
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index 2e713846a3..b8deaa6d25 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -21,32 +21,32 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'));
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(utils.testFilePath('./bar.jsx'));
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+    )).to.equal(undefined);
 
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+    )).to.equal(undefined);
   });
 
   it('resolves via a custom resolver with interface version 1 assumed if not specified', function () {
     const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'));
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(utils.testFilePath('./bar.jsx'));
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+    )).to.equal(undefined);
 
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+    )).to.equal(undefined);
   });
 
   it('resolves via a custom resolver with interface version 2', function () {
@@ -57,21 +57,21 @@ describe('resolve', function () {
     };
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'));
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(utils.testFilePath('./bar.jsx'));
 
     testContextReports.length = 0;
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+    )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>');
     expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
 
     testContextReports.length = 0;
     expect(resolve( '../files/not-found'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+    )).to.equal(undefined);
     expect(testContextReports.length).to.equal(0);
   });
 
@@ -79,32 +79,32 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'));
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
   it('respects import/resolver as object', function () {
     const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'));
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
   it('respects import/resolver as array of objects', function () {
     const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'));
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
   it('finds resolvers from the source files rather than eslint-module-utils', function () {
     const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } });
 
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                      )).to.equal(utils.testFilePath('./bar.jsx'));
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
   it('reports invalid import/resolver config', function () {
@@ -116,8 +116,8 @@ describe('resolve', function () {
 
     testContextReports.length = 0;
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config');
     expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
@@ -132,19 +132,19 @@ describe('resolve', function () {
     };
     testContextReports.length = 0;
     expect(resolve( '../files/foo'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+    )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`);
     expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
   });
 
   it('respects import/resolve extensions', function () {
-    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }});
+    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] } });
 
     expect(resolve( './jsx/MyCoolComponent'
-                      , testContext,
-                      )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx'));
+      , testContext,
+    )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx'));
   });
 
   it('reports load exception in a user resolver', function () {
@@ -155,8 +155,8 @@ describe('resolve', function () {
     };
 
     expect(resolve( '../files/exception'
-                      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
-                    )).to.equal(undefined);
+      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+    )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>');
     expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
@@ -165,7 +165,7 @@ describe('resolve', function () {
   const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip);
   caseDescribe('case sensitivity', function () {
     let file;
-    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }});
+    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] } });
     before('resolve', function () {
       file = resolve(
       // Note the case difference 'MyUncoolComponent' vs 'MyUnCoolComponent'
diff --git a/tests/src/package.js b/tests/src/package.js
index 01f7097242..f759819758 100644
--- a/tests/src/package.js
+++ b/tests/src/package.js
@@ -1,7 +1,7 @@
 const expect = require('chai').expect;
 
-const path = require('path')
-  , fs = require('fs');
+const path = require('path');
+const fs = require('fs');
 
 function isJSFile(f) {
   return path.extname(f) === '.js';
@@ -23,7 +23,7 @@ describe('package', function () {
 
     fs.readdir(
       path.join(pkg, 'rules')
-    , function (err, files) {
+      , function (err, files) {
         expect(err).not.to.exist;
 
         files.filter(isJSFile).forEach(function (f) {
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index 8fc66bc2ef..7ff6549725 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -4,23 +4,23 @@ import { RuleTester } from 'eslint';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
-const ruleTester = new RuleTester()
-  , rule = require('rules/default');
+const ruleTester = new RuleTester();
+const rule = require('rules/default');
 
 ruleTester.run('default', rule, {
   valid: [
     test({ code: 'import "./malformed.js"' }),
 
-    test({code: 'import foo from "./empty-folder";'}),
-    test({code: 'import { foo } from "./default-export";'}),
-    test({code: 'import foo from "./default-export";'}),
-    test({code: 'import foo from "./mixed-exports";'}),
+    test({ code: 'import foo from "./empty-folder";' }),
+    test({ code: 'import { foo } from "./default-export";' }),
+    test({ code: 'import foo from "./default-export";' }),
+    test({ code: 'import foo from "./mixed-exports";' }),
     test({
-      code: 'import bar from "./default-export";'}),
+      code: 'import bar from "./default-export";' }),
     test({
-      code: 'import CoolClass from "./default-class";'}),
+      code: 'import CoolClass from "./default-class";' }),
     test({
-      code: 'import bar, { baz } from "./default-export";'}),
+      code: 'import bar, { baz } from "./default-export";' }),
 
     // core modules always have a default
     test({ code: 'import crypto from "crypto";' }),
@@ -28,14 +28,14 @@ ruleTester.run('default', rule, {
     test({ code: 'import common from "./common";' }),
 
     // es7 export syntax
-    test({ code: 'export bar from "./bar"'
-         , parser: require.resolve('babel-eslint') }),
+    test({ code: 'export bar from "./bar"',
+      parser: require.resolve('babel-eslint') }),
     test({ code: 'export { default as bar } from "./bar"' }),
-    test({ code: 'export bar, { foo } from "./bar"'
-         , parser: require.resolve('babel-eslint') }),
+    test({ code: 'export bar, { foo } from "./bar"',
+      parser: require.resolve('babel-eslint') }),
     test({ code: 'export { default as bar, foo } from "./bar"' }),
-    test({ code: 'export bar, * as names from "./bar"'
-         , parser: require.resolve('babel-eslint') }),
+    test({ code: 'export bar, * as names from "./bar"',
+      parser: require.resolve('babel-eslint') }),
 
     // sanity check
     test({ code: 'export {a} from "./named-exports"' }),
@@ -103,8 +103,8 @@ ruleTester.run('default', rule, {
 
     test({
       code: 'import baz from "./named-exports";',
-      errors: [{ message: 'No default export found in imported module "./named-exports".'
-               , type: 'ImportDefaultSpecifier'}]}),
+      errors: [{ message: 'No default export found in imported module "./named-exports".',
+        type: 'ImportDefaultSpecifier' }] }),
 
     // es7 export syntax
     test({
@@ -156,109 +156,109 @@ if (!CASE_SENSITIVE_FS) {
 
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
-      ruleTester.run(`default`, rule, {
-        valid: [
-          test({
-            code: `import foobar from "./typescript-default"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import foobar from "./typescript-export-assign-default"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import foobar from "./typescript-export-assign-function"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import foobar from "./typescript-export-assign-mixed"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import foobar from "./typescript-export-assign-default-reexport"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import React from "./typescript-export-assign-default-namespace"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-            parserOptions: {
-              tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-assign-default-namespace/'),
-            },
-          }),
-          test({
-            code: `import Foo from "./typescript-export-as-default-namespace"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-            parserOptions: {
-              tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-as-default-namespace/'),
-            },
-          }),
-          test({
-            code: `import foobar from "./typescript-export-assign-property"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-        ],
+    ruleTester.run(`default`, rule, {
+      valid: [
+        test({
+          code: `import foobar from "./typescript-default"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+        }),
+        test({
+          code: `import foobar from "./typescript-export-assign-default"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+        }),
+        test({
+          code: `import foobar from "./typescript-export-assign-function"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+        }),
+        test({
+          code: `import foobar from "./typescript-export-assign-mixed"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+        }),
+        test({
+          code: `import foobar from "./typescript-export-assign-default-reexport"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+        }),
+        test({
+          code: `import React from "./typescript-export-assign-default-namespace"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+          parserOptions: {
+            tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-assign-default-namespace/'),
+          },
+        }),
+        test({
+          code: `import Foo from "./typescript-export-as-default-namespace"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+          parserOptions: {
+            tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-as-default-namespace/'),
+          },
+        }),
+        test({
+          code: `import foobar from "./typescript-export-assign-property"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+        }),
+      ],
 
-        invalid: [
-          test({
-            code: `import foobar from "./typescript"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-            errors: ['No default export found in imported module "./typescript".'],
-          }),
-          test({
-            code: `import React from "./typescript-export-assign-default-namespace"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-            errors: ['No default export found in imported module "./typescript-export-assign-default-namespace".'],
-          }),
-          test({
-            code: `import FooBar from "./typescript-export-as-default-namespace"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-            errors: ['No default export found in imported module "./typescript-export-as-default-namespace".'],
-          }),
-        ],
-      });
+      invalid: [
+        test({
+          code: `import foobar from "./typescript"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+          errors: ['No default export found in imported module "./typescript".'],
+        }),
+        test({
+          code: `import React from "./typescript-export-assign-default-namespace"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+          errors: ['No default export found in imported module "./typescript-export-assign-default-namespace".'],
+        }),
+        test({
+          code: `import FooBar from "./typescript-export-as-default-namespace"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+          errors: ['No default export found in imported module "./typescript-export-as-default-namespace".'],
+        }),
+      ],
     });
+  });
 });
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index da3b25d95a..d997b949b6 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -4,8 +4,8 @@ import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
-const ruleTester = new RuleTester()
-  , rule = require('rules/export');
+const ruleTester = new RuleTester();
+const rule = require('rules/export');
 
 ruleTester.run('export', rule, {
   valid: [].concat(
@@ -13,7 +13,7 @@ ruleTester.run('export', rule, {
 
     // default
     test({ code: 'var foo = "foo"; export default foo;' }),
-    test({ code: 'export var foo = "foo"; export var bar = "bar";'}),
+    test({ code: 'export var foo = "foo"; export var bar = "bar";' }),
     test({ code: 'export var foo = "foo", bar = "bar";' }),
     test({ code: 'export var { foo, bar } = object;' }),
     test({ code: 'export var [ foo, bar ] = array;' }),
@@ -82,7 +82,7 @@ ruleTester.run('export', rule, {
     test({
       code: 'let foo; export { foo }; export * from "./export-all"',
       errors: ['Multiple exports of name \'foo\'.',
-               'Multiple exports of name \'foo\'.'],
+        'Multiple exports of name \'foo\'.'],
     }),
     // test({ code: 'export * from "./default-export"'
     //      , errors: [{ message: 'No named exports found in module ' +
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index e06e6496d4..9ee22548e4 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -77,7 +77,7 @@ ruleTester.run('extensions', rule, {
         import Component from './Component.jsx'
         import express from 'express'
       `,
-      options: [ 'always', {ignorePackages: true} ],
+      options: [ 'always', { ignorePackages: true } ],
     }),
 
     test({
@@ -87,7 +87,7 @@ ruleTester.run('extensions', rule, {
         import Component from './Component'
         import express from 'express'
       `,
-      options: [ 'never', {ignorePackages: true} ],
+      options: [ 'never', { ignorePackages: true } ],
     }),
 
     test({
@@ -198,9 +198,9 @@ ruleTester.run('extensions', rule, {
       settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
       errors: [
         {
-            message: 'Unexpected use of file extension "js" for "./bar.js"',
-            line: 1,
-            column: 17,
+          message: 'Unexpected use of file extension "js" for "./bar.js"',
+          line: 1,
+          column: 17,
         },
       ],
     }),
@@ -214,9 +214,9 @@ ruleTester.run('extensions', rule, {
       settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
       errors: [
         {
-            message: 'Unexpected use of file extension "js" for "./bar.js"',
-            line: 1,
-            column: 17,
+          message: 'Unexpected use of file extension "js" for "./bar.js"',
+          line: 1,
+          column: 17,
         },
       ],
     }),
@@ -230,9 +230,9 @@ ruleTester.run('extensions', rule, {
       settings: { 'import/resolve': { 'extensions': [ '.jsx', '.json', '.js' ] } },
       errors: [
         {
-            message: 'Unexpected use of file extension "jsx" for "./bar.jsx"',
-            line: 1,
-            column: 23,
+          message: 'Unexpected use of file extension "jsx" for "./bar.jsx"',
+          line: 1,
+          column: 23,
         },
       ],
     }),
@@ -259,9 +259,9 @@ ruleTester.run('extensions', rule, {
       settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
       errors: [
         {
-            message: 'Unexpected use of file extension "js" for "./bar.js"',
-            line: 1,
-            column: 19,
+          message: 'Unexpected use of file extension "js" for "./bar.js"',
+          line: 1,
+          column: 19,
         },
       ],
     }),
@@ -276,9 +276,9 @@ ruleTester.run('extensions', rule, {
       settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
       errors: [
         {
-            message: 'Unexpected use of file extension "js" for "./bar.js"',
-            line: 1,
-            column: 19,
+          message: 'Unexpected use of file extension "js" for "./bar.js"',
+          line: 1,
+          column: 19,
         },
       ],
     }),
@@ -289,9 +289,9 @@ ruleTester.run('extensions', rule, {
       options: [ 'never' ],
       errors: [
         {
-            message: 'Unexpected use of file extension "js" for "./fake-file.js"',
-            line: 1,
-            column: 19,
+          message: 'Unexpected use of file extension "js" for "./fake-file.js"',
+          line: 1,
+          column: 19,
         },
       ],
     }),
@@ -300,9 +300,9 @@ ruleTester.run('extensions', rule, {
       options: [ 'always' ],
       errors: [
         {
-            message: 'Missing file extension for "non-package/test"',
-            line: 1,
-            column: 19,
+          message: 'Missing file extension for "non-package/test"',
+          line: 1,
+          column: 19,
         },
       ],
     }),
@@ -312,9 +312,9 @@ ruleTester.run('extensions', rule, {
       options: [ 'always' ],
       errors: [
         {
-            message: 'Missing file extension for "@name/pkg/test"',
-            line: 1,
-            column: 19,
+          message: 'Missing file extension for "@name/pkg/test"',
+          line: 1,
+          column: 19,
         },
       ],
     }),
@@ -324,9 +324,9 @@ ruleTester.run('extensions', rule, {
       options: [ 'never' ],
       errors: [
         {
-            message: 'Unexpected use of file extension "js" for "@name/pkg/test.js"',
-            line: 1,
-            column: 19,
+          message: 'Unexpected use of file extension "js" for "@name/pkg/test.js"',
+          line: 1,
+          column: 19,
         },
       ],
     }),
@@ -341,7 +341,7 @@ ruleTester.run('extensions', rule, {
         import baw from '@scoped/baw/import'
         import express from 'express'
       `,
-      options: [ 'always', {ignorePackages: true} ],
+      options: [ 'always', { ignorePackages: true } ],
       errors: [
         {
           message: 'Missing file extension for "./Component"',
@@ -388,7 +388,7 @@ ruleTester.run('extensions', rule, {
           column: 31,
         },
       ],
-      options: [ 'never', {ignorePackages: true} ],
+      options: [ 'never', { ignorePackages: true } ],
     }),
 
     // export (#964)
diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index 603a595d91..e8b40eb98f 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -2,69 +2,67 @@ import { test } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/first');
+const ruleTester = new RuleTester();
+const rule = require('rules/first');
 
 ruleTester.run('first', rule, {
   valid: [
     test({ code: "import { x } from './foo'; import { y } from './bar';\
-                  export { x, y }" })
-  , test({ code: "import { x } from 'foo'; import { y } from './bar'" })
-  , test({ code: "import { x } from './foo'; import { y } from 'bar'" })
-  , test({ code: "import { x } from './foo'; import { y } from 'bar'"
-         , options: ['disable-absolute-first'],
-         })
-  , test({ code: "'use directive';\
-                  import { x } from 'foo';" })
-  ,
+                  export { x, y }" }),
+    test({ code: "import { x } from 'foo'; import { y } from './bar'" }),
+    test({ code: "import { x } from './foo'; import { y } from 'bar'" }),
+    test({ code: "import { x } from './foo'; import { y } from 'bar'",
+      options: ['disable-absolute-first'],
+    }),
+    test({ code: "'use directive';\
+                  import { x } from 'foo';" }),  
   ],
   invalid: [
     test({ code: "import { x } from './foo';\
                   export { x };\
-                  import { y } from './bar';"
-         , errors: 1
-         , output: "import { x } from './foo';\
+                  import { y } from './bar';",
+    errors: 1,
+    output: "import { x } from './foo';\
                   import { y } from './bar';\
                   export { x };",
-         })
-  , test({ code: "import { x } from './foo';\
+    }),
+    test({ code: "import { x } from './foo';\
                   export { x };\
                   import { y } from './bar';\
-                  import { z } from './baz';"
-         , errors: 2
-         , output: "import { x } from './foo';\
+                  import { z } from './baz';",
+    errors: 2,
+    output: "import { x } from './foo';\
                   import { y } from './bar';\
                   import { z } from './baz';\
                   export { x };",
-         })
-  , test({ code: "import { x } from './foo'; import { y } from 'bar'"
-         , options: ['absolute-first']
-         , errors: 1,
-         })
-  , test({ code: "import { x } from 'foo';\
+    }),
+    test({ code: "import { x } from './foo'; import { y } from 'bar'",
+      options: ['absolute-first'],
+      errors: 1,
+    }),
+    test({ code: "import { x } from 'foo';\
                   'use directive';\
-                  import { y } from 'bar';"
-         , errors: 1
-         , output: "import { x } from 'foo';\
+                  import { y } from 'bar';",
+    errors: 1,
+    output: "import { x } from 'foo';\
                   import { y } from 'bar';\
                   'use directive';",
-         })
-  , test({ code: "var a = 1;\
+    }),
+    test({ code: "var a = 1;\
                   import { y } from './bar';\
                   if (true) { x() };\
                   import { x } from './foo';\
-                  import { z } from './baz';"
-         , errors: 3
-         , output: "import { y } from './bar';\
+                  import { z } from './baz';",
+    errors: 3,
+    output: "import { y } from './bar';\
                   var a = 1;\
                   if (true) { x() };\
                   import { x } from './foo';\
                   import { z } from './baz';",
-  })
-  , test({ code: "if (true) { console.log(1) }import a from 'b'"
-         , errors: 1
-         , output: "import a from 'b'\nif (true) { console.log(1) }",
-  })
-  ,
+    }),
+    test({ code: "if (true) { console.log(1) }import a from 'b'",
+      errors: 1,
+      output: "import a from 'b'\nif (true) { console.log(1) }",
+    }),  
   ],
 });
diff --git a/tests/src/rules/group-exports.js b/tests/src/rules/group-exports.js
index a3f2a11d5d..c3d07046f0 100644
--- a/tests/src/rules/group-exports.js
+++ b/tests/src/rules/group-exports.js
@@ -1,8 +1,8 @@
 import { test } from '../utils';
 import { RuleTester } from 'eslint';
 import rule from 'rules/group-exports';
-import {resolve} from 'path';
-import {default as babelPresetFlow} from 'babel-preset-flow';
+import { resolve } from 'path';
+import { default as babelPresetFlow } from 'babel-preset-flow';
 
 /* eslint-disable max-len */
 const errors = {
@@ -60,7 +60,7 @@ ruleTester.run('group-exports', rule, {
       export { default as module1 } from './module-1'
       export { default as module2 } from './module-2'
     ` }),
-    test({ code: 'module.exports = {} '}),
+    test({ code: 'module.exports = {} ' }),
     test({ code: `
       module.exports = { test: true,
         another: false }
diff --git a/tests/src/rules/max-dependencies.js b/tests/src/rules/max-dependencies.js
index 09d13a060c..f4e5f9a976 100644
--- a/tests/src/rules/max-dependencies.js
+++ b/tests/src/rules/max-dependencies.js
@@ -2,8 +2,8 @@ import { test } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/max-dependencies');
+const ruleTester = new RuleTester();
+const rule = require('rules/max-dependencies');
 
 ruleTester.run('max-dependencies', rule, {
   valid: [
@@ -21,7 +21,7 @@ ruleTester.run('max-dependencies', rule, {
       }],
     }),
 
-    test({ code: 'import {x, y, z} from "./foo"'}),
+    test({ code: 'import {x, y, z} from "./foo"' }),
   ],
   invalid: [
     test({
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index fce805c890..f09ee20595 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -4,42 +4,42 @@ import { RuleTester } from 'eslint';
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
 
-const ruleTester = new RuleTester()
-  , rule = require('rules/named');
+const ruleTester = new RuleTester();
+const rule = require('rules/named');
 
 function error(name, module) {
-  return { message: name + ' not found in \'' + module + '\''
-         , type: 'Identifier' };
+  return { message: name + ' not found in \'' + module + '\'',
+    type: 'Identifier' };
 }
 
 ruleTester.run('named', rule, {
   valid: [
     test({ code: 'import "./malformed.js"' }),
 
-    test({code: 'import { foo } from "./bar"'}),
-    test({code: 'import { foo } from "./empty-module"'}),
-    test({code: 'import bar from "./bar.js"'}),
-    test({code: 'import bar, { foo } from "./bar.js"'}),
-    test({code: 'import {a, b, d} from "./named-exports"'}),
-    test({code: 'import {ExportedClass} from "./named-exports"'}),
-    test({code: 'import { destructingAssign } from "./named-exports"'}),
-    test({code: 'import { destructingRenamedAssign } from "./named-exports"'}),
-    test({code: 'import { ActionTypes } from "./qc"'}),
-    test({code: 'import {a, b, c, d} from "./re-export"'}),
-    test({code: 'import {a, b, c} from "./re-export-common-star"'}),
-    test({code: 'import {RuleTester} from "./re-export-node_modules"'}),
-
-    test({ code: 'import { jsxFoo } from "./jsx/AnotherComponent"'
-         , settings: { 'import/resolve': { 'extensions': ['.js', '.jsx'] } } }),
+    test({ code: 'import { foo } from "./bar"' }),
+    test({ code: 'import { foo } from "./empty-module"' }),
+    test({ code: 'import bar from "./bar.js"' }),
+    test({ code: 'import bar, { foo } from "./bar.js"' }),
+    test({ code: 'import {a, b, d} from "./named-exports"' }),
+    test({ code: 'import {ExportedClass} from "./named-exports"' }),
+    test({ code: 'import { destructingAssign } from "./named-exports"' }),
+    test({ code: 'import { destructingRenamedAssign } from "./named-exports"' }),
+    test({ code: 'import { ActionTypes } from "./qc"' }),
+    test({ code: 'import {a, b, c, d} from "./re-export"' }),
+    test({ code: 'import {a, b, c} from "./re-export-common-star"' }),
+    test({ code: 'import {RuleTester} from "./re-export-node_modules"' }),
+
+    test({ code: 'import { jsxFoo } from "./jsx/AnotherComponent"',
+      settings: { 'import/resolve': { 'extensions': ['.js', '.jsx'] } } }),
 
     // validate that eslint-disable-line silences this properly
-    test({code: 'import {a, b, d} from "./common"; ' +
+    test({ code: 'import {a, b, d} from "./common"; ' +
                 '// eslint-disable-line named' }),
 
     test({ code: 'import { foo, bar } from "./re-export-names"' }),
 
-    test({ code: 'import { foo, bar } from "./common"'
-         , settings: { 'import/ignore': ['common'] } }),
+    test({ code: 'import { foo, bar } from "./common"',
+      settings: { 'import/ignore': ['common'] } }),
 
     // ignore core modules by default
     test({ code: 'import { foo } from "crypto"' }),
@@ -63,7 +63,7 @@ ruleTester.run('named', rule, {
     }),
 
     // regression tests
-    test({ code: 'let foo; export { foo as bar }'}),
+    test({ code: 'let foo; export { foo as bar }' }),
 
     // destructured exports
     test({ code: 'import { destructuredProp } from "./named-exports"' }),
@@ -151,27 +151,27 @@ ruleTester.run('named', rule, {
 
   invalid: [
 
-    test({ code: 'import { somethingElse } from "./test-module"'
-         , errors: [ error('somethingElse', './test-module') ] }),
+    test({ code: 'import { somethingElse } from "./test-module"',
+      errors: [ error('somethingElse', './test-module') ] }),
 
-    test({code: 'import { baz } from "./bar"',
-      errors: [error('baz', './bar')]}),
+    test({ code: 'import { baz } from "./bar"',
+      errors: [error('baz', './bar')] }),
 
     // test multiple
-    test({code: 'import { baz, bop } from "./bar"',
-      errors: [error('baz', './bar'), error('bop', './bar')]}),
+    test({ code: 'import { baz, bop } from "./bar"',
+      errors: [error('baz', './bar'), error('bop', './bar')] }),
 
-    test({code: 'import {a, b, c} from "./named-exports"',
-      errors: [error('c', './named-exports')]}),
+    test({ code: 'import {a, b, c} from "./named-exports"',
+      errors: [error('c', './named-exports')] }),
 
-    test({code: 'import { a } from "./default-export"',
-      errors: [error('a', './default-export')]}),
+    test({ code: 'import { a } from "./default-export"',
+      errors: [error('a', './default-export')] }),
 
-    test({code: 'import { ActionTypess } from "./qc"',
-      errors: [error('ActionTypess', './qc')]}),
+    test({ code: 'import { ActionTypess } from "./qc"',
+      errors: [error('ActionTypess', './qc')] }),
 
-    test({code: 'import {a, b, c, d, e} from "./re-export"',
-      errors: [error('e', './re-export')]}),
+    test({ code: 'import {a, b, c, d, e} from "./re-export"',
+      errors: [error('e', './re-export')] }),
 
     test({
       code: 'import { a } from "./re-export-names"',
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 291960dbf5..ce55bccc35 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -2,8 +2,8 @@ import { test, SYNTAX_CASES, getTSParsers } from '../utils';
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
 
-const ruleTester = new RuleTester({ env: { es6: true }})
-  , rule = require('rules/namespace');
+const ruleTester = new RuleTester({ env: { es6: true } });
+const rule = require('rules/namespace');
 
 
 function error(name, namespace) {
@@ -13,7 +13,7 @@ function error(name, namespace) {
 const valid = [
   test({ code: 'import "./malformed.js"' }),
 
-  test({ code: "import * as foo from './empty-folder';"}),
+  test({ code: "import * as foo from './empty-folder';" }),
   test({ code: 'import * as names from "./named-exports"; ' +
                'console.log((names.b).c); ' }),
 
@@ -56,13 +56,13 @@ const valid = [
   /////////
   // es7 //
   /////////
-  test({ code: 'export * as names from "./named-exports"'
-       , parser: require.resolve('babel-eslint') }),
-  test({ code: 'export defport, * as names from "./named-exports"'
-       , parser: require.resolve('babel-eslint') }),
+  test({ code: 'export * as names from "./named-exports"',
+    parser: require.resolve('babel-eslint') }),
+  test({ code: 'export defport, * as names from "./named-exports"',
+    parser: require.resolve('babel-eslint') }),
   // non-existent is handled by no-unresolved
-  test({ code: 'export * as names from "./does-not-exist"'
-       , parser: require.resolve('babel-eslint') }),
+  test({ code: 'export * as names from "./does-not-exist"',
+    parser: require.resolve('babel-eslint') }),
 
   test({
     code: 'import * as Endpoints from "./issue-195/Endpoints"; console.log(Endpoints.Users)',
@@ -80,8 +80,8 @@ const valid = [
   test({ code: "import * as names from './default-export';" }),
   test({ code: "import * as names from './default-export'; console.log(names.default)" }),
   test({
-   code: 'export * as names from "./default-export"',
-   parser: require.resolve('babel-eslint'),
+    code: 'export * as names from "./default-export"',
+    parser: require.resolve('babel-eslint'),
   }),
   test({
     code: 'export defport, * as names from "./default-export"',
@@ -176,18 +176,18 @@ const valid = [
 
 const invalid = [
   test({ code: "import * as names from './named-exports'; " +
-               ' console.log(names.c);'
-       , errors: [error('c', 'names')] }),
+               ' console.log(names.c);',
+  errors: [error('c', 'names')] }),
 
   test({ code: "import * as names from './named-exports';" +
-               " console.log(names['a']);"
-       , errors: ["Unable to validate computed reference to imported namespace 'names'."] }),
+               " console.log(names['a']);",
+  errors: ["Unable to validate computed reference to imported namespace 'names'."] }),
 
   // assignment warning (from no-reassign)
-  test({ code: 'import * as foo from \'./bar\'; foo.foo = \'y\';'
-       , errors: [{ message: 'Assignment to member of namespace \'foo\'.'}] }),
-  test({ code: 'import * as foo from \'./bar\'; foo.x = \'y\';'
-       , errors: ['Assignment to member of namespace \'foo\'.', "'x' not found in imported namespace 'foo'."] }),
+  test({ code: 'import * as foo from \'./bar\'; foo.foo = \'y\';',
+    errors: [{ message: 'Assignment to member of namespace \'foo\'.' }] }),
+  test({ code: 'import * as foo from \'./bar\'; foo.x = \'y\';',
+    errors: ['Assignment to member of namespace \'foo\'.', "'x' not found in imported namespace 'foo'."] }),
 
   // invalid destructuring
   test({
@@ -276,8 +276,8 @@ const invalid = [
     test({ parser, code: `import * as a from "./${folder}/a"; var {b:{c:{d:{e}}}} = a` }),
     test({ parser, code: `import { b } from "./${folder}/a"; var {c:{d:{e}}} = b` }));
 
-    // deep namespaces should include explicitly exported defaults
-    test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.default)` }),
+  // deep namespaces should include explicitly exported defaults
+  test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.default)` }),
 
   invalid.push(
     test({
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 9965f315ed..58f5ef1dd8 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -5,7 +5,7 @@ import { getTSParsers } from '../utils';
 
 const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.';
 const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => {
-    return `Expected ${count} empty lines after import statement not followed by another import.`;
+  return `Expected ${count} empty lines after import statement not followed by another import.`;
 };
 const REQUIRE_ERROR_MESSAGE = 'Expected 1 empty line after require statement not followed by another require.';
 
@@ -68,7 +68,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
           return somethingElse();
       }
     }`,
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
       code: `import path from 'path';\nimport foo from 'foo';\n`,
@@ -281,16 +281,16 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       code: `import foo from 'foo';\nvar a = 123;\n\nimport { bar } from './bar-lib';\nvar b=456;`,
       output: `import foo from 'foo';\n\nvar a = 123;\n\nimport { bar } from './bar-lib';\n\nvar b=456;`,
       errors: [
-      {
-        line: 1,
-        column: 1,
-        message: IMPORT_ERROR_MESSAGE,
-      },
-      {
-        line: 4,
-        column: 1,
-        message: IMPORT_ERROR_MESSAGE,
-      }],
+        {
+          line: 1,
+          column: 1,
+          message: IMPORT_ERROR_MESSAGE,
+        },
+        {
+          line: 4,
+          column: 1,
+          message: IMPORT_ERROR_MESSAGE,
+        }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
diff --git a/tests/src/rules/no-absolute-path.js b/tests/src/rules/no-absolute-path.js
index e22d867f09..63fb8c0b6b 100644
--- a/tests/src/rules/no-absolute-path.js
+++ b/tests/src/rules/no-absolute-path.js
@@ -2,8 +2,8 @@ import { test } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-absolute-path');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-absolute-path');
 
 const error = {
   message: 'Do not import modules using an absolute path',
@@ -11,20 +11,20 @@ const error = {
 
 ruleTester.run('no-absolute-path', rule, {
   valid: [
-    test({ code: 'import _ from "lodash"'}),
-    test({ code: 'import find from "lodash.find"'}),
-    test({ code: 'import foo from "./foo"'}),
-    test({ code: 'import foo from "../foo"'}),
-    test({ code: 'import foo from "foo"'}),
-    test({ code: 'import foo from "./"'}),
-    test({ code: 'import foo from "@scope/foo"'}),
-    test({ code: 'var _ = require("lodash")'}),
-    test({ code: 'var find = require("lodash.find")'}),
-    test({ code: 'var foo = require("./foo")'}),
-    test({ code: 'var foo = require("../foo")'}),
-    test({ code: 'var foo = require("foo")'}),
-    test({ code: 'var foo = require("./")'}),
-    test({ code: 'var foo = require("@scope/foo")'}),
+    test({ code: 'import _ from "lodash"' }),
+    test({ code: 'import find from "lodash.find"' }),
+    test({ code: 'import foo from "./foo"' }),
+    test({ code: 'import foo from "../foo"' }),
+    test({ code: 'import foo from "foo"' }),
+    test({ code: 'import foo from "./"' }),
+    test({ code: 'import foo from "@scope/foo"' }),
+    test({ code: 'var _ = require("lodash")' }),
+    test({ code: 'var find = require("lodash.find")' }),
+    test({ code: 'var foo = require("./foo")' }),
+    test({ code: 'var foo = require("../foo")' }),
+    test({ code: 'var foo = require("foo")' }),
+    test({ code: 'var foo = require("./")' }),
+    test({ code: 'var foo = require("@scope/foo")' }),
 
     test({ code: 'import events from "events"' }),
     test({ code: 'import path from "path"' }),
diff --git a/tests/src/rules/no-amd.js b/tests/src/rules/no-amd.js
index 1371244006..74c89c4116 100644
--- a/tests/src/rules/no-amd.js
+++ b/tests/src/rules/no-amd.js
@@ -12,7 +12,7 @@ ruleTester.run('no-amd', require('rules/no-amd'), {
 
     'require("x")',
     // 2-args, not an array
-		'require("x", "y")',
+    'require("x", "y")',
     // random other function
     'setTimeout(foo, 100)',
     // non-identifier callee
@@ -25,13 +25,13 @@ ruleTester.run('no-amd', require('rules/no-amd'), {
     // unmatched arg types/number
     'define(0, 1, 2)',
     'define("a")',
-	],
+  ],
 
-	invalid: semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
-      { code: 'define([], function() {})', errors: [ { message: 'Expected imports instead of AMD define().' }] },
-      { code: 'define(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD define().' }] },
+  invalid: semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
+    { code: 'define([], function() {})', errors: [ { message: 'Expected imports instead of AMD define().' }] },
+    { code: 'define(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD define().' }] },
 
-      { code: 'require([], function() {})', errors: [ { message: 'Expected imports instead of AMD require().' }] },
-      { code: 'require(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD require().' }] },
-	],
+    { code: 'require([], function() {})', errors: [ { message: 'Expected imports instead of AMD require().' }] },
+    { code: 'require(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD require().' }] },
+  ],
 });
diff --git a/tests/src/rules/no-anonymous-default-export.js b/tests/src/rules/no-anonymous-default-export.js
index 735f2dbd58..231f1b667d 100644
--- a/tests/src/rules/no-anonymous-default-export.js
+++ b/tests/src/rules/no-anonymous-default-export.js
@@ -6,50 +6,50 @@ const ruleTester = new RuleTester();
 const rule = require('rules/no-anonymous-default-export');
 
 ruleTester.run('no-anonymous-default-export', rule, {
-    valid: [
-      // Exports with identifiers are valid
-      test({ code: 'const foo = 123\nexport default foo' }),
-      test({ code: 'export default function foo() {}'}),
-      test({ code: 'export default class MyClass {}'}),
-
-      // Allow each forbidden type with appropriate option
-      test({ code: 'export default []', options: [{ allowArray: true }] }),
-      test({ code: 'export default () => {}', options: [{ allowArrowFunction: true }] }),
-      test({ code: 'export default class {}', options: [{ allowAnonymousClass: true }] }),
-      test({ code: 'export default function() {}', options: [{ allowAnonymousFunction: true }] }),
-      test({ code: 'export default 123', options: [{ allowLiteral: true }] }),
-      test({ code: 'export default \'foo\'', options: [{ allowLiteral: true }] }),
-      test({ code: 'export default `foo`', options: [{ allowLiteral: true }] }),
-      test({ code: 'export default {}', options: [{ allowObject: true }] }),
-      test({ code: 'export default foo(bar)', options: [{ allowCallExpression: true }] }),
-
-      // Allow forbidden types with multiple options
-      test({ code: 'export default 123', options: [{ allowLiteral: true, allowObject: true }] }),
-      test({ code: 'export default {}', options: [{ allowLiteral: true, allowObject: true }] }),
-
-      // Sanity check unrelated export syntaxes
-      test({ code: 'export * from \'foo\'' }),
-      test({ code: 'const foo = 123\nexport { foo }' }),
-      test({ code: 'const foo = 123\nexport { foo as default }' }),
-
-      // Allow call expressions by default for backwards compatibility
-      test({ code: 'export default foo(bar)' }),
-
-      ...SYNTAX_CASES,
-    ],
-
-    invalid: [
-      test({ code: 'export default []', errors: [{ message: 'Assign array to a variable before exporting as module default' }] }),
-      test({ code: 'export default () => {}', errors: [{ message: 'Assign arrow function to a variable before exporting as module default' }] }),
-      test({ code: 'export default class {}', errors: [{ message: 'Unexpected default export of anonymous class' }] }),
-      test({ code: 'export default function() {}', errors: [{ message: 'Unexpected default export of anonymous function' }] }),
-      test({ code: 'export default 123', errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
-      test({ code: 'export default \'foo\'', errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
-      test({ code: 'export default `foo`', errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
-      test({ code: 'export default {}', errors: [{ message: 'Assign object to a variable before exporting as module default' }] }),
-      test({ code: 'export default foo(bar)', options: [{ allowCallExpression: false }], errors: [{ message: 'Assign call result to a variable before exporting as module default' }] }),
-
-      // Test failure with non-covering exception
-      test({ code: 'export default 123', options: [{ allowObject: true }], errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
-    ],
+  valid: [
+    // Exports with identifiers are valid
+    test({ code: 'const foo = 123\nexport default foo' }),
+    test({ code: 'export default function foo() {}' }),
+    test({ code: 'export default class MyClass {}' }),
+
+    // Allow each forbidden type with appropriate option
+    test({ code: 'export default []', options: [{ allowArray: true }] }),
+    test({ code: 'export default () => {}', options: [{ allowArrowFunction: true }] }),
+    test({ code: 'export default class {}', options: [{ allowAnonymousClass: true }] }),
+    test({ code: 'export default function() {}', options: [{ allowAnonymousFunction: true }] }),
+    test({ code: 'export default 123', options: [{ allowLiteral: true }] }),
+    test({ code: 'export default \'foo\'', options: [{ allowLiteral: true }] }),
+    test({ code: 'export default `foo`', options: [{ allowLiteral: true }] }),
+    test({ code: 'export default {}', options: [{ allowObject: true }] }),
+    test({ code: 'export default foo(bar)', options: [{ allowCallExpression: true }] }),
+
+    // Allow forbidden types with multiple options
+    test({ code: 'export default 123', options: [{ allowLiteral: true, allowObject: true }] }),
+    test({ code: 'export default {}', options: [{ allowLiteral: true, allowObject: true }] }),
+
+    // Sanity check unrelated export syntaxes
+    test({ code: 'export * from \'foo\'' }),
+    test({ code: 'const foo = 123\nexport { foo }' }),
+    test({ code: 'const foo = 123\nexport { foo as default }' }),
+
+    // Allow call expressions by default for backwards compatibility
+    test({ code: 'export default foo(bar)' }),
+
+    ...SYNTAX_CASES,
+  ],
+
+  invalid: [
+    test({ code: 'export default []', errors: [{ message: 'Assign array to a variable before exporting as module default' }] }),
+    test({ code: 'export default () => {}', errors: [{ message: 'Assign arrow function to a variable before exporting as module default' }] }),
+    test({ code: 'export default class {}', errors: [{ message: 'Unexpected default export of anonymous class' }] }),
+    test({ code: 'export default function() {}', errors: [{ message: 'Unexpected default export of anonymous function' }] }),
+    test({ code: 'export default 123', errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
+    test({ code: 'export default \'foo\'', errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
+    test({ code: 'export default `foo`', errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
+    test({ code: 'export default {}', errors: [{ message: 'Assign object to a variable before exporting as module default' }] }),
+    test({ code: 'export default foo(bar)', options: [{ allowCallExpression: false }], errors: [{ message: 'Assign call result to a variable before exporting as module default' }] }),
+
+    // Test failure with non-covering exception
+    test({ code: 'export default 123', options: [{ allowObject: true }], errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
+  ],
 });
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index f474abd5cd..b016602b29 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -2,8 +2,8 @@ import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
-const EXPORT_MESSAGE = 'Expected "export" or "export default"'
-    , IMPORT_MESSAGE = 'Expected "import" instead of "require()"';
+const EXPORT_MESSAGE = 'Expected "export" or "export default"';
+const IMPORT_MESSAGE = 'Expected "import" instead of "require()"';
 
 const ruleTester = new RuleTester();
 
@@ -49,7 +49,7 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
     // commonJS rules should be scoped to commonJS spec. `rootRequire` is not
     // recognized by this commonJS plugin.
     { code: 'rootRequire("x")', options: [{ allowRequire: true }] },
-    { code: 'rootRequire("x")', options: [{ allowRequire: false}] },
+    { code: 'rootRequire("x")', options: [{ allowRequire: false }] },
 
     { code: 'module.exports = function () {}', options: ['allow-primitive-modules'] },
     { code: 'module.exports = function () {}', options: [{ allowPrimitiveModules: true }] },
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index beb459ccfb..1525781ce5 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -2,8 +2,8 @@ import { test as _test, testFilePath } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-cycle');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-cycle');
 
 const error = message => ({ message });
 
@@ -15,7 +15,7 @@ const test = def => _test(Object.assign(def, {
 ruleTester.run('no-cycle', rule, {
   valid: [
     // this rule doesn't care if the cycle length is 0
-    test({ code: 'import foo from "./foo.js"'}),
+    test({ code: 'import foo from "./foo.js"' }),
 
     test({ code: 'import _ from "lodash"' }),
     test({ code: 'import foo from "@scope/foo"' }),
diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index d0c89bfd34..bc0119a019 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -2,8 +2,8 @@ import { test } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-default-export');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-default-export');
 
 ruleTester.run('no-default-export', rule, {
   valid: [
diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index 2c84134154..aa2aebedc6 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -2,8 +2,8 @@ import { test, SYNTAX_CASES, getTSParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-deprecated');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-deprecated');
 
 ruleTester.run('no-deprecated', rule, {
   valid: [
@@ -220,8 +220,8 @@ describe('TypeScript', function () {
           errors: [
             { type: 'ImportSpecifier', message: 'Deprecated: don\'t use this!' },
             { type: 'Identifier', message: 'Deprecated: don\'t use this!' },
-          ]},
-          parserConfig)),
+          ] },
+        parserConfig)),
       ],
     });
   });
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 4579e66744..ed8204cf76 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -3,11 +3,11 @@ import { test as testUtil, getNonDefaultParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-duplicates');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-duplicates');
 
 const test = process.env.ESLINT_VERSION === '3' || process.env.ESLINT_VERSION === '2'
-  ? t => testUtil(Object.assign({}, t, {output: t.code}))
+  ? t => testUtil(Object.assign({}, t, { output: t.code }))
   : testUtil;
 
 ruleTester.run('no-duplicates', rule, {
@@ -29,12 +29,12 @@ ruleTester.run('no-duplicates', rule, {
     // #1107: Using different query strings that trigger different webpack loaders.
     test({
       code: "import x from './bar?optionX'; import y from './bar?optionY';",
-      options: [{'considerQueryString': true}],
+      options: [{ 'considerQueryString': true }],
       settings: { 'import/resolver': 'webpack' },
     }),
     test({
       code: "import x from './foo'; import y from './bar';",
-      options: [{'considerQueryString': true}],
+      options: [{ 'considerQueryString': true }],
       settings: { 'import/resolver': 'webpack' },
     }),
 
@@ -65,30 +65,30 @@ ruleTester.run('no-duplicates', rule, {
       output: "import { x , y } from './bar'; ",
       settings: { 'import/resolve': {
         paths: [path.join( process.cwd()
-                         , 'tests', 'files',
-                         )] }},
+          , 'tests', 'files',
+        )] } },
       errors: 2, // path ends up hardcoded
-     }),
+    }),
 
     // #1107: Using different query strings that trigger different webpack loaders.
     test({
       code: "import x from './bar.js?optionX'; import y from './bar?optionX';",
       settings: { 'import/resolver': 'webpack' },
       errors: 2, // path ends up hardcoded
-     }),
+    }),
     test({
       code: "import x from './bar?optionX'; import y from './bar?optionY';",
       settings: { 'import/resolver': 'webpack' },
       errors: 2, // path ends up hardcoded
-     }),
+    }),
 
     // #1107: Using same query strings that trigger the same loader.
     test({
       code: "import x from './bar?optionX'; import y from './bar.js?optionX';",
-      options: [{'considerQueryString': true}],
+      options: [{ 'considerQueryString': true }],
       settings: { 'import/resolver': 'webpack' },
       errors: 2, // path ends up hardcoded
-     }),
+    }),
 
     // #86: duplicate unresolved modules should be flagged
     test({
@@ -402,29 +402,29 @@ ruleTester.run('no-duplicates', rule, {
 
 context('TypeScript', function() {
   getNonDefaultParsers()
-  .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
-  .forEach((parser) => {
-    const parserConfig = {
-      parser: parser,
-      settings: {
-        'import/parsers': { [parser]: ['.ts'] },
-        'import/resolver': { 'eslint-import-resolver-typescript': true },
-      },
-    };
-
-    ruleTester.run('no-duplicates', rule, {
-      valid: [
+    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .forEach((parser) => {
+      const parserConfig = {
+        parser: parser,
+        settings: {
+          'import/parsers': { [parser]: ['.ts'] },
+          'import/resolver': { 'eslint-import-resolver-typescript': true },
+        },
+      };
+
+      ruleTester.run('no-duplicates', rule, {
+        valid: [
         // #1667: ignore duplicate if is a typescript type import
-        test(
-          {
-            code: "import type { x } from './foo'; import y from './foo'",
-            parser,
-          },
-          parserConfig,
-        ),
-      ],
-      invalid: [],
+          test(
+            {
+              code: "import type { x } from './foo'; import y from './foo'",
+              parser,
+            },
+            parserConfig,
+          ),
+        ],
+        invalid: [],
+      });
     });
-  });
 });
 
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index 27ebd6fe44..0519664427 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -2,8 +2,8 @@ import { test } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-dynamic-require');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-dynamic-require');
 
 const error = {
   message: 'Calls to require() should use string literals',
@@ -11,17 +11,17 @@ const error = {
 
 ruleTester.run('no-dynamic-require', rule, {
   valid: [
-    test({ code: 'import _ from "lodash"'}),
-    test({ code: 'require("foo")'}),
-    test({ code: 'require(`foo`)'}),
-    test({ code: 'require("./foo")'}),
-    test({ code: 'require("@scope/foo")'}),
-    test({ code: 'require()'}),
-    test({ code: 'require("./foo", "bar" + "okay")'}),
-    test({ code: 'var foo = require("foo")'}),
-    test({ code: 'var foo = require(`foo`)'}),
-    test({ code: 'var foo = require("./foo")'}),
-    test({ code: 'var foo = require("@scope/foo")'}),
+    test({ code: 'import _ from "lodash"' }),
+    test({ code: 'require("foo")' }),
+    test({ code: 'require(`foo`)' }),
+    test({ code: 'require("./foo")' }),
+    test({ code: 'require("@scope/foo")' }),
+    test({ code: 'require()' }),
+    test({ code: 'require("./foo", "bar" + "okay")' }),
+    test({ code: 'var foo = require("foo")' }),
+    test({ code: 'var foo = require(`foo`)' }),
+    test({ code: 'var foo = require("./foo")' }),
+    test({ code: 'var foo = require("@scope/foo")' }),
   ],
   invalid: [
     test({
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 8940c9be9d..56eb555eb1 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -44,17 +44,16 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       test({ code: `export { foo } from "${pkg}"` }),
       test({ code: `export * from "${pkg}"` }),
     ]),
-    test({ code: 'import "eslint"'}),
-    test({ code: 'import "eslint/lib/api"'}),
-    test({ code: 'import "fs"'}),
-    test({ code: 'import "./foo"'}),
-    test({ code: 'import "@org/package"'}),
+    test({ code: 'import "eslint"' }),
+    test({ code: 'import "eslint/lib/api"' }),
+    test({ code: 'import "fs"' }),
+    test({ code: 'import "./foo"' }),
+    test({ code: 'import "@org/package"' }),
 
     test({ code: 'import "electron"', settings: { 'import/core-modules': ['electron'] } }),
-    test({ code: 'import "eslint"' }),
     test({
       code: 'import "eslint"',
-      options: [{peerDependencies: true}],
+      options: [{ peerDependencies: true }],
     }),
 
     // 'project' type
@@ -64,65 +63,65 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: 'import chai from "chai"',
-      options: [{devDependencies: ['*.spec.js']}],
+      options: [{ devDependencies: ['*.spec.js'] }],
       filename: 'foo.spec.js',
     }),
     test({
       code: 'import chai from "chai"',
-      options: [{devDependencies: ['*.spec.js']}],
+      options: [{ devDependencies: ['*.spec.js'] }],
       filename: path.join(process.cwd(), 'foo.spec.js'),
     }),
     test({
       code: 'import chai from "chai"',
-      options: [{devDependencies: ['*.test.js', '*.spec.js']}],
+      options: [{ devDependencies: ['*.test.js', '*.spec.js'] }],
       filename: path.join(process.cwd(), 'foo.spec.js'),
     }),
     test({ code: 'require(6)' }),
     test({
       code: 'import "doctrine"',
-      options: [{packageDir: path.join(__dirname, '../../../')}],
+      options: [{ packageDir: path.join(__dirname, '../../../') }],
     }),
     test({
       code: 'import type MyType from "myflowtyped";',
-      options: [{packageDir: packageDirWithFlowTyped}],
+      options: [{ packageDir: packageDirWithFlowTyped }],
       parser: require.resolve('babel-eslint'),
     }),
     test({
       code: 'import react from "react";',
-      options: [{packageDir: packageDirMonoRepoWithNested}],
+      options: [{ packageDir: packageDirMonoRepoWithNested }],
     }),
     test({
       code: 'import leftpad from "left-pad";',
-      options: [{packageDir: [packageDirMonoRepoWithNested, packageDirMonoRepoRoot]}],
+      options: [{ packageDir: [packageDirMonoRepoWithNested, packageDirMonoRepoRoot] }],
     }),
     test({
       code: 'import leftpad from "left-pad";',
-      options: [{packageDir: packageDirMonoRepoRoot}],
+      options: [{ packageDir: packageDirMonoRepoRoot }],
     }),
     test({
       code: 'import react from "react";',
-      options: [{packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested]}],
+      options: [{ packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested] }],
     }),
     test({
       code: 'import leftpad from "left-pad";',
-      options: [{packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested]}],
+      options: [{ packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested] }],
     }),
     test({
       code: 'import rightpad from "right-pad";',
-      options: [{packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested]}],
+      options: [{ packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested] }],
     }),
-    test({ code: 'import foo from "@generated/foo"'}),
+    test({ code: 'import foo from "@generated/foo"' }),
     test({
       code: 'import foo from "@generated/foo"',
-      options: [{packageDir: packageDirBundleDeps}],
+      options: [{ packageDir: packageDirBundleDeps }],
     }),
     test({
       code: 'import foo from "@generated/foo"',
-      options: [{packageDir: packageDirBundledDepsAsObject}],
+      options: [{ packageDir: packageDirBundledDepsAsObject }],
     }),
     test({
       code: 'import foo from "@generated/foo"',
-      options: [{packageDir: packageDirBundledDepsRaceCondition}],
+      options: [{ packageDir: packageDirBundledDepsRaceCondition }],
     }),
     test({ code: 'export function getToken() {}' }),
     test({ code: 'export class Component extends React.Component {}' }),
@@ -133,7 +132,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'import "not-a-dependency"',
       filename: path.join(packageDirMonoRepoRoot, 'foo.js'),
-      options: [{packageDir: packageDirMonoRepoRoot }],
+      options: [{ packageDir: packageDirMonoRepoRoot }],
       errors: [{
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
@@ -141,14 +140,14 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'import "not-a-dependency"',
       filename: path.join(packageDirMonoRepoWithNested, 'foo.js'),
-      options: [{packageDir: packageDirMonoRepoRoot}],
+      options: [{ packageDir: packageDirMonoRepoRoot }],
       errors: [{
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
     test({
       code: 'import "not-a-dependency"',
-      options: [{packageDir: packageDirMonoRepoRoot}],
+      options: [{ packageDir: packageDirMonoRepoRoot }],
       errors: [{
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
@@ -173,14 +172,14 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: 'import "eslint"',
-      options: [{devDependencies: false, peerDependencies: false}],
+      options: [{ devDependencies: false, peerDependencies: false }],
       errors: [{
         message: '\'eslint\' should be listed in the project\'s dependencies, not devDependencies.',
       }],
     }),
     test({
       code: 'import "lodash.isarray"',
-      options: [{optionalDependencies: false}],
+      options: [{ optionalDependencies: false }],
       errors: [{
         message: '\'lodash.isarray\' should be listed in the project\'s dependencies, not optionalDependencies.',
       }],
@@ -193,14 +192,14 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: 'var glob = require("glob")',
-      options: [{devDependencies: false}],
+      options: [{ devDependencies: false }],
       errors: [{
         message: '\'glob\' should be listed in the project\'s dependencies, not devDependencies.',
       }],
     }),
     test({
       code: 'import chai from "chai"',
-      options: [{devDependencies: ['*.test.js']}],
+      options: [{ devDependencies: ['*.test.js'] }],
       filename: 'foo.tes.js',
       errors: [{
         message: '\'chai\' should be listed in the project\'s dependencies, not devDependencies.',
@@ -208,7 +207,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: 'import chai from "chai"',
-      options: [{devDependencies: ['*.test.js']}],
+      options: [{ devDependencies: ['*.test.js'] }],
       filename: path.join(process.cwd(), 'foo.tes.js'),
       errors: [{
         message: '\'chai\' should be listed in the project\'s dependencies, not devDependencies.',
@@ -216,7 +215,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: 'import chai from "chai"',
-      options: [{devDependencies: ['*.test.js', '*.spec.js']}],
+      options: [{ devDependencies: ['*.test.js', '*.spec.js'] }],
       filename: 'foo.tes.js',
       errors: [{
         message: '\'chai\' should be listed in the project\'s dependencies, not devDependencies.',
@@ -224,7 +223,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: 'import chai from "chai"',
-      options: [{devDependencies: ['*.test.js', '*.spec.js']}],
+      options: [{ devDependencies: ['*.test.js', '*.spec.js'] }],
       filename: path.join(process.cwd(), 'foo.tes.js'),
       errors: [{
         message: '\'chai\' should be listed in the project\'s dependencies, not devDependencies.',
@@ -232,28 +231,28 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: 'var eslint = require("lodash.isarray")',
-      options: [{optionalDependencies: false}],
+      options: [{ optionalDependencies: false }],
       errors: [{
         message: '\'lodash.isarray\' should be listed in the project\'s dependencies, not optionalDependencies.',
       }],
     }),
     test({
       code: 'import "not-a-dependency"',
-      options: [{packageDir: path.join(__dirname, '../../../')}],
+      options: [{ packageDir: path.join(__dirname, '../../../') }],
       errors: [{
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
     test({
       code: 'import "bar"',
-      options: [{packageDir: path.join(__dirname, './doesn-exist/')}],
+      options: [{ packageDir: path.join(__dirname, './doesn-exist/') }],
       errors: [{
         message: 'The package.json file could not be found.',
       }],
     }),
     test({
       code: 'import foo from "foo"',
-      options: [{packageDir: packageDirWithSyntaxError}],
+      options: [{ packageDir: packageDirWithSyntaxError }],
       errors: [{
         message: 'The package.json file could not be parsed: ' + packageFileWithSyntaxErrorMessage,
       }],
@@ -261,7 +260,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'import leftpad from "left-pad";',
       filename: path.join(packageDirMonoRepoWithNested, 'foo.js'),
-      options: [{packageDir: packageDirMonoRepoWithNested}],
+      options: [{ packageDir: packageDirMonoRepoWithNested }],
       errors: [{
         message: "'left-pad' should be listed in the project's dependencies. Run 'npm i -S left-pad' to add it",
       }],
@@ -276,7 +275,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'import react from "react";',
       filename: path.join(packageDirMonoRepoWithNested, 'foo.js'),
-      options: [{packageDir: packageDirMonoRepoRoot}],
+      options: [{ packageDir: packageDirMonoRepoRoot }],
       errors: [{
         message: "'react' should be listed in the project's dependencies. Run 'npm i -S react' to add it",
       }],
@@ -284,7 +283,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'import "react";',
       filename: path.join(packageDirWithEmpty, 'index.js'),
-      options: [{packageDir: packageDirWithEmpty}],
+      options: [{ packageDir: packageDirWithEmpty }],
       errors: [{
         message: "'react' should be listed in the project's dependencies. Run 'npm i -S react' to add it",
       }],
@@ -295,12 +294,12 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: 'import foo from "@generated/foo"',
-      options: [{bundledDependencies: false}],
+      options: [{ bundledDependencies: false }],
       errors: ["'@generated/foo' should be listed in the project's dependencies. Run 'npm i -S @generated/foo' to add it"],
     }),
     test({
       code: 'import bar from "@generated/bar"',
-      options: [{packageDir: packageDirBundledDepsRaceCondition}],
+      options: [{ packageDir: packageDirBundledDepsRaceCondition }],
       errors: ["'@generated/bar' should be listed in the project's dependencies. Run 'npm i -S @generated/bar' to add it"],
     }),
     test({
@@ -333,13 +332,13 @@ describe('TypeScript', function () {
         valid: [
           test(Object.assign({
             code: 'import type { JSONSchema7Type } from "@types/json-schema";',
-            options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
           }, parserConfig)),
         ],
         invalid: [
           test(Object.assign({
             code: 'import { JSONSchema7Type } from "@types/json-schema";',
-            options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             errors: [{
               message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
             }],
@@ -352,14 +351,14 @@ describe('TypeScript', function () {
         invalid: [
           test(Object.assign({
             code: 'import { JSONSchema7Type } from "@types/json-schema";',
-            options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             errors: [{
               message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
             }],
           }, parserConfig)),
           test(Object.assign({
             code: 'import type { JSONSchema7Type } from "@types/json-schema";',
-            options: [{packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             errors: [{
               message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
             }],
diff --git a/tests/src/rules/no-mutable-exports.js b/tests/src/rules/no-mutable-exports.js
index a4fd8f4c45..2ecae48cdb 100644
--- a/tests/src/rules/no-mutable-exports.js
+++ b/tests/src/rules/no-mutable-exports.js
@@ -1,29 +1,29 @@
-import {test} from '../utils';
-import {RuleTester} from 'eslint';
+import { test } from '../utils';
+import { RuleTester } from 'eslint';
 import rule from 'rules/no-mutable-exports';
 
 const ruleTester = new RuleTester();
 
 ruleTester.run('no-mutable-exports', rule, {
   valid: [
-    test({ code: 'export const count = 1'}),
-    test({ code: 'export function getCount() {}'}),
-    test({ code: 'export class Counter {}'}),
-    test({ code: 'export default count = 1'}),
-    test({ code: 'export default function getCount() {}'}),
-    test({ code: 'export default class Counter {}'}),
-    test({ code: 'const count = 1\nexport { count }'}),
-    test({ code: 'const count = 1\nexport { count as counter }'}),
-    test({ code: 'const count = 1\nexport default count'}),
-    test({ code: 'const count = 1\nexport { count as default }'}),
-    test({ code: 'function getCount() {}\nexport { getCount }'}),
-    test({ code: 'function getCount() {}\nexport { getCount as getCounter }'}),
-    test({ code: 'function getCount() {}\nexport default getCount'}),
-    test({ code: 'function getCount() {}\nexport { getCount as default }'}),
-    test({ code: 'class Counter {}\nexport { Counter }'}),
-    test({ code: 'class Counter {}\nexport { Counter as Count }'}),
-    test({ code: 'class Counter {}\nexport default Counter'}),
-    test({ code: 'class Counter {}\nexport { Counter as default }'}),
+    test({ code: 'export const count = 1' }),
+    test({ code: 'export function getCount() {}' }),
+    test({ code: 'export class Counter {}' }),
+    test({ code: 'export default count = 1' }),
+    test({ code: 'export default function getCount() {}' }),
+    test({ code: 'export default class Counter {}' }),
+    test({ code: 'const count = 1\nexport { count }' }),
+    test({ code: 'const count = 1\nexport { count as counter }' }),
+    test({ code: 'const count = 1\nexport default count' }),
+    test({ code: 'const count = 1\nexport { count as default }' }),
+    test({ code: 'function getCount() {}\nexport { getCount }' }),
+    test({ code: 'function getCount() {}\nexport { getCount as getCounter }' }),
+    test({ code: 'function getCount() {}\nexport default getCount' }),
+    test({ code: 'function getCount() {}\nexport { getCount as default }' }),
+    test({ code: 'class Counter {}\nexport { Counter }' }),
+    test({ code: 'class Counter {}\nexport { Counter as Count }' }),
+    test({ code: 'class Counter {}\nexport default Counter' }),
+    test({ code: 'class Counter {}\nexport { Counter as default }' }),
     test({
       parser: require.resolve('babel-eslint'),
       code: 'export Something from "./something";',
diff --git a/tests/src/rules/no-named-as-default-member.js b/tests/src/rules/no-named-as-default-member.js
index 4845d7bb26..b4f3cf5896 100644
--- a/tests/src/rules/no-named-as-default-member.js
+++ b/tests/src/rules/no-named-as-default-member.js
@@ -1,16 +1,16 @@
 import { test, SYNTAX_CASES } from '../utils';
-import {RuleTester} from 'eslint';
+import { RuleTester } from 'eslint';
 import rule from 'rules/no-named-as-default-member';
 
 const ruleTester = new RuleTester();
 
 ruleTester.run('no-named-as-default-member', rule, {
   valid: [
-    test({code: 'import bar, {foo} from "./bar";'}),
-    test({code: 'import bar from "./bar"; const baz = bar.baz'}),
-    test({code: 'import {foo} from "./bar"; const baz = foo.baz;'}),
-    test({code: 'import * as named from "./named-exports"; const a = named.a'}),
-    test({code: 'import foo from "./default-export-default-property"; const a = foo.default'}),
+    test({ code: 'import bar, {foo} from "./bar";' }),
+    test({ code: 'import bar from "./bar"; const baz = bar.baz' }),
+    test({ code: 'import {foo} from "./bar"; const baz = foo.baz;' }),
+    test({ code: 'import * as named from "./named-exports"; const a = named.a' }),
+    test({ code: 'import foo from "./default-export-default-property"; const a = foo.default' }),
 
     ...SYNTAX_CASES,
   ],
diff --git a/tests/src/rules/no-named-as-default.js b/tests/src/rules/no-named-as-default.js
index ba796cedfa..57b2f53bd8 100644
--- a/tests/src/rules/no-named-as-default.js
+++ b/tests/src/rules/no-named-as-default.js
@@ -1,25 +1,25 @@
 import { test, SYNTAX_CASES } from '../utils';
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-named-as-default');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-named-as-default');
 
 ruleTester.run('no-named-as-default', rule, {
   valid: [
     test({ code: 'import "./malformed.js"' }),
 
-    test({code: 'import bar, { foo } from "./bar";'}),
-    test({code: 'import bar, { foo } from "./empty-folder";'}),
+    test({ code: 'import bar, { foo } from "./bar";' }),
+    test({ code: 'import bar, { foo } from "./empty-folder";' }),
 
     // es7
-    test({ code: 'export bar, { foo } from "./bar";'
-         , parser: require.resolve('babel-eslint') }),
-    test({ code: 'export bar from "./bar";'
-         , parser: require.resolve('babel-eslint') }),
+    test({ code: 'export bar, { foo } from "./bar";',
+      parser: require.resolve('babel-eslint') }),
+    test({ code: 'export bar from "./bar";',
+      parser: require.resolve('babel-eslint') }),
 
     // #566: don't false-positive on `default` itself
-    test({ code: 'export default from "./bar";'
-         , parser: require.resolve('babel-eslint') }),
+    test({ code: 'export default from "./bar";',
+      parser: require.resolve('babel-eslint') }),
 
     ...SYNTAX_CASES,
   ],
@@ -28,27 +28,27 @@ ruleTester.run('no-named-as-default', rule, {
     test({
       code: 'import foo from "./bar";',
       errors: [ {
-        message: 'Using exported name \'foo\' as identifier for default export.'
-      , type: 'ImportDefaultSpecifier' } ] }),
+        message: 'Using exported name \'foo\' as identifier for default export.',
+        type: 'ImportDefaultSpecifier' } ] }),
     test({
       code: 'import foo, { foo as bar } from "./bar";',
       errors: [ {
-        message: 'Using exported name \'foo\' as identifier for default export.'
-      , type: 'ImportDefaultSpecifier' } ] }),
+        message: 'Using exported name \'foo\' as identifier for default export.',
+        type: 'ImportDefaultSpecifier' } ] }),
 
     // es7
     test({
       code: 'export foo from "./bar";',
       parser: require.resolve('babel-eslint'),
       errors: [ {
-        message: 'Using exported name \'foo\' as identifier for default export.'
-      , type: 'ExportDefaultSpecifier' } ] }),
+        message: 'Using exported name \'foo\' as identifier for default export.',
+        type: 'ExportDefaultSpecifier' } ] }),
     test({
       code: 'export foo, { foo as bar } from "./bar";',
       parser: require.resolve('babel-eslint'),
       errors: [ {
-        message: 'Using exported name \'foo\' as identifier for default export.'
-    , type: 'ExportDefaultSpecifier' } ] }),
+        message: 'Using exported name \'foo\' as identifier for default export.',
+        type: 'ExportDefaultSpecifier' } ] }),
 
     test({
       code: 'import foo from "./malformed.js"',
diff --git a/tests/src/rules/no-named-default.js b/tests/src/rules/no-named-default.js
index bffd3dda31..ee8e0959ee 100644
--- a/tests/src/rules/no-named-default.js
+++ b/tests/src/rules/no-named-default.js
@@ -1,13 +1,13 @@
 import { test, SYNTAX_CASES } from '../utils';
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-named-default');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-named-default');
 
 ruleTester.run('no-named-default', rule, {
   valid: [
-    test({code: 'import bar from "./bar";'}),
-    test({code: 'import bar, { foo } from "./bar";'}),
+    test({ code: 'import bar from "./bar";' }),
+    test({ code: 'import bar, { foo } from "./bar";' }),
 
     ...SYNTAX_CASES,
   ],
diff --git a/tests/src/rules/no-named-export.js b/tests/src/rules/no-named-export.js
index a47ad6b7a0..41d0fcd7cf 100644
--- a/tests/src/rules/no-named-export.js
+++ b/tests/src/rules/no-named-export.js
@@ -1,8 +1,8 @@
 import { RuleTester } from 'eslint';
 import { test } from '../utils';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-named-export');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-named-export');
 
 ruleTester.run('no-named-export', rule, {
   valid: [
diff --git a/tests/src/rules/no-nodejs-modules.js b/tests/src/rules/no-nodejs-modules.js
index 32af477dde..3587a71dca 100644
--- a/tests/src/rules/no-nodejs-modules.js
+++ b/tests/src/rules/no-nodejs-modules.js
@@ -2,8 +2,8 @@ import { test } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-nodejs-modules');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-nodejs-modules');
 
 const error = message => ({
   message,
@@ -11,20 +11,20 @@ const error = message => ({
 
 ruleTester.run('no-nodejs-modules', rule, {
   valid: [
-    test({ code: 'import _ from "lodash"'}),
-    test({ code: 'import find from "lodash.find"'}),
-    test({ code: 'import foo from "./foo"'}),
-    test({ code: 'import foo from "../foo"'}),
-    test({ code: 'import foo from "foo"'}),
-    test({ code: 'import foo from "./"'}),
-    test({ code: 'import foo from "@scope/foo"'}),
-    test({ code: 'var _ = require("lodash")'}),
-    test({ code: 'var find = require("lodash.find")'}),
-    test({ code: 'var foo = require("./foo")'}),
-    test({ code: 'var foo = require("../foo")'}),
-    test({ code: 'var foo = require("foo")'}),
-    test({ code: 'var foo = require("./")'}),
-    test({ code: 'var foo = require("@scope/foo")'}),
+    test({ code: 'import _ from "lodash"' }),
+    test({ code: 'import find from "lodash.find"' }),
+    test({ code: 'import foo from "./foo"' }),
+    test({ code: 'import foo from "../foo"' }),
+    test({ code: 'import foo from "foo"' }),
+    test({ code: 'import foo from "./"' }),
+    test({ code: 'import foo from "@scope/foo"' }),
+    test({ code: 'var _ = require("lodash")' }),
+    test({ code: 'var find = require("lodash.find")' }),
+    test({ code: 'var foo = require("./foo")' }),
+    test({ code: 'var foo = require("../foo")' }),
+    test({ code: 'var foo = require("foo")' }),
+    test({ code: 'var foo = require("./")' }),
+    test({ code: 'var foo = require("@scope/foo")' }),
     test({
       code: 'import events from "events"',
       options: [{
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index 826e6408d0..e39f4326d4 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -57,9 +57,9 @@ ruleTester.run('no-restricted-paths', rule, {
     test({
       code: 'notrequire("../server/b.js")',
       filename: testFilePath('./restricted-paths/client/a.js'),
-        options: [ {
-          zones: [ { target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/server' } ],
-        } ] }),
+      options: [ {
+        zones: [ { target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/server' } ],
+      } ] }),
 
     // no config
     test({ code: 'require("../server/b.js")' }),
diff --git a/tests/src/rules/no-self-import.js b/tests/src/rules/no-self-import.js
index 6e255a3eb2..ff1248b43c 100644
--- a/tests/src/rules/no-self-import.js
+++ b/tests/src/rules/no-self-import.js
@@ -2,8 +2,8 @@ import { test, testFilePath } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-self-import');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-self-import');
 
 const error = {
   message: 'Module imports itself.',
diff --git a/tests/src/rules/no-unassigned-import.js b/tests/src/rules/no-unassigned-import.js
index deb43b3262..8724b80d30 100644
--- a/tests/src/rules/no-unassigned-import.js
+++ b/tests/src/rules/no-unassigned-import.js
@@ -3,8 +3,8 @@ import * as path from 'path';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-unassigned-import');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-unassigned-import');
 
 const error = {
   message: 'Imported module should be assigned',
@@ -12,21 +12,21 @@ const error = {
 
 ruleTester.run('no-unassigned-import', rule, {
   valid: [
-    test({ code: 'import _ from "lodash"'}),
-    test({ code: 'import _, {foo} from "lodash"'}),
-    test({ code: 'import _, {foo as bar} from "lodash"'}),
-    test({ code: 'import {foo as bar} from "lodash"'}),
-    test({ code: 'import * as _ from "lodash"'}),
-    test({ code: 'import _ from "./"'}),
-    test({ code: 'const _ = require("lodash")'}),
-    test({ code: 'const {foo} = require("lodash")'}),
-    test({ code: 'const {foo: bar} = require("lodash")'}),
-    test({ code: 'const [a, b] = require("lodash")'}),
-    test({ code: 'const _ = require("./")'}),
-    test({ code: 'foo(require("lodash"))'}),
-    test({ code: 'require("lodash").foo'}),
-    test({ code: 'require("lodash").foo()'}),
-    test({ code: 'require("lodash")()'}),
+    test({ code: 'import _ from "lodash"' }),
+    test({ code: 'import _, {foo} from "lodash"' }),
+    test({ code: 'import _, {foo as bar} from "lodash"' }),
+    test({ code: 'import {foo as bar} from "lodash"' }),
+    test({ code: 'import * as _ from "lodash"' }),
+    test({ code: 'import _ from "./"' }),
+    test({ code: 'const _ = require("lodash")' }),
+    test({ code: 'const {foo} = require("lodash")' }),
+    test({ code: 'const {foo: bar} = require("lodash")' }),
+    test({ code: 'const [a, b] = require("lodash")' }),
+    test({ code: 'const _ = require("./")' }),
+    test({ code: 'foo(require("lodash"))' }),
+    test({ code: 'require("lodash").foo' }),
+    test({ code: 'require("lodash").foo()' }),
+    test({ code: 'require("lodash")()' }),
     test({
       code: 'import "app.css"',
       options: [{ 'allow': ['**/*.css'] }],
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 61b03de5c2..da7d4dc5ae 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -6,8 +6,8 @@ import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-  , rule = require('rules/no-unresolved');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-unresolved');
 
 function runResolverTests(resolver) {
   // redefine 'test' to set a resolver
@@ -29,8 +29,8 @@ function runResolverTests(resolver) {
       rest({ code: "import bar from './bar.js';" }),
       rest({ code: "import {someThing} from './test-module';" }),
       rest({ code: "import fs from 'fs';" }),
-      rest({ code: "import('fs');"
-           , parser: require.resolve('babel-eslint') }),
+      rest({ code: "import('fs');",
+        parser: require.resolve('babel-eslint') }),
 
       rest({ code: 'import * as foo from "a"' }),
 
@@ -39,50 +39,50 @@ function runResolverTests(resolver) {
       rest({ code: 'let foo; export { foo }' }),
 
       // stage 1 proposal for export symmetry,
-      rest({ code: 'export * as bar from "./bar"'
-           , parser: require.resolve('babel-eslint') }),
-      rest({ code: 'export bar from "./bar"'
-           , parser: require.resolve('babel-eslint') }),
+      rest({ code: 'export * as bar from "./bar"',
+        parser: require.resolve('babel-eslint') }),
+      rest({ code: 'export bar from "./bar"',
+        parser: require.resolve('babel-eslint') }),
       rest({ code: 'import foo from "./jsx/MyUnCoolComponent.jsx"' }),
 
       // commonjs setting
-      rest({ code: 'var foo = require("./bar")'
-           , options: [{ commonjs: true }]}),
-      rest({ code: 'require("./bar")'
-           , options: [{ commonjs: true }]}),
-      rest({ code: 'require("./does-not-exist")'
-           , options: [{ commonjs: false }]}),
+      rest({ code: 'var foo = require("./bar")',
+        options: [{ commonjs: true }] }),
+      rest({ code: 'require("./bar")',
+        options: [{ commonjs: true }] }),
+      rest({ code: 'require("./does-not-exist")',
+        options: [{ commonjs: false }] }),
       rest({ code: 'require("./does-not-exist")' }),
 
       // amd setting
-      rest({ code: 'require(["./bar"], function (bar) {})'
-           , options: [{ amd: true }]}),
-      rest({ code: 'define(["./bar"], function (bar) {})'
-           , options: [{ amd: true }]}),
-      rest({ code: 'require(["./does-not-exist"], function (bar) {})'
-           , options: [{ amd: false }]}),
+      rest({ code: 'require(["./bar"], function (bar) {})',
+        options: [{ amd: true }] }),
+      rest({ code: 'define(["./bar"], function (bar) {})',
+        options: [{ amd: true }] }),
+      rest({ code: 'require(["./does-not-exist"], function (bar) {})',
+        options: [{ amd: false }] }),
       // magic modules: http://git.io/vByan
-      rest({ code: 'define(["require", "exports", "module"], function (r, e, m) { })'
-           , options: [{ amd: true }]}),
+      rest({ code: 'define(["require", "exports", "module"], function (r, e, m) { })',
+        options: [{ amd: true }] }),
 
       // don't validate without callback param
-      rest({ code: 'require(["./does-not-exist"])'
-           , options: [{ amd: true }]}),
+      rest({ code: 'require(["./does-not-exist"])',
+        options: [{ amd: true }] }),
       rest({ code: 'define(["./does-not-exist"], function (bar) {})' }),
 
       // stress tests
-      rest({ code: 'require("./does-not-exist", "another arg")'
-           , options: [{ commonjs: true, amd: true }]}),
-      rest({ code: 'proxyquire("./does-not-exist")'
-           , options: [{ commonjs: true, amd: true }]}),
-      rest({ code: '(function() {})("./does-not-exist")'
-           , options: [{ commonjs: true, amd: true }]}),
-      rest({ code: 'define([0, foo], function (bar) {})'
-           , options: [{ amd: true }]}),
-      rest({ code: 'require(0)'
-           , options: [{ commonjs: true }]}),
-      rest({ code: 'require(foo)'
-           , options: [{ commonjs: true }]}),
+      rest({ code: 'require("./does-not-exist", "another arg")',
+        options: [{ commonjs: true, amd: true }] }),
+      rest({ code: 'proxyquire("./does-not-exist")',
+        options: [{ commonjs: true, amd: true }] }),
+      rest({ code: '(function() {})("./does-not-exist")',
+        options: [{ commonjs: true, amd: true }] }),
+      rest({ code: 'define([0, foo], function (bar) {})',
+        options: [{ amd: true }] }),
+      rest({ code: 'require(0)',
+        options: [{ commonjs: true }] }),
+      rest({ code: 'require(foo)',
+        options: [{ commonjs: true }] }),
     ],
 
     invalid: [
@@ -96,50 +96,50 @@ function runResolverTests(resolver) {
 
       rest({
         code: "import bar from './baz';",
-        errors: [{ message: "Unable to resolve path to module './baz'."
-                 , type: 'Literal' }],
+        errors: [{ message: "Unable to resolve path to module './baz'.",
+          type: 'Literal' }],
       }),
-      rest({ code: "import bar from './baz';"
-           , errors: [{ message: "Unable to resolve path to module './baz'."
-                      , type: 'Literal',
-                      }] }),
+      rest({ code: "import bar from './baz';",
+        errors: [{ message: "Unable to resolve path to module './baz'.",
+          type: 'Literal',
+        }] }),
       rest({
         code: "import bar from './empty-folder';",
-        errors: [{ message: "Unable to resolve path to module './empty-folder'."
-                 , type: 'Literal',
-                 }]}),
+        errors: [{ message: "Unable to resolve path to module './empty-folder'.",
+          type: 'Literal',
+        }] }),
 
       // sanity check that this module is _not_ found without proper settings
       rest({
         code: "import { DEEP } from 'in-alternate-root';",
         errors: [{ message: 'Unable to resolve path to ' +
-                            "module 'in-alternate-root'."
-                 , type: 'Literal',
-                 }]}),
+                            "module 'in-alternate-root'.",
+        type: 'Literal',
+        }] }),
       rest({
-      code: "import('in-alternate-root').then(function({DEEP}){});",
-      errors: [{ message: 'Unable to resolve path to ' +
-                          "module 'in-alternate-root'."
-                , type: 'Literal',
-                }],
-      parser: require.resolve('babel-eslint')}),
-
-      rest({ code: 'export { foo } from "./does-not-exist"'
-           , errors: ["Unable to resolve path to module './does-not-exist'."] }),
+        code: "import('in-alternate-root').then(function({DEEP}){});",
+        errors: [{ message: 'Unable to resolve path to ' +
+                          "module 'in-alternate-root'.",
+        type: 'Literal',
+        }],
+        parser: require.resolve('babel-eslint') }),
+
+      rest({ code: 'export { foo } from "./does-not-exist"',
+        errors: ["Unable to resolve path to module './does-not-exist'."] }),
       rest({
         code: 'export * from "./does-not-exist"',
         errors: ["Unable to resolve path to module './does-not-exist'."],
       }),
 
       // export symmetry proposal
-      rest({ code: 'export * as bar from "./does-not-exist"'
-           , parser: require.resolve('babel-eslint')
-           , errors: ["Unable to resolve path to module './does-not-exist'."],
-           }),
-      rest({ code: 'export bar from "./does-not-exist"'
-           , parser: require.resolve('babel-eslint')
-           , errors: ["Unable to resolve path to module './does-not-exist'."],
-           }),
+      rest({ code: 'export * as bar from "./does-not-exist"',
+        parser: require.resolve('babel-eslint'),
+        errors: ["Unable to resolve path to module './does-not-exist'."],
+      }),
+      rest({ code: 'export bar from "./does-not-exist"',
+        parser: require.resolve('babel-eslint'),
+        errors: ["Unable to resolve path to module './does-not-exist'."],
+      }),
 
       // commonjs setting
       rest({
@@ -204,10 +204,10 @@ function runResolverTests(resolver) {
       }),
     ],
     invalid: [
-        rest({
-          code: 'import bar from "./foo.json"',
-          errors: ["Unable to resolve path to module './foo.json'."],
-        }),
+      rest({
+        code: 'import bar from "./foo.json"',
+        errors: ["Unable to resolve path to module './foo.json'."],
+      }),
     ],
   });
 
@@ -245,7 +245,7 @@ ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
       settings: {
         'import/resolve': {
           'paths': [path.join( process.cwd()
-                             , 'tests', 'files', 'alternate-root')],
+            , 'tests', 'files', 'alternate-root')],
         },
       },
     }),
@@ -253,10 +253,10 @@ ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
     test({
       code: "import { DEEP } from 'in-alternate-root'; " +
             "import { bar } from 'src-bar';",
-      settings: {'import/resolve': { 'paths': [
+      settings: { 'import/resolve': { 'paths': [
         path.join('tests', 'files', 'src-root'),
         path.join('tests', 'files', 'alternate-root'),
-      ]}}}),
+      ] } } }),
 
     test({
       code: 'import * as foo from "jsx-module/foo"',
@@ -302,34 +302,34 @@ ruleTester.run('no-unresolved ignore list', rule, {
   valid: [
     test({
       code: 'import "./malformed.js"',
-      options: [{ ignore: ['.png$', '.gif$']}],
+      options: [{ ignore: ['.png$', '.gif$'] }],
     }),
     test({
       code: 'import "./test.giffy"',
-      options: [{ ignore: ['.png$', '.gif$']}],
+      options: [{ ignore: ['.png$', '.gif$'] }],
     }),
 
     test({
       code: 'import "./test.gif"',
-      options: [{ ignore: ['.png$', '.gif$']}],
+      options: [{ ignore: ['.png$', '.gif$'] }],
     }),
 
     test({
       code: 'import "./test.png"',
-      options: [{ ignore: ['.png$', '.gif$']}],
+      options: [{ ignore: ['.png$', '.gif$'] }],
     }),
   ],
 
   invalid:[
     test({
       code: 'import "./test.gif"',
-      options: [{ ignore: ['.png$']}],
+      options: [{ ignore: ['.png$'] }],
       errors: [ "Unable to resolve path to module './test.gif'." ],
     }),
 
     test({
       code: 'import "./test.png"',
-      options: [{ ignore: ['.gif$']}],
+      options: [{ ignore: ['.gif$'] }],
       errors: [ "Unable to resolve path to module './test.png'." ],
     }),
   ],
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 99120544b6..0e7826a523 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -5,10 +5,10 @@ import typescriptConfig from '../../../config/typescript';
 import { RuleTester } from 'eslint';
 import fs from 'fs';
 
-const ruleTester = new RuleTester()
-    , typescriptRuleTester = new RuleTester(typescriptConfig)
-    , jsxRuleTester = new RuleTester(jsxConfig)
-    , rule = require('rules/no-unused-modules');
+const ruleTester = new RuleTester();
+const typescriptRuleTester = new RuleTester(typescriptConfig);
+const jsxRuleTester = new RuleTester(jsxConfig);
+const rule = require('rules/no-unused-modules');
 
 const error = message => ({ message });
 
@@ -105,33 +105,33 @@ ruleTester.run('no-unused-modules', rule, {
   valid: [
 
     test({ options: unusedExportsOptions,
-           code: 'import { o2 } from "./file-o";export default () => 12',
-           filename: testFilePath('./no-unused-modules/file-a.js')}),
+      code: 'import { o2 } from "./file-o";export default () => 12',
+      filename: testFilePath('./no-unused-modules/file-a.js') }),
     test({ options: unusedExportsOptions,
-           code: 'export const b = 2',
-           filename: testFilePath('./no-unused-modules/file-b.js')}),
+      code: 'export const b = 2',
+      filename: testFilePath('./no-unused-modules/file-b.js') }),
     test({ options: unusedExportsOptions,
-           code: 'const c1 = 3; function c2() { return 3 }; export { c1, c2 }',
-           filename: testFilePath('./no-unused-modules/file-c.js')}),
+      code: 'const c1 = 3; function c2() { return 3 }; export { c1, c2 }',
+      filename: testFilePath('./no-unused-modules/file-c.js') }),
     test({ options: unusedExportsOptions,
-           code: 'export function d() { return 4 }',
-           filename: testFilePath('./no-unused-modules/file-d.js')}),
+      code: 'export function d() { return 4 }',
+      filename: testFilePath('./no-unused-modules/file-d.js') }),
     test({ options: unusedExportsOptions,
-           code: 'export class q { q0() {} }',
-           filename: testFilePath('./no-unused-modules/file-q.js')}),
+      code: 'export class q { q0() {} }',
+      filename: testFilePath('./no-unused-modules/file-q.js') }),
     test({ options: unusedExportsOptions,
-           code: 'const e0 = 5; export { e0 as e }',
-           filename: testFilePath('./no-unused-modules/file-e.js')}),
+      code: 'const e0 = 5; export { e0 as e }',
+      filename: testFilePath('./no-unused-modules/file-e.js') }),
     test({ options: unusedExportsOptions,
-           code: 'const l0 = 5; const l = 10; export { l0 as l1, l }; export default () => {}',
-           filename: testFilePath('./no-unused-modules/file-l.js')}),
+      code: 'const l0 = 5; const l = 10; export { l0 as l1, l }; export default () => {}',
+      filename: testFilePath('./no-unused-modules/file-l.js') }),
     test({ options: unusedExportsOptions,
-           code: 'const o0 = 0; const o1 = 1; export { o0, o1 as o2 }; export default () => {}',
-           filename: testFilePath('./no-unused-modules/file-o.js')}),
-    ],
+      code: 'const o0 = 0; const o1 = 1; export { o0, o1 as o2 }; export default () => {}',
+      filename: testFilePath('./no-unused-modules/file-o.js') }),
+  ],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: `import eslint from 'eslint'
+      code: `import eslint from 'eslint'
            import fileA from './file-a'
            import { b } from './file-b'
            import { c1, c2 } from './file-c'
@@ -144,17 +144,17 @@ ruleTester.run('no-unused-modules', rule, {
            export { default, o0, o3 } from './file-o'
            export { p } from './file-p'
            import s from './file-s'`,
-           filename: testFilePath('./no-unused-modules/file-0.js'),
-           errors: [
-             error(`exported declaration 'default' not used within other modules`),
-             error(`exported declaration 'o0' not used within other modules`),
-             error(`exported declaration 'o3' not used within other modules`),
-             error(`exported declaration 'p' not used within other modules`),
-           ]}),
-    test({ options: unusedExportsOptions,
-           code: `const n0 = 'n0'; const n1 = 42; export { n0, n1 }; export default () => {}`,
-           filename: testFilePath('./no-unused-modules/file-n.js'),
-           errors: [error(`exported declaration 'default' not used within other modules`)]}),
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+      errors: [
+        error(`exported declaration 'default' not used within other modules`),
+        error(`exported declaration 'o0' not used within other modules`),
+        error(`exported declaration 'o3' not used within other modules`),
+        error(`exported declaration 'p' not used within other modules`),
+      ] }),
+    test({ options: unusedExportsOptions,
+      code: `const n0 = 'n0'; const n1 = 42; export { n0, n1 }; export default () => {}`,
+      filename: testFilePath('./no-unused-modules/file-n.js'),
+      errors: [error(`exported declaration 'default' not used within other modules`)] }),
   ],
 });
 
@@ -163,36 +163,36 @@ ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: 'export default () => 13',
-           filename: testFilePath('./no-unused-modules/file-f.js'),
-           errors: [error(`exported declaration 'default' not used within other modules`)]}),
+      code: 'export default () => 13',
+      filename: testFilePath('./no-unused-modules/file-f.js'),
+      errors: [error(`exported declaration 'default' not used within other modules`)] }),
     test({ options: unusedExportsOptions,
-           code: 'export const g = 2',
-           filename: testFilePath('./no-unused-modules/file-g.js'),
-           errors: [error(`exported declaration 'g' not used within other modules`)]}),
+      code: 'export const g = 2',
+      filename: testFilePath('./no-unused-modules/file-g.js'),
+      errors: [error(`exported declaration 'g' not used within other modules`)] }),
     test({ options: unusedExportsOptions,
-           code: 'const h1 = 3; function h2() { return 3 }; const h3 = true; export { h1, h2, h3 }',
-           filename: testFilePath('./no-unused-modules/file-h.js'),
-           errors: [error(`exported declaration 'h1' not used within other modules`)]}),
+      code: 'const h1 = 3; function h2() { return 3 }; const h3 = true; export { h1, h2, h3 }',
+      filename: testFilePath('./no-unused-modules/file-h.js'),
+      errors: [error(`exported declaration 'h1' not used within other modules`)] }),
     test({ options: unusedExportsOptions,
-           code: 'const i1 = 3; function i2() { return 3 }; export { i1, i2 }',
-           filename: testFilePath('./no-unused-modules/file-i.js'),
-           errors: [
-             error(`exported declaration 'i1' not used within other modules`),
-             error(`exported declaration 'i2' not used within other modules`),
-           ]}),
+      code: 'const i1 = 3; function i2() { return 3 }; export { i1, i2 }',
+      filename: testFilePath('./no-unused-modules/file-i.js'),
+      errors: [
+        error(`exported declaration 'i1' not used within other modules`),
+        error(`exported declaration 'i2' not used within other modules`),
+      ] }),
     test({ options: unusedExportsOptions,
-           code: 'export function j() { return 4 }',
-           filename: testFilePath('./no-unused-modules/file-j.js'),
-           errors: [error(`exported declaration 'j' not used within other modules`)]}),
+      code: 'export function j() { return 4 }',
+      filename: testFilePath('./no-unused-modules/file-j.js'),
+      errors: [error(`exported declaration 'j' not used within other modules`)] }),
     test({ options: unusedExportsOptions,
-           code: 'export class q { q0() {} }',
-           filename: testFilePath('./no-unused-modules/file-q.js'),
-           errors: [error(`exported declaration 'q' not used within other modules`)]}),
+      code: 'export class q { q0() {} }',
+      filename: testFilePath('./no-unused-modules/file-q.js'),
+      errors: [error(`exported declaration 'q' not used within other modules`)] }),
     test({ options: unusedExportsOptions,
-           code: 'const k0 = 5; export { k0 as k }',
-           filename: testFilePath('./no-unused-modules/file-k.js'),
-           errors: [error(`exported declaration 'k' not used within other modules`)]}),
+      code: 'const k0 = 5; export { k0 as k }',
+      filename: testFilePath('./no-unused-modules/file-k.js'),
+      errors: [error(`exported declaration 'k' not used within other modules`)] }),
   ],
 });
 
@@ -200,22 +200,22 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `export { default } from './file-o'`,
-           filename: testFilePath('./no-unused-modules/file-s.js')}),
+      code: `export { default } from './file-o'`,
+      filename: testFilePath('./no-unused-modules/file-s.js') }),
   ],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: `export { k } from '${testFilePath('./no-unused-modules/file-k.js')}'`,
-           filename: testFilePath('./no-unused-modules/file-j.js'),
-           errors: [error(`exported declaration 'k' not used within other modules`)]}),
+      code: `export { k } from '${testFilePath('./no-unused-modules/file-k.js')}'`,
+      filename: testFilePath('./no-unused-modules/file-j.js'),
+      errors: [error(`exported declaration 'k' not used within other modules`)] }),
   ],
 });
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: 'const k0 = 5; export { k0 as k }',
-           filename: testFilePath('./no-unused-modules/file-k.js')}),
+      code: 'const k0 = 5; export { k0 as k }',
+      filename: testFilePath('./no-unused-modules/file-k.js') }),
   ],
   invalid: [],
 });
@@ -225,23 +225,23 @@ ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
       code: 'export default () => 14',
-      filename: testFilePath('./no-unused-modules/file-ignored-a.js')}),
+      filename: testFilePath('./no-unused-modules/file-ignored-a.js') }),
     test({ options: unusedExportsOptions,
       code: 'export const b = 2',
-      filename: testFilePath('./no-unused-modules/file-ignored-b.js')}),
+      filename: testFilePath('./no-unused-modules/file-ignored-b.js') }),
     test({ options: unusedExportsOptions,
       code: 'const c1 = 3; function c2() { return 3 }; export { c1, c2 }',
-      filename: testFilePath('./no-unused-modules/file-ignored-c.js')}),
+      filename: testFilePath('./no-unused-modules/file-ignored-c.js') }),
     test({ options: unusedExportsOptions,
       code: 'export function d() { return 4 }',
-      filename: testFilePath('./no-unused-modules/file-ignored-d.js')}),
+      filename: testFilePath('./no-unused-modules/file-ignored-d.js') }),
     test({ options: unusedExportsOptions,
       code: 'const f = 5; export { f as e }',
-      filename: testFilePath('./no-unused-modules/file-ignored-e.js')}),
+      filename: testFilePath('./no-unused-modules/file-ignored-e.js') }),
     test({ options: unusedExportsOptions,
       code: 'const l0 = 5; const l = 10; export { l0 as l1, l }; export default () => {}',
-      filename: testFilePath('./no-unused-modules/file-ignored-l.js')}),
-    ],
+      filename: testFilePath('./no-unused-modules/file-ignored-l.js') }),
+  ],
   invalid: [],
 });
 
@@ -250,26 +250,26 @@ ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
       code: `import { f } from '${testFilePath('./no-unused-modules/file-f.js')}'`,
-      filename: testFilePath('./no-unused-modules/file-0.js')}),
-    ],
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
+  ],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: 'export default () => 15',
-           filename: testFilePath('./no-unused-modules/file-f.js'),
-           errors: [error(`exported declaration 'default' not used within other modules`)]}),
-    ],
+      code: 'export default () => 15',
+      filename: testFilePath('./no-unused-modules/file-f.js'),
+      errors: [error(`exported declaration 'default' not used within other modules`)] }),
+  ],
 });
 
 // add default import for file with default export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `import f from '${testFilePath('./no-unused-modules/file-f.js')}'`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `import f from '${testFilePath('./no-unused-modules/file-f.js')}'`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
     test({ options: unusedExportsOptions,
-           code: 'export default () => 16',
-           filename: testFilePath('./no-unused-modules/file-f.js')}),
-    ],
+      code: 'export default () => 16',
+      filename: testFilePath('./no-unused-modules/file-f.js') }),
+  ],
   invalid: [],
 });
 
@@ -277,26 +277,26 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `import g from '${testFilePath('./no-unused-modules/file-g.js')}';import {h} from '${testFilePath('./no-unused-modules/file-gg.js')}'`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
-    ],
+      code: `import g from '${testFilePath('./no-unused-modules/file-g.js')}';import {h} from '${testFilePath('./no-unused-modules/file-gg.js')}'`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
+  ],
   invalid: [
     test({ options: unusedExportsOptions,
-            code: 'export const g = 2',
-            filename: testFilePath('./no-unused-modules/file-g.js'),
-            errors: [error(`exported declaration 'g' not used within other modules`)]})],
+      code: 'export const g = 2',
+      filename: testFilePath('./no-unused-modules/file-g.js'),
+      errors: [error(`exported declaration 'g' not used within other modules`)] })],
 });
 
 // add named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `import { g } from '${testFilePath('./no-unused-modules/file-g.js')}'; import eslint from 'eslint'`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `import { g } from '${testFilePath('./no-unused-modules/file-g.js')}'; import eslint from 'eslint'`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
     test({ options: unusedExportsOptions,
-            code: 'export const g = 2',
-            filename: testFilePath('./no-unused-modules/file-g.js')}),
-    ],
+      code: 'export const g = 2',
+      filename: testFilePath('./no-unused-modules/file-g.js') }),
+  ],
   invalid: [],
 });
 
@@ -304,14 +304,14 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `import { c } from '${testFilePath('./no-unused-modules/file-b.js')}'`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `import { c } from '${testFilePath('./no-unused-modules/file-b.js')}'`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
   ],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: 'export const b = 2',
-           filename: testFilePath('./no-unused-modules/file-b.js'),
-           errors: [error(`exported declaration 'b' not used within other modules`)]}),
+      code: 'export const b = 2',
+      filename: testFilePath('./no-unused-modules/file-b.js'),
+      errors: [error(`exported declaration 'b' not used within other modules`)] }),
   ],
 });
 
@@ -319,12 +319,12 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `import { g as g1 } from '${testFilePath('./no-unused-modules/file-g.js')}'; import eslint from 'eslint'`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `import { g as g1 } from '${testFilePath('./no-unused-modules/file-g.js')}'; import eslint from 'eslint'`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
     test({ options: unusedExportsOptions,
-            code: 'export const g = 2',
-            filename: testFilePath('./no-unused-modules/file-g.js')}),
-    ],
+      code: 'export const g = 2',
+      filename: testFilePath('./no-unused-modules/file-g.js') }),
+  ],
   invalid: [],
 });
 
@@ -332,14 +332,14 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `import { g1 as g } from '${testFilePath('./no-unused-modules/file-g.js')}'`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `import { g1 as g } from '${testFilePath('./no-unused-modules/file-g.js')}'`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
   ],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: 'export const g = 2',
-           filename: testFilePath('./no-unused-modules/file-g.js'),
-           errors: [error(`exported declaration 'g' not used within other modules`)]}),
+      code: 'export const g = 2',
+      filename: testFilePath('./no-unused-modules/file-g.js'),
+      errors: [error(`exported declaration 'g' not used within other modules`)] }),
   ],
 });
 
@@ -347,14 +347,14 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `import { a1, a2 } from '${testFilePath('./no-unused-modules/file-a.js')}'`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `import { a1, a2 } from '${testFilePath('./no-unused-modules/file-a.js')}'`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
   ],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: 'export default () => 17',
-           filename: testFilePath('./no-unused-modules/file-a.js'),
-           errors: [error(`exported declaration 'default' not used within other modules`)]}),
+      code: 'export default () => 17',
+      filename: testFilePath('./no-unused-modules/file-a.js'),
+      errors: [error(`exported declaration 'default' not used within other modules`)] }),
   ],
 });
 
@@ -363,23 +363,23 @@ ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
-           filename: testFilePath('./no-unused-modules/file-m.js'),
-           errors: [
-             error(`exported declaration 'm1' not used within other modules`),
-             error(`exported declaration 'm' not used within other modules`),
-             error(`exported declaration 'default' not used within other modules`),
-          ]}),
+      code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
+      filename: testFilePath('./no-unused-modules/file-m.js'),
+      errors: [
+        error(`exported declaration 'm1' not used within other modules`),
+        error(`exported declaration 'm' not used within other modules`),
+        error(`exported declaration 'default' not used within other modules`),
+      ] }),
   ],
 });
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `import * as m from '${testFilePath('./no-unused-modules/file-m.js')}'; import unknown from 'unknown-module'`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `import * as m from '${testFilePath('./no-unused-modules/file-m.js')}'; import unknown from 'unknown-module'`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
     test({ options: unusedExportsOptions,
-           code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
-           filename: testFilePath('./no-unused-modules/file-m.js')}),
+      code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
+      filename: testFilePath('./no-unused-modules/file-m.js') }),
   ],
   invalid: [],
 });
@@ -388,8 +388,8 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `/* import * as m from '${testFilePath('./no-unused-modules/file-m.js')}' */`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `/* import * as m from '${testFilePath('./no-unused-modules/file-m.js')}' */`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
   ],
   invalid: [
     test({ options: unusedExportsOptions,
@@ -399,15 +399,15 @@ ruleTester.run('no-unused-modules', rule, {
         error(`exported declaration 'm1' not used within other modules`),
         error(`exported declaration 'm' not used within other modules`),
         error(`exported declaration 'default' not used within other modules`),
-     ]}),
+      ] }),
   ],
 });
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-           code: `export * from '${testFilePath('./no-unused-modules/file-m.js')}';`,
-           filename: testFilePath('./no-unused-modules/file-0.js')}),
+      code: `export * from '${testFilePath('./no-unused-modules/file-m.js')}';`,
+      filename: testFilePath('./no-unused-modules/file-0.js') }),
   ],
   invalid: [],
 });
@@ -415,9 +415,9 @@ ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
-           filename: testFilePath('./no-unused-modules/file-m.js'),
-           errors: [error(`exported declaration 'default' not used within other modules`)]}),
+      code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
+      filename: testFilePath('./no-unused-modules/file-m.js'),
+      errors: [error(`exported declaration 'default' not used within other modules`)] }),
   ],
 });
 
@@ -425,16 +425,16 @@ ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: `export { m1, m} from '${testFilePath('./no-unused-modules/file-m.js')}';`,
-           filename: testFilePath('./no-unused-modules/file-0.js'),
-           errors: [
-             error(`exported declaration 'm1' not used within other modules`),
-             error(`exported declaration 'm' not used within other modules`),
-           ]}),
+      code: `export { m1, m} from '${testFilePath('./no-unused-modules/file-m.js')}';`,
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+      errors: [
+        error(`exported declaration 'm1' not used within other modules`),
+        error(`exported declaration 'm' not used within other modules`),
+      ] }),
     test({ options: unusedExportsOptions,
-           code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
-           filename: testFilePath('./no-unused-modules/file-m.js'),
-           errors: [error(`exported declaration 'default' not used within other modules`)]}),
+      code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
+      filename: testFilePath('./no-unused-modules/file-m.js'),
+      errors: [error(`exported declaration 'default' not used within other modules`)] }),
   ],
 });
 
@@ -446,16 +446,16 @@ ruleTester.run('no-unused-modules', rule, {
   ],
   invalid: [
     test({ options: unusedExportsOptions,
-           code: `export { default, m1 } from '${testFilePath('./no-unused-modules/file-m.js')}';`,
-           filename: testFilePath('./no-unused-modules/file-0.js'),
-           errors: [
-             error(`exported declaration 'default' not used within other modules`),
-             error(`exported declaration 'm1' not used within other modules`),
-           ]}),
+      code: `export { default, m1 } from '${testFilePath('./no-unused-modules/file-m.js')}';`,
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+      errors: [
+        error(`exported declaration 'default' not used within other modules`),
+        error(`exported declaration 'm1' not used within other modules`),
+      ] }),
     test({ options: unusedExportsOptions,
-           code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
-           filename: testFilePath('./no-unused-modules/file-m.js'),
-           errors: [error(`exported declaration 'm' not used within other modules`)]}),
+      code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
+      filename: testFilePath('./no-unused-modules/file-m.js'),
+      errors: [error(`exported declaration 'm' not used within other modules`)] }),
   ],
 });
 
@@ -463,9 +463,9 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-          code: `export const a = 5;export const b = 't1'`,
-          filename: testFilePath('./no-unused-modules/import-export-1.js'),
-        }),
+      code: `export const a = 5;export const b = 't1'`,
+      filename: testFilePath('./no-unused-modules/import-export-1.js'),
+    }),
   ],
   invalid: [],
 });
@@ -475,10 +475,10 @@ describe('renameDefault', () => {
     valid: [
       test({ options: unusedExportsOptions,
         code: 'export { default as Component } from "./Component"',
-        filename: testFilePath('./no-unused-modules/renameDefault/components.js')}),
+        filename: testFilePath('./no-unused-modules/renameDefault/components.js') }),
       test({ options: unusedExportsOptions,
         code: 'export default function Component() {}',
-        filename: testFilePath('./no-unused-modules/renameDefault/Component.js')}),
+        filename: testFilePath('./no-unused-modules/renameDefault/Component.js') }),
     ],
     invalid: [],
   });
@@ -486,10 +486,10 @@ describe('renameDefault', () => {
     valid: [
       test({ options: unusedExportsOptions,
         code: 'export { default as ComponentA } from "./ComponentA";export { default as ComponentB } from "./ComponentB";',
-        filename: testFilePath('./no-unused-modules/renameDefault-2/components.js')}),
+        filename: testFilePath('./no-unused-modules/renameDefault-2/components.js') }),
       test({ options: unusedExportsOptions,
         code: 'export default function ComponentA() {};',
-        filename: testFilePath('./no-unused-modules/renameDefault-2/ComponentA.js')}),
+        filename: testFilePath('./no-unused-modules/renameDefault-2/ComponentA.js') }),
     ],
     invalid: [],
   });
@@ -497,18 +497,18 @@ describe('renameDefault', () => {
 
 describe('test behaviour for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', {encoding: 'utf8'});
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', { encoding: 'utf8' });
   });
 
   // add import in newly created file
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
-             code: `import * as m from '${testFilePath('./no-unused-modules/file-m.js')}'`,
-             filename: testFilePath('./no-unused-modules/file-added-0.js')}),
+        code: `import * as m from '${testFilePath('./no-unused-modules/file-m.js')}'`,
+        filename: testFilePath('./no-unused-modules/file-added-0.js') }),
       test({ options: unusedExportsOptions,
-             code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
-             filename: testFilePath('./no-unused-modules/file-m.js')}),
+        code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
+        filename: testFilePath('./no-unused-modules/file-m.js') }),
     ],
     invalid: [],
   });
@@ -518,20 +518,20 @@ describe('test behaviour for new file', () => {
     valid: [],
     invalid: [
       test({ options: unusedExportsOptions,
-             code: `export default () => {2}`,
-             filename: testFilePath('./no-unused-modules/file-added-0.js'),
-             errors: [error(`exported declaration 'default' not used within other modules`)]}),
-      ],
+        code: `export default () => {2}`,
+        filename: testFilePath('./no-unused-modules/file-added-0.js'),
+        errors: [error(`exported declaration 'default' not used within other modules`)] }),
+    ],
   });
 
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
-             code: `import def from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
-             filename: testFilePath('./no-unused-modules/file-0.js')}),
+        code: `import def from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
+        filename: testFilePath('./no-unused-modules/file-0.js') }),
       test({ options: unusedExportsOptions,
-             code: `export default () => {}`,
-             filename: testFilePath('./no-unused-modules/file-added-0.js')}),
+        code: `export default () => {}`,
+        filename: testFilePath('./no-unused-modules/file-added-0.js') }),
     ],
     invalid: [],
   });
@@ -540,8 +540,8 @@ describe('test behaviour for new file', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
-             code: `export * from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
-             filename: testFilePath('./no-unused-modules/file-0.js')}),
+        code: `export * from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
+        filename: testFilePath('./no-unused-modules/file-0.js') }),
       // Test export * from 'external-compiled-library'
       test({ options: unusedExportsOptions,
         code: `export * from 'external-compiled-library'`,
@@ -550,16 +550,16 @@ describe('test behaviour for new file', () => {
     ],
     invalid: [
       test({ options: unusedExportsOptions,
-             code: `export const z = 'z';export default () => {}`,
-             filename: testFilePath('./no-unused-modules/file-added-0.js'),
-             errors: [error(`exported declaration 'default' not used within other modules`)]}),
+        code: `export const z = 'z';export default () => {}`,
+        filename: testFilePath('./no-unused-modules/file-added-0.js'),
+        errors: [error(`exported declaration 'default' not used within other modules`)] }),
     ],
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
-             code: `export const a = 2`,
-             filename: testFilePath('./no-unused-modules/file-added-0.js')}),
+        code: `export const a = 2`,
+        filename: testFilePath('./no-unused-modules/file-added-0.js') }),
     ],
     invalid: [],
   });
@@ -569,35 +569,35 @@ describe('test behaviour for new file', () => {
     valid: [],
     invalid: [
       test({ options: unusedExportsOptions,
-             code: `export { a } from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
-             filename: testFilePath('./no-unused-modules/file-0.js'),
-             errors: [error(`exported declaration 'a' not used within other modules`)]}),
+        code: `export { a } from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
+        filename: testFilePath('./no-unused-modules/file-0.js'),
+        errors: [error(`exported declaration 'a' not used within other modules`)] }),
       test({ options: unusedExportsOptions,
-             code: `export const z = 'z';export default () => {}`,
-             filename: testFilePath('./no-unused-modules/file-added-0.js'),
-             errors: [
-               error(`exported declaration 'z' not used within other modules`),
-               error(`exported declaration 'default' not used within other modules`),
-            ]}),
+        code: `export const z = 'z';export default () => {}`,
+        filename: testFilePath('./no-unused-modules/file-added-0.js'),
+        errors: [
+          error(`exported declaration 'z' not used within other modules`),
+          error(`exported declaration 'default' not used within other modules`),
+        ] }),
     ],
   });
 
 
   describe('test behaviour for new file', () => {
     before(() => {
-      fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', {encoding: 'utf8'});
+      fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', { encoding: 'utf8' });
     });
     ruleTester.run('no-unused-modules', rule, {
       valid: [
         test({ options: unusedExportsOptions,
-               code: `export * from '${testFilePath('./no-unused-modules/file-added-1.js')}'`,
-               filename: testFilePath('./no-unused-modules/file-0.js')}),
+          code: `export * from '${testFilePath('./no-unused-modules/file-added-1.js')}'`,
+          filename: testFilePath('./no-unused-modules/file-0.js') }),
       ],
       invalid: [
         test({ options: unusedExportsOptions,
-               code: `export const z = 'z';export default () => {}`,
-               filename: testFilePath('./no-unused-modules/file-added-1.js'),
-               errors: [error(`exported declaration 'default' not used within other modules`)]}),
+          code: `export const z = 'z';export default () => {}`,
+          filename: testFilePath('./no-unused-modules/file-added-1.js'),
+          errors: [error(`exported declaration 'default' not used within other modules`)] }),
       ],
     });
     after(() => {
@@ -616,16 +616,16 @@ describe('test behaviour for new file', () => {
 
 describe('test behaviour for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', {encoding: 'utf8'});
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', { encoding: 'utf8' });
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
-             code: `import added from '${testFilePath('./no-unused-modules/file-added-2.js')}'`,
-             filename: testFilePath('./no-unused-modules/file-added-1.js')}),
+        code: `import added from '${testFilePath('./no-unused-modules/file-added-2.js')}'`,
+        filename: testFilePath('./no-unused-modules/file-added-1.js') }),
       test({ options: unusedExportsOptions,
-             code: `export default () => {}`,
-             filename: testFilePath('./no-unused-modules/file-added-2.js')}),
+        code: `export default () => {}`,
+        filename: testFilePath('./no-unused-modules/file-added-2.js') }),
     ],
     invalid: [],
   });
@@ -638,16 +638,16 @@ describe('test behaviour for new file', () => {
 
 describe('test behaviour for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', {encoding: 'utf8'});
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', { encoding: 'utf8' });
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
-             code: `import { added } from '${testFilePath('./no-unused-modules/file-added-3.js')}'`,
-             filename: testFilePath('./no-unused-modules/file-added-1.js')}),
+        code: `import { added } from '${testFilePath('./no-unused-modules/file-added-3.js')}'`,
+        filename: testFilePath('./no-unused-modules/file-added-1.js') }),
       test({ options: unusedExportsOptions,
-             code: `export const added = () => {}`,
-             filename: testFilePath('./no-unused-modules/file-added-3.js')}),
+        code: `export const added = () => {}`,
+        filename: testFilePath('./no-unused-modules/file-added-3.js') }),
     ],
     invalid: [],
   });
@@ -660,16 +660,16 @@ describe('test behaviour for new file', () => {
 
 describe('test behaviour for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', {encoding: 'utf8'});
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', { encoding: 'utf8' });
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
-             code: `import * as added from '${testFilePath('./no-unused-modules/file-added-4.js.js')}'`,
-             filename: testFilePath('./no-unused-modules/file-added-1.js')}),
+        code: `import * as added from '${testFilePath('./no-unused-modules/file-added-4.js.js')}'`,
+        filename: testFilePath('./no-unused-modules/file-added-1.js') }),
       test({ options: unusedExportsOptions,
-             code: `export const added = () => {}; export default () => {}`,
-             filename: testFilePath('./no-unused-modules/file-added-4.js.js')}),
+        code: `export const added = () => {}; export default () => {}`,
+        filename: testFilePath('./no-unused-modules/file-added-4.js.js') }),
     ],
     invalid: [],
   });
@@ -684,12 +684,12 @@ describe('do not report missing export for ignored file', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: [{
-               src: [testFilePath('./no-unused-modules/**/*.js')],
-               ignoreExports: [testFilePath('./no-unused-modules/*ignored*.js')],
-               missingExports: true,
-              }],
-             code: 'export const test = true',
-             filename: testFilePath('./no-unused-modules/file-ignored-a.js')}),
+        src: [testFilePath('./no-unused-modules/**/*.js')],
+        ignoreExports: [testFilePath('./no-unused-modules/*ignored*.js')],
+        missingExports: true,
+      }],
+      code: 'export const test = true',
+      filename: testFilePath('./no-unused-modules/file-ignored-a.js') }),
     ],
     invalid: [],
   });
@@ -699,8 +699,8 @@ describe('do not report missing export for ignored file', () => {
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({ options: unusedExportsOptions,
-            code: `export const jsxFoo = 'foo'; export const jsxBar = 'bar'`,
-            filename: testFilePath('../jsx/named.jsx')}),
+      code: `export const jsxFoo = 'foo'; export const jsxBar = 'bar'`,
+      filename: testFilePath('../jsx/named.jsx') }),
   ],
   invalid: [],
 });
@@ -709,26 +709,26 @@ describe('do not report unused export for files mentioned in package.json', () =
   ruleTester.run('no-unused-modules', rule, {
     valid: [
       test({ options: unusedExportsOptions,
-             code: 'export const bin = "bin"',
-             filename: testFilePath('./no-unused-modules/bin.js')}),
+        code: 'export const bin = "bin"',
+        filename: testFilePath('./no-unused-modules/bin.js') }),
       test({ options: unusedExportsOptions,
-             code: 'export const binObject = "binObject"',
-             filename: testFilePath('./no-unused-modules/binObject/index.js')}),
+        code: 'export const binObject = "binObject"',
+        filename: testFilePath('./no-unused-modules/binObject/index.js') }),
       test({ options: unusedExportsOptions,
-             code: 'export const browser = "browser"',
-             filename: testFilePath('./no-unused-modules/browser.js')}),
+        code: 'export const browser = "browser"',
+        filename: testFilePath('./no-unused-modules/browser.js') }),
       test({ options: unusedExportsOptions,
-             code: 'export const browserObject = "browserObject"',
-             filename: testFilePath('./no-unused-modules/browserObject/index.js')}),
+        code: 'export const browserObject = "browserObject"',
+        filename: testFilePath('./no-unused-modules/browserObject/index.js') }),
       test({ options: unusedExportsOptions,
-             code: 'export const main = "main"',
-             filename: testFilePath('./no-unused-modules/main/index.js')}),
+        code: 'export const main = "main"',
+        filename: testFilePath('./no-unused-modules/main/index.js') }),
     ],
     invalid: [
       test({ options: unusedExportsOptions,
-             code: 'export const privatePkg = "privatePkg"',
-             filename: testFilePath('./no-unused-modules/privatePkg/index.js'),
-             errors: [error(`exported declaration 'privatePkg' not used within other modules`)]}),
+        code: 'export const privatePkg = "privatePkg"',
+        filename: testFilePath('./no-unused-modules/privatePkg/index.js'),
+        errors: [error(`exported declaration 'privatePkg' not used within other modules`)] }),
     ],
   });
 });
@@ -738,7 +738,7 @@ describe('Avoid errors if re-export all from umd compiled library', () => {
     valid: [
       test({ options: unusedExportsOptions,
         code: `export * from '${testFilePath('./no-unused-modules/bin.js')}'`,
-        filename: testFilePath('./no-unused-modules/main/index.js')}),
+        filename: testFilePath('./no-unused-modules/main/index.js') }),
     ],
     invalid: [],
   });
diff --git a/tests/src/rules/no-useless-path-segments.js b/tests/src/rules/no-useless-path-segments.js
index 33b1ff5b5b..313424d349 100644
--- a/tests/src/rules/no-useless-path-segments.js
+++ b/tests/src/rules/no-useless-path-segments.js
@@ -28,12 +28,12 @@ function runResolverTests(resolver) {
       test({ code: 'import "./malformed"', options: [{ noUselessIndex: true }] }), // ./malformed directory does not exist
       test({ code: 'import "./importType"', options: [{ noUselessIndex: true }] }), // ./importType.js does not exist
 
-      test({ code: 'import(".")'
-           , parser: require.resolve('babel-eslint') }),
-      test({ code: 'import("..")'
-           , parser: require.resolve('babel-eslint') }),
-      test({ code: 'import("fs").then(function(fs){})'
-           , parser: require.resolve('babel-eslint') }),
+      test({ code: 'import(".")',
+        parser: require.resolve('babel-eslint') }),
+      test({ code: 'import("..")',
+        parser: require.resolve('babel-eslint') }),
+      test({ code: 'import("fs").then(function(fs){})',
+        parser: require.resolve('babel-eslint') }),
     ],
 
     invalid: [
diff --git a/tests/src/rules/no-webpack-loader-syntax.js b/tests/src/rules/no-webpack-loader-syntax.js
index 86026e8d1c..5ec848bc65 100644
--- a/tests/src/rules/no-webpack-loader-syntax.js
+++ b/tests/src/rules/no-webpack-loader-syntax.js
@@ -2,24 +2,24 @@ import { test, getTSParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/no-webpack-loader-syntax');
+const ruleTester = new RuleTester();
+const rule = require('rules/no-webpack-loader-syntax');
 
 const message = 'Do not use import syntax to configure webpack loaders.';
 
 ruleTester.run('no-webpack-loader-syntax', rule, {
   valid: [
-    test({ code: 'import _ from "lodash"'}),
-    test({ code: 'import find from "lodash.find"'}),
-    test({ code: 'import foo from "./foo.css"'}),
-    test({ code: 'import data from "@scope/my-package/data.json"'}),
-    test({ code: 'var _ = require("lodash")'}),
-    test({ code: 'var find = require("lodash.find")'}),
-    test({ code: 'var foo = require("./foo")'}),
-    test({ code: 'var foo = require("../foo")'}),
-    test({ code: 'var foo = require("foo")'}),
-    test({ code: 'var foo = require("./")'}),
-    test({ code: 'var foo = require("@scope/foo")'}),
+    test({ code: 'import _ from "lodash"' }),
+    test({ code: 'import find from "lodash.find"' }),
+    test({ code: 'import foo from "./foo.css"' }),
+    test({ code: 'import data from "@scope/my-package/data.json"' }),
+    test({ code: 'var _ = require("lodash")' }),
+    test({ code: 'var find = require("lodash.find")' }),
+    test({ code: 'var foo = require("./foo")' }),
+    test({ code: 'var foo = require("../foo")' }),
+    test({ code: 'var foo = require("foo")' }),
+    test({ code: 'var foo = require("./")' }),
+    test({ code: 'var foo = require("@scope/foo")' }),
   ],
   invalid: [
     test({
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 3023be2db2..b95681b426 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -5,8 +5,8 @@ import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import flatMap from 'array.prototype.flatmap';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/order');
+const ruleTester = new RuleTester();
+const rule = require('rules/order');
 
 function withoutAutofixOutput(test) {
   return Object.assign({}, test, { output: test.code });
@@ -25,7 +25,7 @@ ruleTester.run('order', rule, {
         var relParent4 = require('..');
         var sibling = require('./foo');
         var index = require('./');`,
-      }),
+    }),
     // Default order using import
     test({
       code: `
@@ -36,7 +36,7 @@ ruleTester.run('order', rule, {
         import relParent3 from '../';
         import sibling, {foo3} from './foo';
         import index from './';`,
-      }),
+    }),
     // Multiple module of the same rank next to each other
     test({
       code: `
@@ -45,7 +45,7 @@ ruleTester.run('order', rule, {
         var path = require('path');
         var _ = require('lodash');
         var async = require('async');`,
-      }),
+    }),
     // Overriding order to be the reverse of the default order
     test({
       code: `
@@ -57,7 +57,7 @@ ruleTester.run('order', rule, {
         var async = require('async');
         var fs = require('fs');
       `,
-      options: [{groups: ['index', 'sibling', 'parent', 'external', 'builtin']}],
+      options: [{ groups: ['index', 'sibling', 'parent', 'external', 'builtin'] }],
     }),
     // Ignore dynamic requires
     test({
@@ -116,21 +116,21 @@ ruleTester.run('order', rule, {
         var unknown7 = require('/unknown7');
         var index = require('./');
         var unknown8 = require('/unknown8');
-    `}),
+    ` }),
     // Ignoring unassigned values by default (require)
     test({
       code: `
         require('./foo');
         require('fs');
         var path = require('path');
-    `}),
+    ` }),
     // Ignoring unassigned values by default (import)
     test({
       code: `
         import './foo';
         import 'fs';
         import path from 'path';
-    `}),
+    ` }),
     // No imports
     test({
       code: `
@@ -138,7 +138,7 @@ ruleTester.run('order', rule, {
           return a + b;
         }
         var foo;
-    `}),
+    ` }),
     // Grouping import types
     test({
       code: `
@@ -151,10 +151,10 @@ ruleTester.run('order', rule, {
         var async = require('async');
         var relParent1 = require('../foo');
       `,
-      options: [{groups: [
+      options: [{ groups: [
         ['builtin', 'index'],
         ['sibling', 'parent', 'external'],
-      ]}],
+      ] }],
     }),
     // Omitted types should implicitly be considered as the last type
     test({
@@ -162,11 +162,11 @@ ruleTester.run('order', rule, {
         var index = require('./');
         var path = require('path');
       `,
-      options: [{groups: [
+      options: [{ groups: [
         'index',
         ['sibling', 'parent', 'external'],
         // missing 'builtin'
-      ]}],
+      ] }],
     }),
     // Mixing require and import should have import up top
     test({
@@ -661,7 +661,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'ignore'},
+        alphabetize: { order: 'ignore' },
       }],
     }),
     // Option alphabetize: {order: 'asc'}
@@ -675,7 +675,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'asc'},
+        alphabetize: { order: 'asc' },
       }],
     }),
     // Option alphabetize: {order: 'desc'}
@@ -689,7 +689,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'desc'},
+        alphabetize: { order: 'desc' },
       }],
     }),
     // Option alphabetize with newlines-between: {order: 'asc', newlines-between: 'always'}
@@ -703,7 +703,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'asc'},
+        alphabetize: { order: 'asc' },
         'newlines-between': 'always',
       }],
     }),
@@ -871,12 +871,10 @@ ruleTester.run('order', rule, {
     test({
       code:
         `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n` +
-        `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n`
-      ,
+        `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n`,      
       output:
         `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n` +
-        `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n`
-      ,
+        `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n`,      
       errors: [{
         message: '`fs` import should occur before import of `async`',
       }],
@@ -1020,7 +1018,7 @@ ruleTester.run('order', rule, {
           var async = require('async');
           var fs = require('fs');
         `,
-          output: `
+        output: `
           var async = require('async');
           var sibling = require('./sibling');
           var fs = require('fs');
@@ -1064,7 +1062,7 @@ ruleTester.run('order', rule, {
         var index = require('./');
         var fs = require('fs');
       `,
-      options: [{groups: ['index', 'sibling', 'parent', 'external', 'builtin']}],
+      options: [{ groups: ['index', 'sibling', 'parent', 'external', 'builtin'] }],
       errors: [{
         message: '`./` import should occur before import of `fs`',
       }],
@@ -1127,10 +1125,10 @@ ruleTester.run('order', rule, {
         var path = require('path');
         var sibling = require('./foo');
       `,
-      options: [{groups: [
+      options: [{ groups: [
         ['builtin', 'index'],
         ['sibling', 'parent', 'external'],
-      ]}],
+      ] }],
       errors: [{
         message: '`path` import should occur before import of `./foo`',
       }],
@@ -1145,11 +1143,11 @@ ruleTester.run('order', rule, {
         var async = require('async');
         var path = require('path');
       `,
-      options: [{groups: [
+      options: [{ groups: [
         'index',
         ['sibling', 'parent', 'external', 'internal'],
         // missing 'builtin'
-      ]}],
+      ] }],
       errors: [{
         message: '`async` import should occur before import of `path`',
       }],
@@ -1161,10 +1159,10 @@ ruleTester.run('order', rule, {
         var async = require('async');
         var index = require('./');
       `,
-      options: [{groups: [
+      options: [{ groups: [
         'index',
         ['sibling', 'parent', 'UNKNOWN', 'internal'],
-      ]}],
+      ] }],
       errors: [{
         message: 'Incorrect configuration of the rule: Unknown type `"UNKNOWN"`',
       }],
@@ -1175,10 +1173,10 @@ ruleTester.run('order', rule, {
         var async = require('async');
         var index = require('./');
       `,
-      options: [{groups: [
+      options: [{ groups: [
         'index',
         ['sibling', 'parent', ['builtin'], 'internal'],
-      ]}],
+      ] }],
       errors: [{
         message: 'Incorrect configuration of the rule: Unknown type `["builtin"]`',
       }],
@@ -1189,10 +1187,10 @@ ruleTester.run('order', rule, {
         var async = require('async');
         var index = require('./');
       `,
-      options: [{groups: [
+      options: [{ groups: [
         'index',
         ['sibling', 'parent', 2, 'internal'],
-      ]}],
+      ] }],
       errors: [{
         message: 'Incorrect configuration of the rule: Unknown type `2`',
       }],
@@ -1203,10 +1201,10 @@ ruleTester.run('order', rule, {
         var async = require('async');
         var index = require('./');
       `,
-      options: [{groups: [
+      options: [{ groups: [
         'index',
         ['sibling', 'parent', 'parent', 'internal'],
-      ]}],
+      ] }],
       errors: [{
         message: 'Incorrect configuration of the rule: `parent` is duplicated',
       }],
@@ -1297,7 +1295,7 @@ ruleTester.run('order', rule, {
         `,
         options: [{
           groups: ['external', 'index'],
-          alphabetize: {order: 'asc'},
+          alphabetize: { order: 'asc' },
         }],
         parser,
         errors: [{
@@ -2066,7 +2064,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'asc'},
+        alphabetize: { order: 'asc' },
       }],
       errors: [{
         message: '`Bar` import should occur before import of `bar`',
@@ -2090,7 +2088,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'desc'},
+        alphabetize: { order: 'desc' },
       }],
       errors: [{
         message: '`bar` import should occur before import of `Bar`',
@@ -2112,7 +2110,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'asc', caseInsensitive: true},
+        alphabetize: { order: 'asc', caseInsensitive: true },
       }],
       errors: [{
         message: '`Bar` import should occur before import of `foo`',
@@ -2134,7 +2132,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'desc', caseInsensitive: true},
+        alphabetize: { order: 'desc', caseInsensitive: true },
       }],
       errors: [{
         message: '`foo` import should occur before import of `Bar`',
@@ -2152,7 +2150,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{
         groups: ['external', 'index'],
-        alphabetize: {order: 'asc'},
+        alphabetize: { order: 'asc' },
       }],
       errors: [{
         message: '`..` import should occur before import of `../a`',
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 0989125661..4efa47f5fc 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -2,8 +2,8 @@ import { test, getNonDefaultParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('../../../src/rules/prefer-default-export');
+const ruleTester = new RuleTester();
+const rule = require('../../../src/rules/prefer-default-export');
 
 ruleTester.run('prefer-default-export', rule, {
   valid: [
@@ -11,72 +11,72 @@ ruleTester.run('prefer-default-export', rule, {
       code: `
         export const foo = 'foo';
         export const bar = 'bar';`,
-      }),
+    }),
     test({
       code: `
         export default function bar() {};`,
-      }),
+    }),
     test({
       code: `
         export const foo = 'foo';
         export function bar() {};`,
-      }),
+    }),
     test({
       code: `
         export const foo = 'foo';
         export default bar;`,
-      }),
+    }),
     test({
       code: `
         let foo, bar;
         export { foo, bar }`,
-      }),
+    }),
     test({
       code: `
         export const { foo, bar } = item;`,
-      }),
+    }),
     test({
       code: `
         export const { foo, bar: baz } = item;`,
-      }),
+    }),
     test({
       code: `
         export const { foo: { bar, baz } } = item;`,
-      }),
+    }),
     test({
       code: `
         export const [a, b] = item;`,
-      }),
+    }),
     test({
       code: `
         let item;
         export const foo = item;
         export { item };`,
-      }),
+    }),
     test({
       code: `
         let foo;
         export { foo as default }`,
-      }),
+    }),
     test({
       code: `
         export * from './foo';`,
-      }),
+    }),
     test({
       code: `export Memory, { MemoryValue } from './Memory'`,
       parser: require.resolve('babel-eslint'),
-      }),
+    }),
 
     // no exports at all
     test({
       code: `
         import * as foo from './foo';`,
-      }),
+    }),
 
     test({
       code: `export type UserId = number;`,
       parser: require.resolve('babel-eslint'),
-      }),
+    }),
 
     // issue #653
     test({
@@ -193,14 +193,14 @@ context('TypeScript', function() {
           },
           parserConfig,
         ),
-        test (
+        test(
           {
             code: 'export interface foo { bar: string; }',
             parser,
           },
           parserConfig,
         ),
-        test (
+        test(
           {
             code: 'export interface foo { bar: string; }; export function goo() {}',
             parser,
diff --git a/tests/src/rules/unambiguous.js b/tests/src/rules/unambiguous.js
index 8e7a9a3ae1..72e6b10828 100644
--- a/tests/src/rules/unambiguous.js
+++ b/tests/src/rules/unambiguous.js
@@ -1,7 +1,7 @@
 import { RuleTester } from 'eslint';
 
-const ruleTester = new RuleTester()
-    , rule = require('rules/unambiguous');
+const ruleTester = new RuleTester();
+const rule = require('rules/unambiguous');
 
 ruleTester.run('unambiguous', rule, {
   valid: [
diff --git a/tests/src/utils.js b/tests/src/utils.js
index f1a9e54c29..a76826de51 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -43,8 +43,8 @@ export function test(t) {
 }
 
 export function testContext(settings) {
-  return { getFilename: function () { return FILENAME; }
-         , settings: settings || {} };
+  return { getFilename: function () { return FILENAME; },
+    settings: settings || {} };
 }
 
 export function getFilename(file) {
diff --git a/utils/ignore.js b/utils/ignore.js
index 2a775b5da0..32bbbc6249 100644
--- a/utils/ignore.js
+++ b/utils/ignore.js
@@ -6,7 +6,7 @@ const extname = require('path').extname;
 const log = require('debug')('eslint-plugin-import:utils:ignore');
 
 // one-shot memoized
-let cachedSet, lastSettings;
+let cachedSet; let lastSettings;
 function validExtensions(context) {
   if (cachedSet && context.settings === lastSettings) {
     return cachedSet;
diff --git a/utils/resolve.js b/utils/resolve.js
index d1881a83f9..33a755fcd5 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -7,8 +7,8 @@ const fs = require('fs');
 const Module = require('module');
 const path = require('path');
 
-const hashObject = require('./hash').hashObject
-    , ModuleCache = require('./ModuleCache').default;
+const hashObject = require('./hash').hashObject;
+const ModuleCache = require('./ModuleCache').default;
 
 const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname.toUpperCase(), 'reSOLVE.js'));
 exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS;
@@ -59,8 +59,8 @@ exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cache
   // null means it resolved to a builtin
   if (filepath === null) return true;
   if (filepath.toLowerCase() === process.cwd().toLowerCase()) return true;
-  const parsedPath = path.parse(filepath)
-      , dir = parsedPath.dir;
+  const parsedPath = path.parse(filepath);
+  const dir = parsedPath.dir;
 
   let result = fileExistsCache.get(filepath, cacheSettings);
   if (result != null) return result;
@@ -89,8 +89,8 @@ function fullResolve(modulePath, sourceFile, settings) {
   const coreSet = new Set(settings['import/core-modules']);
   if (coreSet.has(modulePath)) return { found: true, path: null };
 
-  const sourceDir = path.dirname(sourceFile)
-      , cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath;
+  const sourceDir = path.dirname(sourceFile);
+  const cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath;
 
   const cacheSettings = ModuleCache.getSettings(settings);
 
@@ -118,12 +118,12 @@ function fullResolve(modulePath, sourceFile, settings) {
     }
 
     switch (resolver.interfaceVersion) {
-      case 2:
-        return v2();
+    case 2:
+      return v2();
 
-      default:
-      case 1:
-        return v1();
+    default:
+    case 1:
+      return v1();
     }
   }
 
@@ -133,10 +133,10 @@ function fullResolve(modulePath, sourceFile, settings) {
   const resolvers = resolverReducer(configResolvers, new Map());
 
   for (const pair of resolvers) {
-    const name = pair[0]
-      , config = pair[1];
-    const resolver = requireResolver(name, sourceFile)
-        , resolved = withResolver(resolver, config);
+    const name = pair[0];
+    const config = pair[1];
+    const resolver = requireResolver(name, sourceFile);
+    const resolved = withResolver(resolver, config);
 
     if (!resolved.found) continue;
 
@@ -218,9 +218,9 @@ const erroredContexts = new Set();
 function resolve(p, context) {
   try {
     return relative( p
-                   , context.getFilename()
-                   , context.settings
-                   );
+      , context.getFilename()
+      , context.settings
+    );
   } catch (err) {
     if (!erroredContexts.has(context)) {
       // The `err.stack` string starts with `err.name` followed by colon and `err.message`.

From 47bc52bc53dae6b438cfed557b33a066129d15ee Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 17 Jan 2021 15:25:01 -0800
Subject: [PATCH 228/767] [meta] enable `no-cond-assign`, `no-return-assign`

---
 .eslintrc                  |  2 ++
 src/ExportMap.js           |  4 ++--
 src/rules/export.js        | 10 ++++++----
 src/rules/no-deprecated.js | 10 +++-------
 4 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 5ad4ffcec3..9e42281a21 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -26,6 +26,8 @@
         "func-call-spacing": 2,
         "indent": [2, 2],
         "max-len": [1, 99, 2],
+        "no-cond-assign": [2, "always"],
+        "no-return-assign": [2, "always"],
         "no-shadow": 1,
         "no-var": 2,
         "object-curly-spacing": [2, "always"],
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 45c92d8336..d759995427 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -491,8 +491,8 @@ ExportMap.parse = function (path, content, context) {
     // capture namespaces in case of later export
     if (n.type === 'ImportDeclaration') {
       captureDependency(n);
-      let ns;
-      if (n.specifiers.some(s => s.type === 'ImportNamespaceSpecifier' && (ns = s))) {
+      const ns = n.specifiers.find(s => s.type === 'ImportNamespaceSpecifier');
+      if (ns) {
         namespaces.set(ns.local.name, n.source.value);
       }
       return;
diff --git a/src/rules/export.js b/src/rules/export.js
index 203bb7d3b8..386211baaf 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -136,10 +136,12 @@ module.exports = {
         const parent = getParent(node);
 
         let any = false;
-        remoteExports.forEach((v, name) =>
-          name !== 'default' &&
-          (any = true) && // poor man's filter
-          addNamed(name, node, parent));
+        remoteExports.forEach((v, name) => {
+          if (name !== 'default') {
+            any = true; // poor man's filter
+            addNamed(name, node, parent);
+          }
+        });
 
         if (!any) {
           context.report(
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index 4360ee787b..628759bd42 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -9,10 +9,7 @@ function message(deprecation) {
 function getDeprecation(metadata) {
   if (!metadata || !metadata.doc) return;
 
-  let deprecation;
-  if (metadata.doc.tags.some(t => t.title === 'deprecated' && (deprecation = t))) {
-    return deprecation;
-  }
+  return metadata.doc.tags.find(t => t.title === 'deprecated');
 }
 
 module.exports = {
@@ -35,9 +32,8 @@ module.exports = {
       const imports = Exports.get(node.source.value, context);
       if (imports == null) return;
 
-      let moduleDeprecation;
-      if (imports.doc &&
-          imports.doc.tags.some(t => t.title === 'deprecated' && (moduleDeprecation = t))) {
+      const moduleDeprecation = imports.doc && imports.doc.tags.find(t => t.title === 'deprecated');
+      if (moduleDeprecation) {
         context.report({ node, message: message(moduleDeprecation) });
       }
 

From d83a55d7bed4dbce9b08b762226670a68dd2d51c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 17 Jan 2021 18:07:27 -0800
Subject: [PATCH 229/767] [meta] fix resolvers eslint by adding strict pragma

---
 resolvers/node/index.js         |  2 ++
 resolvers/node/test/.eslintrc   | 15 +++++++++------
 resolvers/webpack/.eslintrc     |  6 ++++++
 resolvers/webpack/.eslintrc.yml |  4 ----
 resolvers/webpack/index.js      |  2 ++
 resolvers/webpack/test/alias.js |  2 ++
 6 files changed, 21 insertions(+), 10 deletions(-)
 create mode 100644 resolvers/webpack/.eslintrc
 delete mode 100644 resolvers/webpack/.eslintrc.yml

diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index 3686cb5e6a..85550ddf7a 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const resolve = require('resolve');
 const path = require('path');
 
diff --git a/resolvers/node/test/.eslintrc b/resolvers/node/test/.eslintrc
index 5a1ff85fa5..fc14dae59e 100644
--- a/resolvers/node/test/.eslintrc
+++ b/resolvers/node/test/.eslintrc
@@ -1,6 +1,9 @@
----
-env:
-  mocha: true
-  es6: false
-rules:
-  quotes: 0
+{
+  "env": {
+    "mocha": true,
+    "es6": false
+  },
+  "rules": {
+    "quotes": 0,
+  },
+}
diff --git a/resolvers/webpack/.eslintrc b/resolvers/webpack/.eslintrc
new file mode 100644
index 0000000000..743d5c949e
--- /dev/null
+++ b/resolvers/webpack/.eslintrc
@@ -0,0 +1,6 @@
+{
+  "rules": {
+    "import/no-extraneous-dependencies": 1,
+    "no-console": 1,
+  },
+}
diff --git a/resolvers/webpack/.eslintrc.yml b/resolvers/webpack/.eslintrc.yml
deleted file mode 100644
index febeb09cfa..0000000000
--- a/resolvers/webpack/.eslintrc.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-rules:
-  import/no-extraneous-dependencies: 1
-  no-console: 1
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index cd489005f7..32d5bdff6c 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const findRoot = require('find-root');
 const path = require('path');
 const get = require('lodash/get');
diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js
index a70155f5cf..e48c074055 100644
--- a/resolvers/webpack/test/alias.js
+++ b/resolvers/webpack/test/alias.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai = require('chai');
 const expect = chai.expect;
 const path = require('path');

From ae5f3ce6e49cf61cf877fe3ebaaa20f500706578 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 17 Jan 2021 18:40:45 -0800
Subject: [PATCH 230/767] [meta] fix resolvers eslint by adding strict pragma

---
 resolvers/webpack/test/config.js       | 2 ++
 resolvers/webpack/test/example.js      | 2 ++
 resolvers/webpack/test/extensions.js   | 2 ++
 resolvers/webpack/test/externals.js    | 2 ++
 resolvers/webpack/test/fallback.js     | 2 ++
 resolvers/webpack/test/loaders.js      | 2 ++
 resolvers/webpack/test/modules.js      | 2 ++
 resolvers/webpack/test/packageMains.js | 2 ++
 resolvers/webpack/test/plugins.js      | 2 ++
 resolvers/webpack/test/root.js         | 2 ++
 10 files changed, 20 insertions(+)

diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index a8b025ddca..c6a0a94fb8 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai =  require('chai');
 const expect = chai.expect;
 const path = require('path');
diff --git a/resolvers/webpack/test/example.js b/resolvers/webpack/test/example.js
index c311bc58c2..c7ae933f18 100644
--- a/resolvers/webpack/test/example.js
+++ b/resolvers/webpack/test/example.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const path = require('path');
 
 const resolve = require('../index').resolve;
diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js
index da27e0b2eb..398feb2c83 100644
--- a/resolvers/webpack/test/extensions.js
+++ b/resolvers/webpack/test/extensions.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai =  require('chai');
 const expect = chai.expect;
 const path = require('path');
diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js
index c7e7375e30..ed407a7f79 100644
--- a/resolvers/webpack/test/externals.js
+++ b/resolvers/webpack/test/externals.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai = require('chai');
 const expect = chai.expect;
 const path = require('path');
diff --git a/resolvers/webpack/test/fallback.js b/resolvers/webpack/test/fallback.js
index 6f21ebb58e..31cbffd3ab 100644
--- a/resolvers/webpack/test/fallback.js
+++ b/resolvers/webpack/test/fallback.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai =  require('chai');
 const expect = chai.expect;
 const path = require('path');
diff --git a/resolvers/webpack/test/loaders.js b/resolvers/webpack/test/loaders.js
index 7e6576a7c6..ccf62f99c5 100644
--- a/resolvers/webpack/test/loaders.js
+++ b/resolvers/webpack/test/loaders.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai =  require('chai');
 const expect = chai.expect;
 const path = require('path');
diff --git a/resolvers/webpack/test/modules.js b/resolvers/webpack/test/modules.js
index 777032fded..9242865407 100644
--- a/resolvers/webpack/test/modules.js
+++ b/resolvers/webpack/test/modules.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai =  require('chai');
 const expect = chai.expect;
 const path = require('path');
diff --git a/resolvers/webpack/test/packageMains.js b/resolvers/webpack/test/packageMains.js
index f73665ebaa..dc30e3335a 100644
--- a/resolvers/webpack/test/packageMains.js
+++ b/resolvers/webpack/test/packageMains.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai = require('chai');
 const expect = chai.expect;
 const path = require('path');
diff --git a/resolvers/webpack/test/plugins.js b/resolvers/webpack/test/plugins.js
index d052a57925..d061d8df16 100644
--- a/resolvers/webpack/test/plugins.js
+++ b/resolvers/webpack/test/plugins.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai = require('chai');
 const expect = chai.expect;
 const path = require('path');
diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js
index 3c938654a6..9fa34c24b3 100644
--- a/resolvers/webpack/test/root.js
+++ b/resolvers/webpack/test/root.js
@@ -1,3 +1,5 @@
+'use strict';
+
 const chai =  require('chai');
 const expect = chai.expect;
 const path = require('path');

From 00b079e8ca55138515fcaa8caa58efb5601ad434 Mon Sep 17 00:00:00 2001
From: cherryblossom <31467609+cherryblossom000@users.noreply.github.com>
Date: Sat, 16 Jan 2021 13:19:39 +1100
Subject: [PATCH 231/767] [meta] add `.DS_Store` to `.gitignore`

---
 .gitignore | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.gitignore b/.gitignore
index a01de720c3..bb59bce594 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,3 +49,6 @@ lib/
 yarn.lock
 package-lock.json
 npm-shrinkwrap.json
+
+# macOS
+.DS_Store

From 462b016cd70b2f192c3eab78a70adcd2284f100d Mon Sep 17 00:00:00 2001
From: cherryblossom <31467609+cherryblossom000@users.noreply.github.com>
Date: Wed, 13 Jan 2021 10:39:57 +1100
Subject: [PATCH 232/767] [Fix] `no-unused-modules`: make type imports mark a
 module as used (fixes #1924)

---
 CHANGELOG.md                                  |  4 +
 src/ExportMap.js                              | 80 ++++++++++---------
 src/rules/no-cycle.js                         | 34 +++++---
 src/rules/no-unused-modules.js                | 12 ++-
 .../typescript/file-ts-f-import-type.ts       |  1 +
 .../no-unused-modules/typescript/file-ts-f.ts |  1 +
 .../typescript/file-ts-g-used-as-type.ts      |  1 +
 .../no-unused-modules/typescript/file-ts-g.ts |  1 +
 tests/src/rules/no-unused-modules.js          | 26 +++++-
 9 files changed, 103 insertions(+), 57 deletions(-)
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-f-import-type.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-f.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-g-used-as-type.ts
 create mode 100644 tests/files/no-unused-modules/typescript/file-ts-g.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c5da1d455..1687ebee0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-webpack-loader-syntax`]/TypeScript: avoid crash on missing name ([#1947], thanks @leonardodino)
 - [`no-extraneous-dependencies`]: Add package.json cache ([#1948], thanks @fa93hws)
 - [`prefer-default-export`]: handle empty array destructuring ([#1965], thanks @ljharb)
+- [`no-unused-modules`]: make type imports mark a module as used (fixes #1924) ([#1974], thanks [@cherryblossom000])
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -739,6 +740,8 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
+[#1924]: https://github.com/benmosher/eslint-plugin-import/issues/1924
 [#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
 [#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
 [#1947]: https://github.com/benmosher/eslint-plugin-import/pull/1947
@@ -1289,3 +1292,4 @@ for info on changes for earlier releases.
 [@tomprats]: https://github.com/tomprats
 [@straub]: https://github.com/straub
 [@andreubotella]: https://github.com/andreubotella
+[@cherryblossom000]: https://github.com/cherryblossom000
diff --git a/src/ExportMap.js b/src/ExportMap.js
index d759995427..9ffe7ac8d6 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -83,8 +83,8 @@ export default class ExportMap {
 
   /**
    * ensure that imported name fully resolves.
-   * @param  {[type]}  name [description]
-   * @return {Boolean}      [description]
+   * @param  {string} name
+   * @return {{ found: boolean, path: ExportMap[] }}
    */
   hasDeep(name) {
     if (this.namespace.has(name)) return { found: true, path: [this] };
@@ -241,8 +241,8 @@ const availableDocStyleParsers = {
 
 /**
  * parse JSDoc from leading comments
- * @param  {...[type]} comments [description]
- * @return {{doc: object}}
+ * @param {object[]} comments
+ * @return {{ doc: object }}
  */
 function captureJsDoc(comments) {
   let doc;
@@ -286,6 +286,8 @@ function captureTomDoc(comments) {
   }
 }
 
+const supportedImportTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
+
 ExportMap.get = function (source, context) {
   const path = resolve(source, context);
   if (path == null) return null;
@@ -410,43 +412,27 @@ ExportMap.parse = function (path, content, context) {
     return object;
   }
 
-  function captureDependency(declaration) {
-    if (declaration.source == null) return null;
-    if (declaration.importKind === 'type') return null; // skip Flow type imports
-    const importedSpecifiers = new Set();
-    const supportedTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
-    let hasImportedType = false;
-    if (declaration.specifiers) {
-      declaration.specifiers.forEach(specifier => {
-        const isType = specifier.importKind === 'type';
-        hasImportedType = hasImportedType || isType;
-
-        if (supportedTypes.has(specifier.type) && !isType) {
-          importedSpecifiers.add(specifier.type);
-        }
-        if (specifier.type === 'ImportSpecifier' && !isType) {
-          importedSpecifiers.add(specifier.imported.name);
-        }
-      });
-    }
-
-    // only Flow types were imported
-    if (hasImportedType && importedSpecifiers.size === 0) return null;
+  function captureDependency({ source }, isOnlyImportingTypes, importedSpecifiers = new Set()) {
+    if (source == null) return null;
 
-    const p = remotePath(declaration.source.value);
+    const p = remotePath(source.value);
     if (p == null) return null;
+
+    const declarationMetadata = {
+      // capturing actual node reference holds full AST in memory!
+      source: { value: source.value, loc: source.loc },
+      isOnlyImportingTypes,
+      importedSpecifiers,
+    };
+
     const existing = m.imports.get(p);
-    if (existing != null) return existing.getter;
+    if (existing != null) {
+      existing.declarations.add(declarationMetadata);
+      return existing.getter;
+    }
 
     const getter = thunkFor(p, context);
-    m.imports.set(p, {
-      getter,
-      source: {  // capturing actual node reference holds full AST in memory!
-        value: declaration.source.value,
-        loc: declaration.source.loc,
-      },
-      importedSpecifiers,
-    });
+    m.imports.set(p, { getter, declarations: new Set([declarationMetadata]) });
     return getter;
   }
 
@@ -483,14 +469,32 @@ ExportMap.parse = function (path, content, context) {
     }
 
     if (n.type === 'ExportAllDeclaration') {
-      const getter = captureDependency(n);
+      const getter = captureDependency(n, n.exportKind === 'type');
       if (getter) m.dependencies.add(getter);
       return;
     }
 
     // capture namespaces in case of later export
     if (n.type === 'ImportDeclaration') {
-      captureDependency(n);
+      // import type { Foo } (TS and Flow)
+      const declarationIsType = n.importKind === 'type';
+      let isOnlyImportingTypes = declarationIsType;
+      const importedSpecifiers = new Set();
+      n.specifiers.forEach(specifier => {
+        if (supportedImportTypes.has(specifier.type)) {
+          importedSpecifiers.add(specifier.type);
+        }
+        if (specifier.type === 'ImportSpecifier') {
+          importedSpecifiers.add(specifier.imported.name);
+        }
+
+        // import { type Foo } (Flow)
+        if (!declarationIsType) {
+          isOnlyImportingTypes = specifier.importKind === 'type';
+        }
+      });
+      captureDependency(n, isOnlyImportingTypes, importedSpecifiers);
+
       const ns = n.specifiers.find(s => s.type === 'ImportNamespaceSpecifier');
       if (ns) {
         namespaces.set(ns.local.name, n.source.value);
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 21a428179d..b72bd34fd4 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -48,12 +48,19 @@ module.exports = {
         return; // ignore external modules
       }
 
-      const imported = Exports.get(sourceNode.value, context);
-
-      if (importer.importKind === 'type') {
-        return; // no Flow import resolution
+      if (
+        importer.type === 'ImportDeclaration' && (
+          // import type { Foo } (TS and Flow)
+          importer.importKind === 'type' ||
+          // import { type Foo } (Flow)
+          importer.specifiers.every(({ importKind }) => importKind === 'type')
+        )
+      ) {
+        return; // ignore type imports
       }
 
+      const imported = Exports.get(sourceNode.value, context);
+
       if (imported == null) {
         return;  // no-unresolved territory
       }
@@ -70,15 +77,20 @@ module.exports = {
         if (traversed.has(m.path)) return;
         traversed.add(m.path);
 
-        for (const [path, { getter, source }] of m.imports) {
+        for (const [path, { getter, declarations }] of m.imports) {
           if (path === myPath) return true;
           if (traversed.has(path)) continue;
-          if (ignoreModule(source.value)) continue;
-          if (route.length + 1 < maxDepth) {
-            untraversed.push({
-              mget: getter,
-              route: route.concat(source),
-            });
+          for (const { source, isOnlyImportingTypes } of declarations) {
+            if (ignoreModule(source.value)) continue;
+            // Ignore only type imports
+            if (isOnlyImportingTypes) continue;
+
+            if (route.length + 1 < maxDepth) {
+              untraversed.push({
+                mget: getter,
+                route: route.concat(source),
+              });
+            }
           }
         }
       }
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 16299ac564..dfea6de6df 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -114,7 +114,7 @@ const importList = new Map();
  * keys are the paths to the modules containing the exports, while the
  * lower-level Map keys are the specific identifiers or special AST node names
  * being exported. The leaf-level metadata object at the moment only contains a
- * `whereUsed` propoerty, which contains a Set of paths to modules that import
+ * `whereUsed` property, which contains a Set of paths to modules that import
  * the name.
  *
  * For example, if we have a file named bar.js containing the following exports:
@@ -216,12 +216,10 @@ const prepareImportsAndExports = (srcFiles, context) => {
         if (isNodeModule(key)) {
           return;
         }
-        let localImport = imports.get(key);
-        if (typeof localImport !== 'undefined') {
-          localImport = new Set([...localImport, ...value.importedSpecifiers]);
-        } else {
-          localImport = value.importedSpecifiers;
-        }
+        const localImport = imports.get(key) || new Set();
+        value.declarations.forEach(({ importedSpecifiers }) =>
+          importedSpecifiers.forEach(specifier => localImport.add(specifier))
+        );
         imports.set(key, localImport);
       });
       importList.set(file, imports);
diff --git a/tests/files/no-unused-modules/typescript/file-ts-f-import-type.ts b/tests/files/no-unused-modules/typescript/file-ts-f-import-type.ts
new file mode 100644
index 0000000000..dd82043774
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-f-import-type.ts
@@ -0,0 +1 @@
+import type {g} from './file-ts-g-used-as-type'
diff --git a/tests/files/no-unused-modules/typescript/file-ts-f.ts b/tests/files/no-unused-modules/typescript/file-ts-f.ts
new file mode 100644
index 0000000000..f3a1ca7ab4
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-f.ts
@@ -0,0 +1 @@
+import {g} from './file-ts-g';
diff --git a/tests/files/no-unused-modules/typescript/file-ts-g-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-g-used-as-type.ts
new file mode 100644
index 0000000000..fe5318fbe7
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-g-used-as-type.ts
@@ -0,0 +1 @@
+export interface g {}
diff --git a/tests/files/no-unused-modules/typescript/file-ts-g.ts b/tests/files/no-unused-modules/typescript/file-ts-g.ts
new file mode 100644
index 0000000000..fe5318fbe7
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/file-ts-g.ts
@@ -0,0 +1 @@
+export interface g {}
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 0e7826a523..5906c9afbf 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -827,6 +827,31 @@ context('TypeScript', function () {
           parser: parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-e-used-as-type.ts'),
         }),
+        // Should also be valid when the exporting files are linted before the importing ones
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export interface g {}`,
+          parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-g.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `import {g} from './file-ts-g';`,
+          parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-f.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `export interface g {};`,
+          parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-g-used-as-type.ts'),
+        }),
+        test({
+          options: unusedExportsTypescriptOptions,
+          code: `import type {g} from './file-ts-g';`,
+          parser,
+          filename: testFilePath('./no-unused-modules/typescript/file-ts-f-import-type.ts'),
+        }),
       ],
       invalid: [
         test({
@@ -940,4 +965,3 @@ describe('ignore flow types', () => {
     invalid: [],
   });
 });
-

From 2ae68c15407a60b68496e245853a45b10efd473a Mon Sep 17 00:00:00 2001
From: Michael Blaszczyk <mblaszczyk@atlassian.com>
Date: Thu, 12 Nov 2020 17:13:36 +1100
Subject: [PATCH 233/767] [Fix] `import/no-cycle`: fix perf regression

Fixes #1943.
---
 CHANGELOG.md                                  |  3 ++
 src/ExportMap.js                              | 27 +++++++++---
 .../typescript-export-assign-property.ts      |  3 ++
 tests/src/core/getExports.js                  | 44 +++++++++++++++++--
 4 files changed, 68 insertions(+), 9 deletions(-)
 create mode 100644 tests/files/typescript-export-assign-property.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1687ebee0d..115e1ad8c3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-extraneous-dependencies`]: Add package.json cache ([#1948], thanks @fa93hws)
 - [`prefer-default-export`]: handle empty array destructuring ([#1965], thanks @ljharb)
 - [`no-unused-modules`]: make type imports mark a module as used (fixes #1924) ([#1974], thanks [@cherryblossom000])
+- [`import/no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -741,6 +742,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
+[#1944]: https://github.com/benmosher/eslint-plugin-import/pull/1944
 [#1924]: https://github.com/benmosher/eslint-plugin-import/issues/1924
 [#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
 [#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
@@ -1293,3 +1295,4 @@ for info on changes for earlier releases.
 [@straub]: https://github.com/straub
 [@andreubotella]: https://github.com/andreubotella
 [@cherryblossom000]: https://github.com/cherryblossom000
+[@Blasz]: https://github.com/Blasz
\ No newline at end of file
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 9ffe7ac8d6..215f3de716 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -22,6 +22,7 @@ let parseConfigFileTextToJson;
 const log = debug('eslint-plugin-import:ExportMap');
 
 const exportCache = new Map();
+const tsConfigCache = new Map();
 
 export default class ExportMap {
   constructor(path) {
@@ -438,9 +439,11 @@ ExportMap.parse = function (path, content, context) {
 
   const source = makeSourceCode(content, ast);
 
-  function isEsModuleInterop() {
+  function readTsConfig() {
     const tsConfigInfo = tsConfigLoader({
-      cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
+      cwd:
+        (context.parserOptions && context.parserOptions.tsconfigRootDir) ||
+        process.cwd(),
       getEnv: (key) => process.env[key],
     });
     try {
@@ -450,12 +453,26 @@ ExportMap.parse = function (path, content, context) {
           // this is because projects not using TypeScript won't have typescript installed
           ({ parseConfigFileTextToJson } = require('typescript'));
         }
-        const tsConfig = parseConfigFileTextToJson(tsConfigInfo.tsConfigPath, jsonText).config;
-        return tsConfig.compilerOptions.esModuleInterop;
+        return parseConfigFileTextToJson(tsConfigInfo.tsConfigPath, jsonText).config;
       }
     } catch (e) {
-      return false;
+      // Catch any errors
     }
+
+    return null;
+  }
+
+  function isEsModuleInterop() {
+    const cacheKey = hashObject({
+      tsconfigRootDir: context.parserOptions && context.parserOptions.tsconfigRootDir,
+    }).digest('hex');
+    let tsConfig = tsConfigCache.get(cacheKey);
+    if (typeof tsConfig === 'undefined') {
+      tsConfig = readTsConfig();
+      tsConfigCache.set(cacheKey, tsConfig);
+    }
+
+    return tsConfig !== null ? tsConfig.compilerOptions.esModuleInterop : false;
   }
 
   ast.body.forEach(function (n) {
diff --git a/tests/files/typescript-export-assign-property.ts b/tests/files/typescript-export-assign-property.ts
new file mode 100644
index 0000000000..8dc2b9981e
--- /dev/null
+++ b/tests/files/typescript-export-assign-property.ts
@@ -0,0 +1,3 @@
+const AnalyticsNode = { Analytics: {} };
+
+export = AnalyticsNode.Analytics;
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 523b0ef4cf..5a9bdadb15 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -1,6 +1,8 @@
 import { expect } from  'chai';
 import semver from 'semver';
+import sinon from 'sinon';
 import eslintPkg from 'eslint/package.json';
+import * as tsConfigLoader from 'tsconfig-paths/lib/tsconfig-loader';
 import ExportMap from '../../../src/ExportMap';
 
 import * as fs from 'fs';
@@ -51,7 +53,8 @@ describe('ExportMap', function () {
     const differentSettings = Object.assign(
       {},
       fakeContext,
-      { parserPath: 'espree' });
+      { parserPath: 'espree' },
+    );
 
     expect(ExportMap.get('./named-exports', differentSettings))
       .to.exist.and
@@ -338,11 +341,11 @@ describe('ExportMap', function () {
       // ['string form', { 'typescript-eslint-parser': '.ts' }],
     ];
 
-    if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
+    if (semver.satisfies(eslintPkg.version, '>5')) {
       configs.push(['array form', { '@typescript-eslint/parser': ['.ts', '.tsx'] }]);
     }
 
-    if (semver.satisfies(eslintPkg.version, '<6.0.0')) {
+    if (semver.satisfies(eslintPkg.version, '<6')) {
       configs.push(['array form', { 'typescript-eslint-parser': ['.ts', '.tsx'] }]);
     }
 
@@ -358,8 +361,12 @@ describe('ExportMap', function () {
         let imports;
         before('load imports', function () {
           this.timeout(20000);  // takes a long time :shrug:
+          sinon.spy(tsConfigLoader, 'tsConfigLoader');
           imports = ExportMap.get('./typescript.ts', context);
         });
+        after('clear spies', function () {
+          tsConfigLoader.tsConfigLoader.restore();
+        });
 
         it('returns something for a TypeScript file', function () {
           expect(imports).to.exist;
@@ -388,9 +395,38 @@ describe('ExportMap', function () {
         it('has exported abstract class', function () {
           expect(imports.has('Bar')).to.be.true;
         });
+
+        it('should cache tsconfig until tsconfigRootDir parser option changes', function () {
+          const customContext = Object.assign(
+            {},
+            context,
+            {
+              parserOptions: {
+                tsconfigRootDir: null,
+              },
+            },
+          );
+          expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(0);
+          ExportMap.parse('./baz.ts', 'export const baz = 5', customContext);
+          expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(1);
+          ExportMap.parse('./baz.ts', 'export const baz = 5', customContext);
+          expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(1);
+
+          const differentContext = Object.assign(
+            {},
+            context,
+            {
+              parserOptions: {
+                tsconfigRootDir: process.cwd(),
+              },
+            },
+          );
+
+          ExportMap.parse('./baz.ts', 'export const baz = 5', differentContext);
+          expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(2);
+        });
       });
     });
-
   });
 
   // todo: move to utils

From 93e060f63f3c6f557c7fea9cddc0018c033b058d Mon Sep 17 00:00:00 2001
From: Zhibin Liu <ljqx@live.cn>
Date: Mon, 19 Nov 2018 13:52:41 +0800
Subject: [PATCH 234/767] [Fix] [Generic Import Callback] Make callback for all
 imports once in rules

Fixes #1230.
---
 CHANGELOG.md                            |  6 +-
 src/rules/extensions.js                 | 12 ++--
 src/rules/max-dependencies.js           | 22 ++----
 src/rules/no-extraneous-dependencies.js |  4 +-
 src/rules/no-internal-modules.js        | 24 ++-----
 src/rules/no-nodejs-modules.js          | 15 ++--
 src/rules/no-restricted-paths.js        | 17 ++---
 src/rules/no-self-import.js             | 15 ++--
 src/rules/no-webpack-loader-syntax.js   | 15 ++--
 tests/src/rules/extensions.js           | 93 +++++++++++++++++++++++++
 10 files changed, 130 insertions(+), 93 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 115e1ad8c3..3868b448de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: make type imports mark a module as used (fixes #1924) ([#1974], thanks [@cherryblossom000])
 - [`import/no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
 
+### Changed
+- [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
+
 ## [2.22.1] - 2020-09-27
 ### Fixed
 - [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
@@ -867,6 +870,7 @@ for info on changes for earlier releases.
 [#1253]: https://github.com/benmosher/eslint-plugin-import/pull/1253
 [#1248]: https://github.com/benmosher/eslint-plugin-import/pull/1248
 [#1238]: https://github.com/benmosher/eslint-plugin-import/pull/1238
+[#1237]: https://github.com/benmosher/eslint-plugin-import/pull/1237
 [#1235]: https://github.com/benmosher/eslint-plugin-import/pull/1235
 [#1234]: https://github.com/benmosher/eslint-plugin-import/pull/1234
 [#1232]: https://github.com/benmosher/eslint-plugin-import/pull/1232
@@ -1295,4 +1299,4 @@ for info on changes for earlier releases.
 [@straub]: https://github.com/straub
 [@andreubotella]: https://github.com/andreubotella
 [@cherryblossom000]: https://github.com/cherryblossom000
-[@Blasz]: https://github.com/Blasz
\ No newline at end of file
+[@Blasz]: https://github.com/Blasz
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index d6a469a255..c02ab0a62a 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -2,6 +2,7 @@ import path from 'path';
 
 import resolve from 'eslint-module-utils/resolve';
 import { isBuiltIn, isExternalModule, isScoped, isScopedModule } from '../core/importType';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] };
@@ -134,12 +135,10 @@ module.exports = {
       return false;
     }
 
-    function checkFileExtension(node) {
-      const { source } = node;
-
+    function checkFileExtension(source) {
       // bail if the declaration doesn't have a source, e.g. "export { foo };"
       if (!source) return;
-
+      
       const importPathWithQueryString = source.value;
 
       // don't enforce anything on builtins
@@ -181,9 +180,6 @@ module.exports = {
       }
     }
 
-    return {
-      ImportDeclaration: checkFileExtension,
-      ExportNamedDeclaration: checkFileExtension,
-    };
+    return moduleVisitor(checkFileExtension, { commonjs: true });
   },
 };
diff --git a/src/rules/max-dependencies.js b/src/rules/max-dependencies.js
index 4efff26824..c8e1b3ab13 100644
--- a/src/rules/max-dependencies.js
+++ b/src/rules/max-dependencies.js
@@ -1,4 +1,4 @@
-import isStaticRequire from '../core/staticRequire';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 const DEFAULT_MAX = 10;
@@ -36,23 +36,13 @@ module.exports = {
     const dependencies = new Set(); // keep track of dependencies
     let lastNode; // keep track of the last node to report on
 
-    return {
-      ImportDeclaration(node) {
-        dependencies.add(node.source.value);
-        lastNode = node.source;
-      },
-
-      CallExpression(node) {
-        if (isStaticRequire(node)) {
-          const [ requirePath ] = node.arguments;
-          dependencies.add(requirePath.value);
-          lastNode = node;
-        }
-      },
-
+    return Object.assign({
       'Program:exit': function () {
         countDependencies(dependencies, lastNode, context);
       },
-    };
+    }, moduleVisitor((source) => {
+      dependencies.add(source.value);
+      lastNode = source;
+    }, { commonjs: true }));
   },
 };
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index af8bcb87db..e2b0eadab4 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -207,8 +207,8 @@ module.exports = {
       allowBundledDeps: testConfig(options.bundledDependencies, filename) !== false,
     };
 
-    return moduleVisitor(node => {
-      reportIfMissing(context, deps, depsOptions, node, node.value);
+    return moduleVisitor((source, node) => {
+      reportIfMissing(context, deps, depsOptions, node, source.value);
     }, { commonjs: true });
   },
 };
diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index a234d3b7a8..d23bb36dd4 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -2,7 +2,7 @@ import minimatch from 'minimatch';
 
 import resolve from 'eslint-module-utils/resolve';
 import importType from '../core/importType';
-import isStaticRequire from '../core/staticRequire';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 module.exports = {
@@ -87,24 +87,8 @@ module.exports = {
       }
     }
 
-    return {
-      ImportDeclaration(node) {
-        checkImportForReaching(node.source.value, node.source);
-      },
-      ExportAllDeclaration(node) {
-        checkImportForReaching(node.source.value, node.source);
-      },
-      ExportNamedDeclaration(node) {
-        if (node.source) {
-          checkImportForReaching(node.source.value, node.source);
-        }
-      },
-      CallExpression(node) {
-        if (isStaticRequire(node)) {
-          const [ firstArgument ] = node.arguments;
-          checkImportForReaching(firstArgument.value, firstArgument);
-        }
-      },
-    };
+    return moduleVisitor((source) => {
+      checkImportForReaching(source.value, source);
+    }, { commonjs: true });
   },
 };
diff --git a/src/rules/no-nodejs-modules.js b/src/rules/no-nodejs-modules.js
index bca6c00d23..cbfb384d32 100644
--- a/src/rules/no-nodejs-modules.js
+++ b/src/rules/no-nodejs-modules.js
@@ -1,5 +1,5 @@
 import importType from '../core/importType';
-import isStaticRequire from '../core/staticRequire';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 function reportIfMissing(context, node, allowed, name) {
@@ -35,15 +35,8 @@ module.exports = {
     const options = context.options[0] || {};
     const allowed = options.allow || [];
 
-    return {
-      ImportDeclaration: function handleImports(node) {
-        reportIfMissing(context, node, allowed, node.source.value);
-      },
-      CallExpression: function handleRequires(node) {
-        if (isStaticRequire(node)) {
-          reportIfMissing(context, node, allowed, node.arguments[0].value);
-        }
-      },
-    };
+    return moduleVisitor((source, node) => {
+      reportIfMissing(context, node, allowed, source.value);
+    }, { commonjs: true });
   },
 };
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 55acfc930e..a856a8bb43 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -2,7 +2,7 @@ import containsPath from 'contains-path';
 import path from 'path';
 
 import resolve from 'eslint-module-utils/resolve';
-import isStaticRequire from '../core/staticRequire';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 import importType from '../core/importType';
 
@@ -109,17 +109,8 @@ module.exports = {
       });
     }
 
-    return {
-      ImportDeclaration(node) {
-        checkForRestrictedImportPath(node.source.value, node.source);
-      },
-      CallExpression(node) {
-        if (isStaticRequire(node)) {
-          const [ firstArgument ] = node.arguments;
-
-          checkForRestrictedImportPath(firstArgument.value, firstArgument);
-        }
-      },
-    };
+    return moduleVisitor((source) => {
+      checkForRestrictedImportPath(source.value, source);
+    }, { commonjs: true });
   },
 };
diff --git a/src/rules/no-self-import.js b/src/rules/no-self-import.js
index 6285c28c04..a10be56786 100644
--- a/src/rules/no-self-import.js
+++ b/src/rules/no-self-import.js
@@ -4,7 +4,7 @@
  */
 
 import resolve from 'eslint-module-utils/resolve';
-import isStaticRequire from '../core/staticRequire';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 function isImportingSelf(context, node, requireName) {
@@ -31,15 +31,8 @@ module.exports = {
     schema: [],
   },
   create: function (context) {
-    return {
-      ImportDeclaration(node) {
-        isImportingSelf(context, node, node.source.value);
-      },
-      CallExpression(node) {
-        if (isStaticRequire(node)) {
-          isImportingSelf(context, node, node.arguments[0].value);
-        }
-      },
-    };
+    return moduleVisitor((source, node) => {
+      isImportingSelf(context, node, source.value);
+    }, { commonjs: true });
   },
 };
diff --git a/src/rules/no-webpack-loader-syntax.js b/src/rules/no-webpack-loader-syntax.js
index 520a4cd240..b3228e0d28 100644
--- a/src/rules/no-webpack-loader-syntax.js
+++ b/src/rules/no-webpack-loader-syntax.js
@@ -1,4 +1,4 @@
-import isStaticRequire from '../core/staticRequire';
+import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 function reportIfNonStandard(context, node, name) {
@@ -19,15 +19,8 @@ module.exports = {
   },
 
   create: function (context) {
-    return {
-      ImportDeclaration: function handleImports(node) {
-        reportIfNonStandard(context, node, node.source.value);
-      },
-      CallExpression: function handleRequires(node) {
-        if (isStaticRequire(node)) {
-          reportIfNonStandard(context, node, node.arguments[0].value);
-        }
-      },
-    };
+    return moduleVisitor((source, node) => {
+      reportIfNonStandard(context, node, source.value);
+    }, { commonjs: true });
   },
 };
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 9ee22548e4..505ee8c70b 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -391,6 +391,22 @@ ruleTester.run('extensions', rule, {
       options: [ 'never', { ignorePackages: true } ],
     }),
 
+    test({
+      code: `
+        import foo from './foo.js'
+        import bar from './bar.json'
+        import Component from './Component.jsx'
+      `,
+      errors: [
+        {
+          message: 'Unexpected use of file extension "jsx" for "./Component.jsx"',
+          line: 4,
+          column: 31,
+        },
+      ],
+      options: [ 'always', { pattern: { jsx: 'never' } } ],
+    }),
+
     // export (#964)
     test({
       code: [
@@ -444,6 +460,48 @@ ruleTester.run('extensions', rule, {
         },
       ],
     }),
+    // require (#1230)
+    test({
+      code: [
+        'const { foo } = require("./foo")',
+        'export { foo }',
+      ].join('\n'),
+      options: [ 'always' ],
+      errors: [
+        {
+          message: 'Missing file extension for "./foo"',
+          line: 1,
+          column: 25,
+        },
+      ],
+    }),
+    test({
+      code: [
+        'const { foo } = require("./foo.js")',
+        'export { foo }',
+      ].join('\n'),
+      options: [ 'never' ],
+      errors: [
+        {
+          message: 'Unexpected use of file extension "js" for "./foo.js"',
+          line: 1,
+          column: 25,
+        },
+      ],
+    }),
+
+    // export { } from
+    test({
+      code: 'export { foo } from "./foo"',
+      options: [ 'always' ],
+      errors: [
+        {
+          message: 'Missing file extension for "./foo"',
+          line: 1,
+          column: 21,
+        },
+      ],
+    }),
     test({
       code: 'import foo from "@/ImNotAScopedModule"',
       options: ['always'],
@@ -454,5 +512,40 @@ ruleTester.run('extensions', rule, {
         },
       ],
     }),
+    test({
+      code: 'export { foo } from "./foo.js"',
+      options: [ 'never' ],
+      errors: [
+        {
+          message: 'Unexpected use of file extension "js" for "./foo.js"',
+          line: 1,
+          column: 21,
+        },
+      ],
+    }),
+
+    // export * from
+    test({
+      code: 'export * from "./foo"',
+      options: [ 'always' ],
+      errors: [
+        {
+          message: 'Missing file extension for "./foo"',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    test({
+      code: 'export * from "./foo.js"',
+      options: [ 'never' ],
+      errors: [
+        {
+          message: 'Unexpected use of file extension "js" for "./foo.js"',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
   ],
 });

From 6bb852836676a38d285c022c9ce03af7634db068 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 23 Jan 2021 07:01:44 -0800
Subject: [PATCH 235/767] [meta] fix changelog links

---
 CHANGELOG.md | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3868b448de..452a0fcfea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,11 +9,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
 - [`order`]: ignore non-module-level requires ([#1940], thanks [@golopot])
-- [`no-webpack-loader-syntax`]/TypeScript: avoid crash on missing name ([#1947], thanks @leonardodino)
-- [`no-extraneous-dependencies`]: Add package.json cache ([#1948], thanks @fa93hws)
-- [`prefer-default-export`]: handle empty array destructuring ([#1965], thanks @ljharb)
+- [`no-webpack-loader-syntax`]/TypeScript: avoid crash on missing name ([#1947], thanks [@leonardodino])
+- [`no-extraneous-dependencies`]: Add package.json cache ([#1948], thanks [@fa93hws])
+- [`prefer-default-export`]: handle empty array destructuring ([#1965], thanks [@ljharb])
 - [`no-unused-modules`]: make type imports mark a module as used (fixes #1924) ([#1974], thanks [@cherryblossom000])
-- [`import/no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
+- [`no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
@@ -72,7 +72,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: Fix re-export not counting as usage when used in combination with import ([#1722], thanks [@Ephem])
 - [`no-duplicates`]: Handle TS import type ([#1676], thanks [@kmui2])
 - [`newline-after-import`]: recognize decorators ([#1139], thanks [@atos1990])
-- [`no-unused-modules`]: Revert "[flow] `no-unused-modules`: add flow type support" ([#1770], thanks [@Hypnosphi])
+- [`no-unused-modules`]: Revert "[flow] [`no-unused-modules`]: add flow type support" ([#1770], thanks [@Hypnosphi])
 - TypeScript: Add nested namespace handling ([#1763], thanks [@julien1619])
 - [`namespace`]/`ExportMap`: Fix interface declarations for TypeScript ([#1764], thanks [@julien1619])
 - [`no-unused-modules`]: avoid order-dependence ([#1744], thanks [@darkartur])
@@ -82,7 +82,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - [Refactor] `no-extraneous-dependencies`: use moduleVisitor ([#1735], thanks [@adamborowski])
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
-- [readme] Remove duplicate no-unused-modules from docs ([#1690], thanks [@arvigeus])
+- [readme] Remove duplicate [`no-unused-modules`] from docs ([#1690], thanks [@arvigeus])
 - [Docs] `order`: fix bad inline config ([#1788], thanks [@nickofthyme])
 - [Tests] Add fix for Windows Subsystem for Linux ([#1786], thanks [@manuth])
 - [Docs] `no-unused-rules`: Fix docs for unused exports ([#1776], thanks [@barbogast])
@@ -107,7 +107,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-duplicates`]: allow duplicate imports if one is a namespace and the other not ([#1612], thanks [@sveyret])
 - Add some missing rule meta schemas and types ([#1620], thanks [@bmish])
 - [`named`]: for importing from a module which re-exports named exports from a `node_modules` module ([#1569], [#1447], thanks [@redbugz], [@kentcdodds])
-- [`order`]: Fix alphabetize for mixed requires and imports ([#5625], thanks [@wschurman])
+- [`order`]: Fix alphabetize for mixed requires and imports ([#1626], thanks [@wschurman])
 
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
@@ -230,7 +230,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - aliased internal modules that look like core modules ([#1297], thanks [@echenley])
 - [`namespace`]: add check for null ExportMap ([#1235], [#1144], thanks [@ljqx])
 - [ExportMap] fix condition for checking if block comment ([#1234], [#1233], thanks [@ljqx])
-- Fix overwriting of dynamic import() CallExpression ([`no-cycle`], [`no-relative-parent-import`], [`no-unresolved`], [`no-useless-path-segments`]) ([#1218], [#1166], [#1035], thanks [@vikr01])
+- Fix overwriting of dynamic import() CallExpression ([`no-cycle`], [`no-relative-parent-imports`], [`no-unresolved`], [`no-useless-path-segments`]) ([#1218], [#1166], [#1035], thanks [@vikr01])
 - [`export`]: false positives for TypeScript type + value export ([#1319], thanks [@bradzacher])
 - [`export`]: Support TypeScript namespaces ([#1320], [#1300], thanks [@bradzacher])
 
@@ -731,6 +731,7 @@ for info on changes for earlier releases.
 [`no-named-export`]: ./docs/rules/no-named-export.md
 [`no-namespace`]: ./docs/rules/no-namespace.md
 [`no-nodejs-modules`]: ./docs/rules/no-nodejs-modules.md
+[`no-relative-parent-imports`]: ./docs/rules/no-relative-parent-imports.md
 [`no-restricted-paths`]: ./docs/rules/no-restricted-paths.md
 [`no-self-import`]: ./docs/rules/no-self-import.md
 [`no-unassigned-import`]: ./docs/rules/no-unassigned-import.md
@@ -797,7 +798,7 @@ for info on changes for earlier releases.
 [#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
 [#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
 [#1631]: https://github.com/benmosher/eslint-plugin-import/issues/1631
-[#1625]: https://github.com/benmosher/eslint-plugin-import/pull/1625
+[#1626]: https://github.com/benmosher/eslint-plugin-import/pull/1626
 [#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
 [#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
 [#1616]: https://github.com/benmosher/eslint-plugin-import/issues/1616
@@ -823,6 +824,7 @@ for info on changes for earlier releases.
 [#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
 [#1494]: https://github.com/benmosher/eslint-plugin-import/pull/1494
 [#1493]: https://github.com/benmosher/eslint-plugin-import/pull/1493
+[#1491]: https://github.com/benmosher/eslint-plugin-import/pull/1491
 [#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
 [#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
 [#1447]: https://github.com/benmosher/eslint-plugin-import/pull/1447
@@ -1221,6 +1223,7 @@ for info on changes for earlier releases.
 [@feychenie]: https://github.com/feychenie
 [@kiwka]: https://github.com/kiwka
 [@loganfsmyth]: https://github.com/loganfsmyth
+[@golopot]: https://github.com/golopot
 [@johndevedu]: https://github.com/johndevedu
 [@charlessuh]: https://github.com/charlessuh
 [@kgregory]: https://github.com/kgregory
@@ -1300,3 +1303,8 @@ for info on changes for earlier releases.
 [@andreubotella]: https://github.com/andreubotella
 [@cherryblossom000]: https://github.com/cherryblossom000
 [@Blasz]: https://github.com/Blasz
+[@leonardodino]: https://github.com/leonardodino
+[@fa93hws]: https://github.com/fa93hws
+[@Librazy]: https://github.com/Librazy
+[@swernerx]: https://github.com/swernerx
+[@fsmaia]: https://github.com/fsmaia
\ No newline at end of file

From 196d655e731f4ce77795495c3639dbd5cd80a765 Mon Sep 17 00:00:00 2001
From: Matthias Kunnen <matthias.kunnen@gmail.com>
Date: Thu, 10 Dec 2020 17:40:56 +0000
Subject: [PATCH 236/767] [Fix] `first`: fix handling of `import = require`

Fixes #1957.
---
 CHANGELOG.md             |  4 +++-
 src/rules/first.js       | 12 +++++++---
 tests/src/rules/first.js | 50 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 452a0fcfea..123d480296 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`prefer-default-export`]: handle empty array destructuring ([#1965], thanks [@ljharb])
 - [`no-unused-modules`]: make type imports mark a module as used (fixes #1924) ([#1974], thanks [@cherryblossom000])
 - [`no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
+- [`first`]: fix handling of `import = require` ([#1963], thanks [@MatthiasKunnen])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
@@ -1307,4 +1308,5 @@ for info on changes for earlier releases.
 [@fa93hws]: https://github.com/fa93hws
 [@Librazy]: https://github.com/Librazy
 [@swernerx]: https://github.com/swernerx
-[@fsmaia]: https://github.com/fsmaia
\ No newline at end of file
+[@fsmaia]: https://github.com/fsmaia
+[@MatthiasKunnen]: https://github.com/MatthiasKunnen
diff --git a/src/rules/first.js b/src/rules/first.js
index 4d909bea3e..a3b7f24e03 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -1,5 +1,11 @@
 import docsUrl from '../docsUrl';
 
+function getImportValue(node) {
+  return node.type === 'ImportDeclaration'
+    ? node.source.value
+    : node.moduleReference.expression.value;
+}
+
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -43,13 +49,13 @@ module.exports = {
 
           anyExpressions = true;
 
-          if (node.type === 'ImportDeclaration') {
+          if (node.type === 'ImportDeclaration' || node.type === 'TSImportEqualsDeclaration') {
             if (absoluteFirst) {
-              if (/^\./.test(node.source.value)) {
+              if (/^\./.test(getImportValue(node))) {
                 anyRelative = true;
               } else if (anyRelative) {
                 context.report({
-                  node: node.source,
+                  node: node.type === 'ImportDeclaration' ? node.source : node.moduleReference,
                   message: 'Absolute imports should come before relative imports.',
                 });
               }
diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index e8b40eb98f..3f7301319d 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -1,4 +1,4 @@
-import { test } from '../utils';
+import { test, getTSParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 
@@ -66,3 +66,51 @@ ruleTester.run('first', rule, {
     }),  
   ],
 });
+
+context('TypeScript', function () {
+  getTSParsers()
+    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .forEach((parser) => {
+      const parserConfig = {
+        parser: parser,
+        settings: {
+          'import/parsers': { [parser]: ['.ts'] },
+          'import/resolver': { 'eslint-import-resolver-typescript': true },
+        },
+      };
+
+      ruleTester.run('order', rule, {
+        valid: [
+          test(
+            {
+              code: `
+                import y = require('bar');
+                import { x } from 'foo';
+                import z = require('baz');
+              `,
+              parser,
+            },
+            parserConfig,
+          ),
+        ],
+        invalid: [
+          test(
+            {
+              code: `
+                import { x } from './foo';
+                import y = require('bar');
+              `,
+              options: ['absolute-first'],
+              parser,
+              errors: [
+                {
+                  message: 'Absolute imports should come before relative imports.',
+                },
+              ],
+            },
+            parserConfig,
+          ),
+        ],
+      });
+    });
+});

From e22fc5333554ce94d07c0ebea212ddb781217c50 Mon Sep 17 00:00:00 2001
From: JEROMEH <jerome.henaff@amdocs.com>
Date: Tue, 24 Mar 2020 09:03:01 +0100
Subject: [PATCH 237/767] [Fix] `no-cycle`/`extensions`: fix isExternalModule
 usage

---
 CHANGELOG.md                  |  3 +++
 src/core/importType.js        |  5 ++++-
 src/rules/extensions.js       |  7 +++++--
 src/rules/no-cycle.js         |  7 ++++++-
 tests/src/rules/extensions.js | 29 +++++++++++++++++++++++++++++
 tests/src/rules/no-cycle.js   |  8 ++++----
 6 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 123d480296..54f9886cf5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]: make type imports mark a module as used (fixes #1924) ([#1974], thanks [@cherryblossom000])
 - [`no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
 - [`first`]: fix handling of `import = require` ([#1963], thanks [@MatthiasKunnen])
+- [`no-cycle`]/[`extensions`]: fix isExternalModule usage ([#1696], thanks [@paztis])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
@@ -788,6 +789,7 @@ for info on changes for earlier releases.
 [#1719]: https://github.com/benmosher/eslint-plugin-import/pull/1719
 [#1704]: https://github.com/benmosher/eslint-plugin-import/issues/1704
 [#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
+[#1696]: https://github.com/benmosher/eslint-plugin-import/pull/1696
 [#1691]: https://github.com/benmosher/eslint-plugin-import/pull/1691
 [#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
 [#1689]: https://github.com/benmosher/eslint-plugin-import/pull/1689
@@ -1310,3 +1312,4 @@ for info on changes for earlier releases.
 [@swernerx]: https://github.com/swernerx
 [@fsmaia]: https://github.com/fsmaia
 [@MatthiasKunnen]: https://github.com/MatthiasKunnen
+[@paztis]: https://github.com/paztis
diff --git a/src/core/importType.js b/src/core/importType.js
index b1273124de..82a47dd05e 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -41,8 +41,11 @@ function isSubpath(subpath, path) {
         (right >= normPath.length || normPath[right] === '/');
 }
 
-const externalModuleRegExp = /^\w/;
+const externalModuleRegExp = /^(?:\w|@)/;
 export function isExternalModule(name, settings, path) {
+  if (arguments.length < 3) {
+    throw new TypeError('isExternalModule: name, settings, and path are all required');
+  }
   return externalModuleRegExp.test(name) && isExternalPath(path, name, settings);
 }
 
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index c02ab0a62a..1b2475ec50 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -157,8 +157,11 @@ module.exports = {
       const extension = path.extname(resolvedPath || importPath).substring(1);
 
       // determine if this is a module
-      const isPackage = isExternalModule(importPath, context.settings)
-        || isScoped(importPath);
+      const isPackage = isExternalModule(
+        importPath,
+        context.settings,
+        resolve(importPath, context)
+      ) || isScoped(importPath);
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
         const extensionRequired = isUseOfExtensionRequired(extension, isPackage);
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index b72bd34fd4..77a24fefb6 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -3,6 +3,7 @@
  * @author Ben Mosher
  */
 
+import resolve from 'eslint-module-utils/resolve';
 import Exports from '../ExportMap';
 import { isExternalModule } from '../core/importType';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
@@ -41,7 +42,11 @@ module.exports = {
 
     const options = context.options[0] || {};
     const maxDepth = typeof options.maxDepth === 'number' ? options.maxDepth : Infinity;
-    const ignoreModule = (name) => options.ignoreExternal ? isExternalModule(name) : false;
+    const ignoreModule = (name) => options.ignoreExternal && isExternalModule(
+      name,
+      context.settings,
+      resolve(name, context)
+    );
 
     function checkSourceValue(sourceNode, importer) {
       if (ignoreModule(sourceNode.value)) {
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 505ee8c70b..34960ea54d 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -547,5 +547,34 @@ ruleTester.run('extensions', rule, {
         },
       ],
     }),
+    test({
+      code: 'import foo from "@/ImNotAScopedModule.js"',
+      options: ['never'],
+      errors: [
+        {
+          message: 'Unexpected use of file extension "js" for "@/ImNotAScopedModule.js"',
+          line: 1,
+        },
+      ],
+    }),
+    test({
+      code: `
+        import _ from 'lodash';
+        import m from '@test-scope/some-module/index.js';
+
+        import bar from './bar';
+      `,
+      options: ['never'],
+      settings: {
+        'import/resolver': 'webpack',
+        'import/external-module-folders': ['node_modules', 'symlinked-module'],
+      },
+      errors: [
+        {
+          message: 'Unexpected use of file extension "js" for "@test-scope/some-module/index.js"',
+          line: 3,
+        },
+      ],
+    }),
   ],
 });
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 1525781ce5..965fa36b7e 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -45,7 +45,7 @@ ruleTester.run('no-cycle', rule, {
       options: [{ ignoreExternal: true }],
       settings: {
         'import/resolver': 'webpack',
-        'import/external-module-folders': ['external'],
+        'import/external-module-folders': ['cycles/external'],
       },
     }),
     test({
@@ -53,7 +53,7 @@ ruleTester.run('no-cycle', rule, {
       options: [{ ignoreExternal: true }],
       settings: {
         'import/resolver': 'webpack',
-        'import/external-module-folders': ['external'],
+        'import/external-module-folders': ['cycles/external'],
       },
     }),
     test({
@@ -84,7 +84,7 @@ ruleTester.run('no-cycle', rule, {
       errors: [error(`Dependency cycle detected.`)],
       settings: {
         'import/resolver': 'webpack',
-        'import/external-module-folders': ['external'],
+        'import/external-module-folders': ['cycles/external'],
       },
     }),
     test({
@@ -92,7 +92,7 @@ ruleTester.run('no-cycle', rule, {
       errors: [error(`Dependency cycle via cycles/external/depth-one:1`)],
       settings: {
         'import/resolver': 'webpack',
-        'import/external-module-folders': ['external'],
+        'import/external-module-folders': ['cycles/external'],
       },
     }),
     test({

From 802ce7d49d912289d590f735bf9bd2d931064863 Mon Sep 17 00:00:00 2001
From: JEROMEH <jerome.henaff@amdocs.com>
Date: Tue, 24 Mar 2020 09:03:01 +0100
Subject: [PATCH 238/767] [Fix]
 `extensions`/`no-cycle`/`no-extraneous-dependencies`: Correct module real
 path resolution

add real support of isAbsolute (windows + unix support)

importType refactoring: use the real resolved package path to check if external of internal, and not the name only like before: in case of monorepo, external modules are not under node_modules due to symlink but still out of the module.

correct tests node_modules dependencies to really provide teh package.json like in real usage

correct no-extraneous-dependencies rule: get the real name from the resolved package.json. If not aliased imports (alias/react for example) will not be correctly interpreted

change path import

add real support of isAbsolute (windows + unix support)

correct no-extraneous-dependencies rule: get the real name from the resolved package.json. If not aliased imports (alias/react for example) will not be correctly interpreted

even externals like "a/file.js" must not use extension.
only module names like 'module.js' and '@scope/module.js' are allowed

correct bad external definition: must be the folder path under the root of the module.
Here the module root is test folder, not cycles folder
---
 CHANGELOG.md                                  |  1 +
 package.json                                  |  1 +
 src/core/importType.js                        | 72 ++++++++++---------
 src/core/packagePath.js                       | 18 +++++
 src/rules/extensions.js                       |  5 +-
 src/rules/no-cycle.js                         |  3 +-
 src/rules/no-extraneous-dependencies.js       | 19 +++--
 .../node_modules/@generated/bar/package.json  |  3 +
 .../node_modules/@generated/foo/package.json  |  3 +
 .../@org/not-a-dependency/package.json        |  3 +
 .../node_modules/@org/package/package.json    |  3 +
 tests/files/node_modules/a/package.json       |  3 +
 tests/files/node_modules/chai/package.json    |  3 +
 .../node_modules/es6-module/package.json      |  3 +
 .../eslint-import-resolver-foo/package.json   |  3 +
 tests/files/node_modules/exceljs/package.json |  1 +
 tests/files/node_modules/jquery/package.json  |  3 +
 .../node_modules/jsx-module/package.json      |  3 +
 tests/files/node_modules/left-pad             |  1 -
 tests/files/node_modules/left-pad/index.js    |  0
 .../node_modules/left-pad/not-a-dependency    |  0
 .../files/node_modules/left-pad/package.json  |  3 +
 .../not-a-dependency/package.json             |  3 +
 tests/files/node_modules/react                |  1 -
 tests/files/node_modules/react/index.js       |  1 +
 .../files/node_modules/react/not-a-dependency |  0
 tests/files/node_modules/react/package.json   |  3 +
 tests/files/webpack.config.js                 |  3 +
 tests/src/core/importType.js                  | 15 ++--
 tests/src/rules/no-extraneous-dependencies.js |  8 +++
 tests/src/rules/order.js                      | 19 +----
 31 files changed, 140 insertions(+), 67 deletions(-)
 create mode 100644 src/core/packagePath.js
 create mode 100644 tests/files/node_modules/@generated/bar/package.json
 create mode 100644 tests/files/node_modules/@generated/foo/package.json
 create mode 100644 tests/files/node_modules/@org/not-a-dependency/package.json
 create mode 100644 tests/files/node_modules/@org/package/package.json
 create mode 100644 tests/files/node_modules/a/package.json
 create mode 100644 tests/files/node_modules/chai/package.json
 create mode 100644 tests/files/node_modules/es6-module/package.json
 create mode 100644 tests/files/node_modules/eslint-import-resolver-foo/package.json
 create mode 100644 tests/files/node_modules/jquery/package.json
 create mode 100644 tests/files/node_modules/jsx-module/package.json
 delete mode 120000 tests/files/node_modules/left-pad
 create mode 100644 tests/files/node_modules/left-pad/index.js
 create mode 100644 tests/files/node_modules/left-pad/not-a-dependency
 create mode 100644 tests/files/node_modules/left-pad/package.json
 create mode 100644 tests/files/node_modules/not-a-dependency/package.json
 delete mode 120000 tests/files/node_modules/react
 create mode 100644 tests/files/node_modules/react/index.js
 create mode 100644 tests/files/node_modules/react/not-a-dependency
 create mode 100644 tests/files/node_modules/react/package.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 54f9886cf5..bd503f04aa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
 - [`first`]: fix handling of `import = require` ([#1963], thanks [@MatthiasKunnen])
 - [`no-cycle`]/[`extensions`]: fix isExternalModule usage ([#1696], thanks [@paztis])
+- [`extensions`]/[`no-cycle`]/[`no-extraneous-dependencies`]: Correct module real path resolution ([#1696], thanks [@paztis])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
diff --git a/package.json b/package.json
index f584a8dda4..eb259e4aaf 100644
--- a/package.json
+++ b/package.json
@@ -104,6 +104,7 @@
     "doctrine": "1.5.0",
     "eslint-import-resolver-node": "^0.3.4",
     "eslint-module-utils": "^2.6.0",
+    "find-up": "^2.0.0",
     "has": "^1.0.3",
     "is-core-module": "^1.0.2",
     "minimatch": "^3.0.4",
diff --git a/src/core/importType.js b/src/core/importType.js
index 82a47dd05e..ecea976f4a 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -1,6 +1,8 @@
+import { isAbsolute as nodeIsAbsolute, relative, resolve as nodeResolve } from 'path';
 import isCoreModule from 'is-core-module';
 
 import resolve from 'eslint-module-utils/resolve';
+import { getContextPackagePath } from './packagePath';
 
 function baseModule(name) {
   if (isScoped(name)) {
@@ -12,7 +14,7 @@ function baseModule(name) {
 }
 
 export function isAbsolute(name) {
-  return name && name.startsWith('/');
+  return nodeIsAbsolute(name);
 }
 
 // path is defined only when a resolver resolves to a non-standard path
@@ -23,35 +25,43 @@ export function isBuiltIn(name, settings, path) {
   return isCoreModule(base) || extras.indexOf(base) > -1;
 }
 
-function isExternalPath(path, name, settings) {
-  const folders = (settings && settings['import/external-module-folders']) || ['node_modules'];
-  return !path || folders.some(folder => isSubpath(folder, path));
+export function isExternalModule(name, settings, path, context) {
+  if (arguments.length < 4) {
+    throw new TypeError('isExternalModule: name, settings, path, and context are all required');
+  }
+  return isModule(name) && isExternalPath(name, settings, path, getContextPackagePath(context));
+}
+
+export function isExternalModuleMain(name, settings, path, context) {
+  return isModuleMain(name) && isExternalPath(name, settings, path, getContextPackagePath(context));
 }
 
-function isSubpath(subpath, path) {
-  const normPath = path.replace(/\\/g, '/');
-  const normSubpath = subpath.replace(/\\/g, '/').replace(/\/$/, '');
-  if (normSubpath.length === 0) {
+function isExternalPath(name, settings, path, packagePath) {
+  const internalScope = (settings && settings['import/internal-regex']);
+  if (internalScope && new RegExp(internalScope).test(name)) {
     return false;
   }
-  const left = normPath.indexOf(normSubpath);
-  const right = left + normSubpath.length;
-  return left !== -1 &&
-        (left === 0 || normSubpath[0] !== '/' && normPath[left - 1] === '/') &&
-        (right >= normPath.length || normPath[right] === '/');
-}
 
-const externalModuleRegExp = /^(?:\w|@)/;
-export function isExternalModule(name, settings, path) {
-  if (arguments.length < 3) {
-    throw new TypeError('isExternalModule: name, settings, and path are all required');
+  if (!path || relative(packagePath, path).startsWith('..')) {
+    return true;
   }
-  return externalModuleRegExp.test(name) && isExternalPath(path, name, settings);
+
+  const folders = (settings && settings['import/external-module-folders']) || ['node_modules'];
+  return folders.some((folder) => {
+    const folderPath = nodeResolve(packagePath, folder);
+    const relativePath = relative(folderPath, path);
+    return !relativePath.startsWith('..');
+  });
+}
+
+const moduleRegExp = /^\w/;
+function isModule(name) {
+  return name && moduleRegExp.test(name);
 }
 
-const externalModuleMainRegExp = /^[\w]((?!\/).)*$/;
-export function isExternalModuleMain(name, settings, path) {
-  return externalModuleMainRegExp.test(name) && isExternalPath(path, name, settings);
+const moduleMainRegExp = /^[\w]((?!\/).)*$/;
+function isModuleMain(name) {
+  return name && moduleMainRegExp.test(name);
 }
 
 const scopedRegExp = /^@[^/]*\/?[^/]+/;
@@ -64,12 +74,6 @@ export function isScopedMain(name) {
   return name && scopedMainRegExp.test(name);
 }
 
-function isInternalModule(name, settings, path) {
-  const internalScope = (settings && settings['import/internal-regex']);
-  const matchesScopedOrExternalRegExp = scopedRegExp.test(name) || externalModuleRegExp.test(name);
-  return (matchesScopedOrExternalRegExp && (internalScope && new RegExp(internalScope).test(name) || !isExternalPath(path, name, settings)));
-}
-
 function isRelativeToParent(name) {
   return/^\.\.$|^\.\.[\\/]/.test(name);
 }
@@ -83,12 +87,14 @@ function isRelativeToSibling(name) {
   return /^\.[\\/]/.test(name);
 }
 
-function typeTest(name, settings, path) {
+function typeTest(name, context, path) {
+  const { settings } = context;
   if (isAbsolute(name, settings, path)) { return 'absolute'; }
   if (isBuiltIn(name, settings, path)) { return 'builtin'; }
-  if (isInternalModule(name, settings, path)) { return 'internal'; }
-  if (isExternalModule(name, settings, path)) { return 'external'; }
-  if (isScoped(name, settings, path)) { return 'external'; }
+  if (isModule(name, settings, path) || isScoped(name, settings, path)) {
+    const packagePath = getContextPackagePath(context);
+    return isExternalPath(name, settings, path, packagePath) ? 'external' : 'internal';
+  }
   if (isRelativeToParent(name, settings, path)) { return 'parent'; }
   if (isIndex(name, settings, path)) { return 'index'; }
   if (isRelativeToSibling(name, settings, path)) { return 'sibling'; }
@@ -100,5 +106,5 @@ export function isScopedModule(name) {
 }
 
 export default function resolveImportType(name, context) {
-  return typeTest(name, context.settings, resolve(name, context));
+  return typeTest(name, context, resolve(name, context));
 }
diff --git a/src/core/packagePath.js b/src/core/packagePath.js
new file mode 100644
index 0000000000..e95b066668
--- /dev/null
+++ b/src/core/packagePath.js
@@ -0,0 +1,18 @@
+import { dirname } from 'path';
+import findUp from 'find-up';
+import readPkgUp from 'read-pkg-up';
+
+
+export function getContextPackagePath(context) {
+  return getFilePackagePath(context.getFilename());
+}
+
+export function getFilePackagePath(filePath) {
+  const fp = findUp.sync('package.json', { cwd: filePath });
+  return dirname(fp);
+}
+
+export function getFilePackageName(filePath) {
+  const { pkg } = readPkgUp.sync({ cwd: filePath, normalize: false });
+  return pkg && pkg.name;
+}
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 1b2475ec50..bd47afa99d 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -130,8 +130,8 @@ module.exports = {
     function isExternalRootModule(file) {
       const slashCount = file.split('/').length - 1;
 
+      if (slashCount === 0)  return true;
       if (isScopedModule(file) && slashCount <= 1) return true;
-      if (isExternalModule(file, context, resolve(file, context)) && !slashCount) return true;
       return false;
     }
 
@@ -160,7 +160,8 @@ module.exports = {
       const isPackage = isExternalModule(
         importPath,
         context.settings,
-        resolve(importPath, context)
+        resolve(importPath, context),
+        context
       ) || isScoped(importPath);
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 77a24fefb6..74b77cbc3c 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -45,7 +45,8 @@ module.exports = {
     const ignoreModule = (name) => options.ignoreExternal && isExternalModule(
       name,
       context.settings,
-      resolve(name, context)
+      resolve(name, context),
+      context
     );
 
     function checkSourceValue(sourceNode, importer) {
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index e2b0eadab4..2e541584f1 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -5,6 +5,7 @@ import minimatch from 'minimatch';
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import importType from '../core/importType';
+import { getFilePackageName } from '../core/packagePath';
 import docsUrl from '../docsUrl';
 
 const depFieldCache = new Map();
@@ -116,6 +117,15 @@ function optDepErrorMessage(packageName) {
     `not optionalDependencies.`;
 }
 
+function getModuleOriginalName(name) {
+  const [first, second] = name.split('/');
+  return first.startsWith('@') ? `${first}/${second}` : first;
+}
+
+function getModuleRealName(resolved) {
+  return getFilePackageName(resolved);
+}
+
 function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types
   if (node.importKind === 'type' || (node.parent && node.parent.importKind === 'type')) {
@@ -129,10 +139,11 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
   const resolved = resolve(name, context);
   if (!resolved) { return; }
 
-  const splitName = name.split('/');
-  const packageName = splitName[0][0] === '@'
-    ? splitName.slice(0, 2).join('/')
-    : splitName[0];
+  // get the real name from the resolved package.json
+  // if not aliased imports (alias/react for example) will not be correctly interpreted
+  // fallback on original name in case no package.json found
+  const packageName = getModuleRealName(resolved) || getModuleOriginalName(name);
+
   const isInDeps = deps.dependencies[packageName] !== undefined;
   const isInDevDeps = deps.devDependencies[packageName] !== undefined;
   const isInOptDeps = deps.optionalDependencies[packageName] !== undefined;
diff --git a/tests/files/node_modules/@generated/bar/package.json b/tests/files/node_modules/@generated/bar/package.json
new file mode 100644
index 0000000000..b70db688d6
--- /dev/null
+++ b/tests/files/node_modules/@generated/bar/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "@generated/bar"
+}
diff --git a/tests/files/node_modules/@generated/foo/package.json b/tests/files/node_modules/@generated/foo/package.json
new file mode 100644
index 0000000000..c5d0d6b332
--- /dev/null
+++ b/tests/files/node_modules/@generated/foo/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "@generated/foo"
+}
diff --git a/tests/files/node_modules/@org/not-a-dependency/package.json b/tests/files/node_modules/@org/not-a-dependency/package.json
new file mode 100644
index 0000000000..a81c5f2919
--- /dev/null
+++ b/tests/files/node_modules/@org/not-a-dependency/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "@org/not-a-dependency"
+}
diff --git a/tests/files/node_modules/@org/package/package.json b/tests/files/node_modules/@org/package/package.json
new file mode 100644
index 0000000000..7cb5d73daf
--- /dev/null
+++ b/tests/files/node_modules/@org/package/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "@org/package"
+}
diff --git a/tests/files/node_modules/a/package.json b/tests/files/node_modules/a/package.json
new file mode 100644
index 0000000000..44d21f1fa7
--- /dev/null
+++ b/tests/files/node_modules/a/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "a"
+}
diff --git a/tests/files/node_modules/chai/package.json b/tests/files/node_modules/chai/package.json
new file mode 100644
index 0000000000..00acdd2ca7
--- /dev/null
+++ b/tests/files/node_modules/chai/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "chai"
+}
diff --git a/tests/files/node_modules/es6-module/package.json b/tests/files/node_modules/es6-module/package.json
new file mode 100644
index 0000000000..0bff4dda08
--- /dev/null
+++ b/tests/files/node_modules/es6-module/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "es6-module"
+}
diff --git a/tests/files/node_modules/eslint-import-resolver-foo/package.json b/tests/files/node_modules/eslint-import-resolver-foo/package.json
new file mode 100644
index 0000000000..190e8e6e4c
--- /dev/null
+++ b/tests/files/node_modules/eslint-import-resolver-foo/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "eslint-import-resolver-foo"
+}
diff --git a/tests/files/node_modules/exceljs/package.json b/tests/files/node_modules/exceljs/package.json
index 70d59eaaa7..f2412292d2 100644
--- a/tests/files/node_modules/exceljs/package.json
+++ b/tests/files/node_modules/exceljs/package.json
@@ -1,3 +1,4 @@
 {
+  "name": "exceljs",
   "main": "./excel.js"
 }
diff --git a/tests/files/node_modules/jquery/package.json b/tests/files/node_modules/jquery/package.json
new file mode 100644
index 0000000000..e0563fbf49
--- /dev/null
+++ b/tests/files/node_modules/jquery/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "jquery"
+}
diff --git a/tests/files/node_modules/jsx-module/package.json b/tests/files/node_modules/jsx-module/package.json
new file mode 100644
index 0000000000..6edbe5fc98
--- /dev/null
+++ b/tests/files/node_modules/jsx-module/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "jsx-module"
+}
diff --git a/tests/files/node_modules/left-pad b/tests/files/node_modules/left-pad
deleted file mode 120000
index dbbbe75d2d..0000000000
--- a/tests/files/node_modules/left-pad
+++ /dev/null
@@ -1 +0,0 @@
-not-a-dependency
\ No newline at end of file
diff --git a/tests/files/node_modules/left-pad/index.js b/tests/files/node_modules/left-pad/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/node_modules/left-pad/not-a-dependency b/tests/files/node_modules/left-pad/not-a-dependency
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/node_modules/left-pad/package.json b/tests/files/node_modules/left-pad/package.json
new file mode 100644
index 0000000000..a95a5e067f
--- /dev/null
+++ b/tests/files/node_modules/left-pad/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "left-pad"
+}
diff --git a/tests/files/node_modules/not-a-dependency/package.json b/tests/files/node_modules/not-a-dependency/package.json
new file mode 100644
index 0000000000..8572331218
--- /dev/null
+++ b/tests/files/node_modules/not-a-dependency/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "not-a-dependency"
+}
diff --git a/tests/files/node_modules/react b/tests/files/node_modules/react
deleted file mode 120000
index dbbbe75d2d..0000000000
--- a/tests/files/node_modules/react
+++ /dev/null
@@ -1 +0,0 @@
-not-a-dependency
\ No newline at end of file
diff --git a/tests/files/node_modules/react/index.js b/tests/files/node_modules/react/index.js
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/tests/files/node_modules/react/index.js
@@ -0,0 +1 @@
+
diff --git a/tests/files/node_modules/react/not-a-dependency b/tests/files/node_modules/react/not-a-dependency
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/node_modules/react/package.json b/tests/files/node_modules/react/package.json
new file mode 100644
index 0000000000..bcbea4166f
--- /dev/null
+++ b/tests/files/node_modules/react/package.json
@@ -0,0 +1,3 @@
+{
+  "name": "react"
+}
diff --git a/tests/files/webpack.config.js b/tests/files/webpack.config.js
index 980c32425e..6a5dc0b88c 100644
--- a/tests/files/webpack.config.js
+++ b/tests/files/webpack.config.js
@@ -2,5 +2,8 @@ module.exports = {
   resolve: {
     extensions: ['', '.js', '.jsx'],
     root: __dirname,
+    alias: {
+      'alias/chai$': 'chai' // alias for no-extraneous-dependencies tests
+    }
   },
 }
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 5eb655e552..371a3d7397 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -128,7 +128,7 @@ describe('importType(name)', function () {
 
   it("should return 'internal' for module from 'node_modules' if 'node_modules' missed in 'external-module-folders'", function() {
     const foldersContext = testContext({ 'import/external-module-folders': [] });
-    expect(importType('resolve', foldersContext)).to.equal('internal');
+    expect(importType('chai', foldersContext)).to.equal('internal');
   });
 
   it("should return 'internal' for module from 'node_modules' if its name matched 'internal-regex'", function() {
@@ -188,7 +188,7 @@ describe('importType(name)', function () {
 
     const foldersContext = testContext({
       'import/resolver': 'webpack',
-      'import/external-module-folders': ['files/symlinked-module'],
+      'import/external-module-folders': ['symlinked-module'],
     });
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
   });
@@ -202,7 +202,7 @@ describe('importType(name)', function () {
 
     const foldersContext_2 = testContext({
       'import/resolver': 'webpack',
-      'import/external-module-folders': ['les/symlinked-module'],
+      'import/external-module-folders': ['ymlinked-module'],
     });
     expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal');
   });
@@ -210,7 +210,7 @@ describe('importType(name)', function () {
   it('returns "external" for a scoped module from a symlinked directory which partial path ending w/ slash is contained in "external-module-folders" (webpack resolver)', function() {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
-      'import/external-module-folders': ['files/symlinked-module/'],
+      'import/external-module-folders': ['symlinked-module/'],
     });
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
   });
@@ -218,7 +218,7 @@ describe('importType(name)', function () {
   it('returns "internal" for a scoped module from a symlinked directory when "external-module-folders" contains an absolute path resembling directory‘s relative path (webpack resolver)', function() {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
-      'import/external-module-folders': ['/files/symlinked-module'],
+      'import/external-module-folders': ['/symlinked-module'],
     });
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('internal');
   });
@@ -232,10 +232,11 @@ describe('importType(name)', function () {
   });
 
   it('`isExternalModule` works with windows directory separator', function() {
-    expect(isExternalModule('foo', {}, 'E:\\path\\to\\node_modules\\foo')).to.equal(true);
+    const context = testContext();
+    expect(isExternalModule('foo', {}, 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
     expect(isExternalModule('foo', {
       'import/external-module-folders': ['E:\\path\\to\\node_modules'],
-    }, 'E:\\path\\to\\node_modules\\foo')).to.equal(true);
+    }, 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
   });
 
   it('correctly identifies scoped modules with `isScopedModule`', () => {
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 56eb555eb1..c94e9f977e 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -314,6 +314,14 @@ ruleTester.run('no-extraneous-dependencies', rule, {
         message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
       }],
     }),
+    test({
+      code: 'import chai from "alias/chai";',
+      settings: { 'import/resolver': 'webpack' },
+      errors: [{
+        // missing dependency is chai not alias
+        message: "'chai' should be listed in the project's dependencies. Run 'npm i -S chai' to add it",
+      }],
+    }),
   ],
 });
 
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index b95681b426..c599a73c82 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -376,23 +376,6 @@ ruleTester.run('order', rule, {
         'import/external-module-folders': ['node_modules', 'symlinked-module'],
       },
     }),
-    // Monorepo setup, using Webpack resolver, partial workspace folder path
-    // in external-module-folders
-    test({
-      code: `
-        import _ from 'lodash';
-        import m from '@test-scope/some-module';
-
-        import bar from './bar';
-      `,
-      options: [{
-        'newlines-between': 'always',
-      }],
-      settings: {
-        'import/resolver': 'webpack',
-        'import/external-module-folders': ['node_modules', 'files/symlinked-module'],
-      },
-    }),
     // Monorepo setup, using Node resolver (doesn't resolve symlinks)
     test({
       code: `
@@ -406,7 +389,7 @@ ruleTester.run('order', rule, {
       }],
       settings: {
         'import/resolver': 'node',
-        'import/external-module-folders': ['node_modules', 'files/symlinked-module'],
+        'import/external-module-folders': ['node_modules', 'symlinked-module'],
       },
     }),
     // Option: newlines-between: 'always'

From 4c82ad09977d38212a72392e9e9860da72794389 Mon Sep 17 00:00:00 2001
From: Flo Edelmann <florian-edelmann@online.de>
Date: Tue, 1 Dec 2020 11:06:05 +0100
Subject: [PATCH 239/767] [New] `no-commonjs`: Allow expressionless template
 literals

---
 CHANGELOG.md                          |  5 +++++
 src/rules/no-commonjs.js              | 10 ++++++----
 tests/src/rules/no-commonjs.js        |  6 ++++++
 tests/src/rules/no-dynamic-require.js |  8 ++++++++
 4 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd503f04aa..57495c4f54 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Added
+- [`no-commonjs`]: Also detect require calls with expressionless template literals: ``` require(`x`) ``` ([#1958], thanks [@FloEdelmann])
+
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
 - [`order`]: ignore non-module-level requires ([#1940], thanks [@golopot])
@@ -752,6 +755,7 @@ for info on changes for earlier releases.
 [#1944]: https://github.com/benmosher/eslint-plugin-import/pull/1944
 [#1924]: https://github.com/benmosher/eslint-plugin-import/issues/1924
 [#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
+[#1958]: https://github.com/benmosher/eslint-plugin-import/pull/1958
 [#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
 [#1947]: https://github.com/benmosher/eslint-plugin-import/pull/1947
 [#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940
@@ -1314,3 +1318,4 @@ for info on changes for earlier releases.
 [@fsmaia]: https://github.com/fsmaia
 [@MatthiasKunnen]: https://github.com/MatthiasKunnen
 [@paztis]: https://github.com/paztis
+[@FloEdelmann]: https://github.com/FloEdelmann
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index 7b38739ec8..08d29a0cdb 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -45,6 +45,11 @@ function isConditional(node) {
   return false;
 }
 
+function isLiteralString(node) {
+  return (node.type === 'Literal' && typeof node.value === 'string') ||
+    (node.type === 'TemplateLiteral' && node.expressions.length === 0);
+}
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -114,10 +119,7 @@ module.exports = {
         if (call.callee.name !== 'require') return;
 
         if (call.arguments.length !== 1) return;
-        const module = call.arguments[0];
-
-        if (module.type !== 'Literal') return;
-        if (typeof module.value !== 'string') return;
+        if (!isLiteralString(call.arguments[0])) return;
 
         if (allowRequire(call, options)) return;
 
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index b016602b29..b1d8c03c1d 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -37,6 +37,7 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
     { code: "var bar = require('./bar', true);" },
     { code: "var bar = proxyquire('./bar');" },
     { code: "var bar = require('./ba' + 'r');" },
+    { code: 'var bar = require(`x${1}`);', parserOptions: { ecmaVersion: 2015 } },
     { code: 'var zero = require(0);' },
     { code: 'require("x")', options: [{ allowRequire: true }] },
 
@@ -71,6 +72,11 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
       { code: 'var x = require("x")', output: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
       { code: 'x = require("x")', output: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
       { code: 'require("x")', output: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+      { code: 'require(`x`)',
+        parserOptions: { ecmaVersion: 2015 },
+        output: 'require(`x`)',
+        errors: [ { message: IMPORT_MESSAGE }],
+      },
 
       { code: 'if (typeof window !== "undefined") require("x")',
         options: [{ allowConditionalRequire: false }],
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index 0519664427..7dba242313 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -44,5 +44,13 @@ ruleTester.run('no-dynamic-require', rule, {
       code: 'require(name + "foo", "bar")',
       errors: [error],
     }),
+    test({
+      code: 'require(`foo${x}`)',
+      errors: [error],
+    }),
+    test({
+      code: 'var foo = require(`foo${x}`)',
+      errors: [error],
+    }),
   ],
 });

From 9fa6bc9a05dfca906f6a485c92b15845c2490a32 Mon Sep 17 00:00:00 2001
From: Takanori Oishi <takanori0014@live.jp>
Date: Sat, 12 Sep 2020 15:02:53 +0900
Subject: [PATCH 240/767] [Docs] `no-named-as-default`: add semicolon

---
 CHANGELOG.md                      | 3 +++
 docs/rules/no-named-as-default.md | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 57495c4f54..347034bbc6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
+- [Docs] [`no-named-as-default`]: add semicolon ([#1897], thanks [@bicstone])
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -759,6 +760,7 @@ for info on changes for earlier releases.
 [#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
 [#1947]: https://github.com/benmosher/eslint-plugin-import/pull/1947
 [#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940
+[#1897]: https://github.com/benmosher/eslint-plugin-import/pull/1897
 [#1889]: https://github.com/benmosher/eslint-plugin-import/pull/1889
 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
 [#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
@@ -1319,3 +1321,4 @@ for info on changes for earlier releases.
 [@MatthiasKunnen]: https://github.com/MatthiasKunnen
 [@paztis]: https://github.com/paztis
 [@FloEdelmann]: https://github.com/FloEdelmann
+[@bicstone]: https://github.com/bicstone
\ No newline at end of file
diff --git a/docs/rules/no-named-as-default.md b/docs/rules/no-named-as-default.md
index 0a92b7b517..0421413833 100644
--- a/docs/rules/no-named-as-default.md
+++ b/docs/rules/no-named-as-default.md
@@ -31,7 +31,7 @@ For post-ES2015 `export` extensions, this also prevents exporting the default fr
 
 ```js
 // valid:
-export foo from './foo.js'
+export foo from './foo.js';
 
 // message: Using exported name 'bar' as identifier for default export.
 export bar from './foo.js';

From 877e22c79bb870a2bf6b610b645473cb7bb27b68 Mon Sep 17 00:00:00 2001
From: Alexey <lesha.ogonkov@gmail.com>
Date: Thu, 10 Dec 2020 12:34:34 +0300
Subject: [PATCH 241/767] [resolvers/webpack] [patch] Add warning about async
 Webpack configs

---
 resolvers/webpack/CHANGELOG.md                |  8 ++++++++
 resolvers/webpack/README.md                   |  4 ++++
 resolvers/webpack/index.js                    | 20 ++++++++++---------
 resolvers/webpack/test/.eslintrc              |  1 +
 resolvers/webpack/test/config.js              | 10 ++++++++++
 .../test/files/webpack.config.async.js        |  7 +++++++
 6 files changed, 41 insertions(+), 9 deletions(-)
 create mode 100644 resolvers/webpack/test/files/webpack.config.async.js

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index df66f8bbb6..8ab56e1a01 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Changed
+ - Add warning about async Webpack configs ([#1962], thanks [@ogonkov])
+- Replace node-libs-browser with is-core-module ([#1967], thanks [@andersk])
+
 ## 0.13.0 - 2020-09-27
 
 ### Breaking
@@ -137,6 +141,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - `interpret` configs (such as `.babel.js`).
   Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
+[#1967]: https://github.com/benmosher/eslint-plugin-import/pull/1967
+[#1962]: https://github.com/benmosher/eslint-plugin-import/pull/1962
 [#1705]: https://github.com/benmosher/eslint-plugin-import/pull/1705
 [#1595]: https://github.com/benmosher/eslint-plugin-import/pull/1595
 [#1503]: https://github.com/benmosher/eslint-plugin-import/pull/1503
@@ -193,3 +199,5 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@Aghassi]: https://github.com/Aghassi
 [@migueloller]: https://github.com/migueloller
 [@opichals]: https://github.com/opichals
+[@andersk]: https://github.com/andersk
+[@ogonkov]: https://github.com/ogonkov
\ No newline at end of file
diff --git a/resolvers/webpack/README.md b/resolvers/webpack/README.md
index 9646dc24e4..cdb9222fae 100644
--- a/resolvers/webpack/README.md
+++ b/resolvers/webpack/README.md
@@ -4,6 +4,10 @@
 
 Webpack-literate module resolution plugin for [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import).
 
+> :boom: Only "synchronous" Webpack configs are supported at the moment.
+> If your config returns a `Promise`, this will cause problems.
+> Consider splitting your asynchronous configuration to a separate config.
+
 Published separately to allow pegging to a specific version in case of breaking
 changes.
 
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 32d5bdff6c..b1d7e15134 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -125,10 +125,16 @@ exports.resolve = function (source, file, settings) {
     }
   }
 
+  if (typeof webpackConfig.then === 'function') {
+    webpackConfig = {};
+
+    console.warn('Webpack config returns a `Promise`; that signature is not supported at the moment. Using empty object instead.');
+  }
+
   if (webpackConfig == null) {
     webpackConfig = {};
 
-    console.warn('No webpack configuration with a "resolve" field found. Using empty object instead');
+    console.warn('No webpack configuration with a "resolve" field found. Using empty object instead.');
   }
 
   log('Using config: ', webpackConfig);
@@ -243,19 +249,15 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
   const SyncNodeJsInputFileSystem = webpackRequire('enhanced-resolve/lib/SyncNodeJsInputFileSystem');
 
   const ModuleAliasPlugin = webpackRequire('enhanced-resolve/lib/ModuleAliasPlugin');
-  const ModulesInDirectoriesPlugin =
-    webpackRequire('enhanced-resolve/lib/ModulesInDirectoriesPlugin');
+  const ModulesInDirectoriesPlugin = webpackRequire('enhanced-resolve/lib/ModulesInDirectoriesPlugin');
   const ModulesInRootPlugin = webpackRequire('enhanced-resolve/lib/ModulesInRootPlugin');
   const ModuleAsFilePlugin = webpackRequire('enhanced-resolve/lib/ModuleAsFilePlugin');
   const ModuleAsDirectoryPlugin = webpackRequire('enhanced-resolve/lib/ModuleAsDirectoryPlugin');
-  const DirectoryDescriptionFilePlugin =
-    webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFilePlugin');
-  const DirectoryDefaultFilePlugin =
-    webpackRequire('enhanced-resolve/lib/DirectoryDefaultFilePlugin');
+  const DirectoryDescriptionFilePlugin = webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFilePlugin');
+  const DirectoryDefaultFilePlugin = webpackRequire('enhanced-resolve/lib/DirectoryDefaultFilePlugin');
   const FileAppendPlugin = webpackRequire('enhanced-resolve/lib/FileAppendPlugin');
   const ResultSymlinkPlugin = webpackRequire('enhanced-resolve/lib/ResultSymlinkPlugin');
-  const DirectoryDescriptionFileFieldAliasPlugin =
-    webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFileFieldAliasPlugin');
+  const DirectoryDescriptionFileFieldAliasPlugin = webpackRequire('enhanced-resolve/lib/DirectoryDescriptionFileFieldAliasPlugin');
 
   const resolver = new Resolver(new SyncNodeJsInputFileSystem());
 
diff --git a/resolvers/webpack/test/.eslintrc b/resolvers/webpack/test/.eslintrc
index 2ad1adee92..a9cee4100d 100644
--- a/resolvers/webpack/test/.eslintrc
+++ b/resolvers/webpack/test/.eslintrc
@@ -1,5 +1,6 @@
 ---
 env:
   mocha: true
+  es6: true
 rules:
   quotes: 0
diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index c6a0a94fb8..20ecac5723 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -145,4 +145,14 @@ describe("config", function () {
 
     expect(function () { resolve('baz', file, settings); }).to.not.throw(Error);
   });
+
+  it('prevents async config using', function() {
+    const settings = {
+      config: require(path.join(__dirname, './files/webpack.config.async.js')),
+    };
+    const result = resolve('foo', file, settings);
+
+    expect(result).not.to.have.property('path');
+    expect(result).to.have.property('found').to.be.false;
+  });
 });
diff --git a/resolvers/webpack/test/files/webpack.config.async.js b/resolvers/webpack/test/files/webpack.config.async.js
new file mode 100644
index 0000000000..9b7aaa7f4d
--- /dev/null
+++ b/resolvers/webpack/test/files/webpack.config.async.js
@@ -0,0 +1,7 @@
+const config = require('./webpack.config.js')
+
+module.exports = function() {
+  return new Promise(function(resolve) {
+    resolve(config)
+  })
+}

From fd4b16b6a9bc405ba1195be5c841c1a6a63bd59f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 26 Jan 2021 12:08:19 -0800
Subject: [PATCH 242/767] [meta] enable `quotes` rule everywhere

---
 .eslintrc                                     |   9 ++
 resolvers/node/test/.eslintrc                 |   9 --
 resolvers/node/test/native.js                 |   2 +-
 resolvers/node/test/paths.js                  |  26 +--
 resolvers/webpack/test/.eslintrc              |   6 -
 resolvers/webpack/test/alias.js               | 152 +++++++++---------
 resolvers/webpack/test/config.js              |  22 +--
 resolvers/webpack/test/example.js             |   4 +-
 resolvers/webpack/test/extensions.js          |  12 +-
 resolvers/webpack/test/externals.js           |  10 +-
 resolvers/webpack/test/fallback.js            |  12 +-
 resolvers/webpack/test/loaders.js             |  13 +-
 resolvers/webpack/test/modules.js             |   6 +-
 .../test/package-mains/webpack.alt.config.js  |   2 +-
 resolvers/webpack/test/packageMains.js        |  16 +-
 resolvers/webpack/test/plugins.js             |   8 +-
 resolvers/webpack/test/root.js                |  26 +--
 17 files changed, 163 insertions(+), 172 deletions(-)
 delete mode 100644 resolvers/node/test/.eslintrc
 delete mode 100644 resolvers/webpack/test/.eslintrc

diff --git a/.eslintrc b/.eslintrc
index 9e42281a21..356666af5d 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -72,5 +72,14 @@
                 "no-console": "off",
             },
         },
+        {
+            "files": [
+                "resolvers/*/test/**/*",
+            ],
+            "env": {
+                "mocha": true,
+                "es6": false
+            },
+        }
     ],
 }
diff --git a/resolvers/node/test/.eslintrc b/resolvers/node/test/.eslintrc
deleted file mode 100644
index fc14dae59e..0000000000
--- a/resolvers/node/test/.eslintrc
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "env": {
-    "mocha": true,
-    "es6": false
-  },
-  "rules": {
-    "quotes": 0,
-  },
-}
diff --git a/resolvers/node/test/native.js b/resolvers/node/test/native.js
index 4e8441ff0a..134f23bbce 100644
--- a/resolvers/node/test/native.js
+++ b/resolvers/node/test/native.js
@@ -1 +1 @@
-exports.natively = function () { return "but where do we feature?"; };
+exports.natively = function () { return 'but where do we feature?'; };
diff --git a/resolvers/node/test/paths.js b/resolvers/node/test/paths.js
index 81d8fb8448..1c42b46167 100644
--- a/resolvers/node/test/paths.js
+++ b/resolvers/node/test/paths.js
@@ -3,8 +3,8 @@ const expect = require('chai').expect;
 const path = require('path');
 const node = require('../index.js');
 
-describe("paths", function () {
-  it("handles base path relative to CWD", function () {
+describe('paths', function () {
+  it('handles base path relative to CWD', function () {
     expect(node.resolve('../', './test/file.js'))
       .to.have.property('path')
       .equal(path.resolve(__dirname, '../index.js'));
@@ -12,18 +12,18 @@ describe("paths", function () {
 });
 
 
-describe("core", function () {
-  it("returns found, but null path, for core Node modules", function () {
-    const resolved = node.resolve('fs', "./test/file.js");
-    expect(resolved).has.property("found", true);
-    expect(resolved).has.property("path", null);
+describe('core', function () {
+  it('returns found, but null path, for core Node modules', function () {
+    const resolved = node.resolve('fs', './test/file.js');
+    expect(resolved).has.property('found', true);
+    expect(resolved).has.property('path', null);
   });
 });
 
 
-describe("default options", function () {
+describe('default options', function () {
 
-  it("finds .json files", function () {
+  it('finds .json files', function () {
     expect(node.resolve('./data', './test/file.js'))
       .to.have.property('path')
       .equal(path.resolve(__dirname, './data.json'));
@@ -34,25 +34,25 @@ describe("default options", function () {
       .to.have.property('found', false);
   });
 
-  it("finds mjs modules, with precedence over .js", function () {
+  it('finds mjs modules, with precedence over .js', function () {
     expect(node.resolve('./native', './test/file.js'))
       .to.have.property('path')
       .equal(path.resolve(__dirname, './native.mjs'));
   });
 
-  it("finds .node modules, with lowest precedence", function () {
+  it('finds .node modules, with lowest precedence', function () {
     expect(node.resolve('./native.node', './test/file.js'))
       .to.have.property('path')
       .equal(path.resolve(__dirname, './native.node'));
   });
 
-  it("finds .node modules", function () {
+  it('finds .node modules', function () {
     expect(node.resolve('./dot-node', './test/file.js'))
       .to.have.property('path')
       .equal(path.resolve(__dirname, './dot-node.node'));
   });
 
-  it("still finds .js if explicit", function () {
+  it('still finds .js if explicit', function () {
     expect(node.resolve('./native.js', './test/file.js'))
       .to.have.property('path')
       .equal(path.resolve(__dirname, './native.js'));
diff --git a/resolvers/webpack/test/.eslintrc b/resolvers/webpack/test/.eslintrc
deleted file mode 100644
index a9cee4100d..0000000000
--- a/resolvers/webpack/test/.eslintrc
+++ /dev/null
@@ -1,6 +0,0 @@
----
-env:
-  mocha: true
-  es6: true
-rules:
-  quotes: 0
diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js
index e48c074055..06aad44699 100644
--- a/resolvers/webpack/test/alias.js
+++ b/resolvers/webpack/test/alias.js
@@ -8,132 +8,132 @@ const webpack = require('../index');
 
 const file = path.join(__dirname, 'files', 'dummy.js');
 
-describe("resolve.alias", function () {
+describe('resolve.alias', function () {
   let resolved;
   before(function () { resolved = webpack.resolve('foo', file); });
 
-  it("is found", function () { expect(resolved).to.have.property('found', true); });
+  it('is found', function () { expect(resolved).to.have.property('found', true); });
 
-  it("is correct", function () {
+  it('is correct', function () {
     expect(resolved).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
   });
 });
 
 // todo: reimplement with resolver function / config
-// describe.skip("webpack alias spec", function () {
+// describe.skip('webpack alias spec', function () {
 //   // from table: http://webpack.github.io/docs/configuration.html#resolve-alias
 //   function tableLine(alias, xyz, xyzFile) {
 //     describe(JSON.stringify(alias), function () {
-//       it("xyz: " + xyz, function () {
-//         expect(resolveAlias('xyz', alias)).to.equal(xyz)
-//       })
-//       it("xyz/file: " + (xyzFile.name || xyzFile), function () {
+//       it('xyz: ' + xyz, function () {
+//         expect(resolveAlias('xyz', alias)).to.equal(xyz);
+//       });
+//       it('xyz/file: ' + (xyzFile.name || xyzFile), function () {
 //         if (xyzFile === Error) {
-//           expect(resolveAlias.bind(null, 'xyz/file', alias)).to.throw(xyzFile)
+//           expect(resolveAlias.bind(null, 'xyz/file', alias)).to.throw(xyzFile);
 //         } else {
-//           expect(resolveAlias('xyz/file', alias)).to.equal(xyzFile)
+//           expect(resolveAlias('xyz/file', alias)).to.equal(xyzFile);
 //         }
-//       })
-//     })
+//       });
+//     });
 //   }
 
 //   tableLine( {}
-//            , 'xyz', 'xyz/file' )
+//     , 'xyz', 'xyz/file' );
 
-//   tableLine( { xyz: "/absolute/path/to/file.js" }
-//            , '/absolute/path/to/file.js', 'xyz/file' )
+//   tableLine( { xyz: '/absolute/path/to/file.js' }
+//     , '/absolute/path/to/file.js', 'xyz/file' );
 
-//   tableLine( { xyz$: "/absolute/path/to/file.js" }
-//            ,  "/absolute/path/to/file.js", Error )
+//   tableLine( { xyz$: '/absolute/path/to/file.js' }
+//     ,  '/absolute/path/to/file.js', Error );
 
-//   tableLine( { xyz: "./dir/file.js" }
-//            , './dir/file.js',  'xyz/file' )
+//   tableLine( { xyz: './dir/file.js' }
+//     , './dir/file.js',  'xyz/file' );
 
-//   tableLine( { xyz$: "./dir/file.js" }
-//            , './dir/file.js', Error )
+//   tableLine( { xyz$: './dir/file.js' }
+//     , './dir/file.js', Error );
 
-//   tableLine( { xyz: "/some/dir" }
-//            , '/some/dir', '/some/dir/file' )
+//   tableLine( { xyz: '/some/dir' }
+//     , '/some/dir', '/some/dir/file' );
 
-//   tableLine( { xyz$: "/some/dir" }
-//            , '/some/dir', 'xyz/file' )
+//   tableLine( { xyz$: '/some/dir' }
+//     , '/some/dir', 'xyz/file' );
 
-//   tableLine( { xyz: "./dir" }
-//            , './dir', './dir/file' )
+//   tableLine( { xyz: './dir' }
+//     , './dir', './dir/file' );
 
-//   tableLine( { xyz: "modu" }
-//            , 'modu', 'modu/file' )
+//   tableLine( { xyz: 'modu' }
+//     , 'modu', 'modu/file' );
 
-//   tableLine( { xyz$: "modu" }
-//            , 'modu', 'xyz/file' )
+//   tableLine( { xyz$: 'modu' }
+//     , 'modu', 'xyz/file' );
 
-//   tableLine( { xyz: "modu/some/file.js" }
-//            , 'modu/some/file.js', Error )
+//   tableLine( { xyz: 'modu/some/file.js' }
+//     , 'modu/some/file.js', Error );
 
-//   tableLine( { xyz: "modu/dir" }
-//            , 'modu/dir', 'modu/dir/file' )
+//   tableLine( { xyz: 'modu/dir' }
+//     , 'modu/dir', 'modu/dir/file' );
 
-//   tableLine( { xyz: "xyz/dir" }
-//            , 'xyz/dir',  'xyz/dir/file' )
+//   tableLine( { xyz: 'xyz/dir' }
+//     , 'xyz/dir',  'xyz/dir/file' );
 
-//   tableLine( { xyz$: "xyz/dir" }
-//            , 'xyz/dir', 'xyz/file' )
-// })
+//   tableLine( { xyz$: 'xyz/dir' }
+//     , 'xyz/dir', 'xyz/file' );
+// });
 
-// describe.skip("nested module names", function () {
+// describe.skip('nested module names', function () {
 //   // from table: http://webpack.github.io/docs/configuration.html#resolve-alias
 //   function nestedName(alias, xyz, xyzFile) {
 //     describe(JSON.stringify(alias), function () {
-//       it("top/xyz: " + xyz, function () {
-//         expect(resolveAlias('top/xyz', alias)).to.equal(xyz)
-//       })
-//       it("top/xyz/file: " + (xyzFile.name || xyzFile), function () {
+//       it('top/xyz: ' + xyz, function () {
+//         expect(resolveAlias('top/xyz', alias)).to.equal(xyz);
+//       });
+//       it('top/xyz/file: ' + (xyzFile.name || xyzFile), function () {
 //         if (xyzFile === Error) {
-//           expect(resolveAlias.bind(null, 'top/xyz/file', alias)).to.throw(xyzFile)
+//           expect(resolveAlias.bind(null, 'top/xyz/file', alias)).to.throw(xyzFile);
 //         } else {
-//           expect(resolveAlias('top/xyz/file', alias)).to.equal(xyzFile)
+//           expect(resolveAlias('top/xyz/file', alias)).to.equal(xyzFile);
 //         }
-//       })
-//     })
+//       });
+//     });
 //   }
 
-//   nestedName( { 'top/xyz': "/absolute/path/to/file.js" }
-//       , '/absolute/path/to/file.js', 'top/xyz/file' )
+//   nestedName( { 'top/xyz': '/absolute/path/to/file.js' }
+//     , '/absolute/path/to/file.js', 'top/xyz/file' );
 
-//   nestedName( { 'top/xyz$': "/absolute/path/to/file.js" }
-//       ,  "/absolute/path/to/file.js", Error )
+//   nestedName( { 'top/xyz$': '/absolute/path/to/file.js' }
+//     ,  '/absolute/path/to/file.js', Error );
 
-//   nestedName( { 'top/xyz': "./dir/file.js" }
-//       , './dir/file.js',  'top/xyz/file' )
+//   nestedName( { 'top/xyz': './dir/file.js' }
+//     , './dir/file.js',  'top/xyz/file' );
 
-//   nestedName( { 'top/xyz$': "./dir/file.js" }
-//       , './dir/file.js', Error )
+//   nestedName( { 'top/xyz$': './dir/file.js' }
+//     , './dir/file.js', Error );
 
-//   nestedName( { 'top/xyz': "/some/dir" }
-//       , '/some/dir', '/some/dir/file' )
+//   nestedName( { 'top/xyz': '/some/dir' }
+//     , '/some/dir', '/some/dir/file' );
 
-//   nestedName( { 'top/xyz$': "/some/dir" }
-//       , '/some/dir', 'top/xyz/file' )
+//   nestedName( { 'top/xyz$': '/some/dir' }
+//     , '/some/dir', 'top/xyz/file' );
 
-//   nestedName( { 'top/xyz': "./dir" }
-//       , './dir', './dir/file' )
+//   nestedName( { 'top/xyz': './dir' }
+//     , './dir', './dir/file' );
 
-//   nestedName( { 'top/xyz': "modu" }
-//       , 'modu', 'modu/file' )
+//   nestedName( { 'top/xyz': 'modu' }
+//     , 'modu', 'modu/file' );
 
-//   nestedName( { 'top/xyz$': "modu" }
-//       , 'modu', 'top/xyz/file' )
+//   nestedName( { 'top/xyz$': 'modu' }
+//     , 'modu', 'top/xyz/file' );
 
-//   nestedName( { 'top/xyz': "modu/some/file.js" }
-//       , 'modu/some/file.js', Error )
+//   nestedName( { 'top/xyz': 'modu/some/file.js' }
+//     , 'modu/some/file.js', Error );
 
-//   nestedName( { 'top/xyz': "modu/dir" }
-//       , 'modu/dir', 'modu/dir/file' )
+//   nestedName( { 'top/xyz': 'modu/dir' }
+//     , 'modu/dir', 'modu/dir/file' );
 
-//   nestedName( { 'top/xyz': "top/xyz/dir" }
-//       , 'top/xyz/dir',  'top/xyz/dir/file' )
+//   nestedName( { 'top/xyz': 'top/xyz/dir' }
+//     , 'top/xyz/dir',  'top/xyz/dir/file' );
 
-//   nestedName( { 'top/xyz$': "top/xyz/dir" }
-//       , 'top/xyz/dir', 'top/xyz/file' )
-// })
+//   nestedName( { 'top/xyz$': 'top/xyz/dir' }
+//     , 'top/xyz/dir', 'top/xyz/file' );
+// });
diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index 20ecac5723..069c2e3942 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -13,18 +13,18 @@ const absoluteSettings = {
   config: path.join(__dirname, 'files', 'some', 'absolute.path.webpack.config.js'),
 };
 
-describe("config", function () {
-  it("finds webpack.config.js in parent directories", function () {
+describe('config', function () {
+  it('finds webpack.config.js in parent directories', function () {
     expect(resolve('main-module', file)).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
-  it("finds absolute webpack.config.js files", function () {
+  it('finds absolute webpack.config.js files', function () {
     expect(resolve('foo', file, absoluteSettings)).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
   });
 
-  it("finds compile-to-js configs", function () {
+  it('finds compile-to-js configs', function () {
     const settings = {
       config: path.join(__dirname, './files/webpack.config.babel.js'),
     };
@@ -34,13 +34,13 @@ describe("config", function () {
       .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
-  it("finds compile-to-js config in parent directories", function () {
+  it('finds compile-to-js config in parent directories', function () {
     expect(resolve('main-module', extensionFile))
       .to.have.property('path')
       .and.equal(path.join(__dirname, 'config-extensions', 'src', 'main-module.js'));
   });
 
-  it("finds the first config with a resolve section", function () {
+  it('finds the first config with a resolve section', function () {
     const settings = {
       config: path.join(__dirname, './files/webpack.config.multiple.js'),
     };
@@ -49,7 +49,7 @@ describe("config", function () {
       .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
-  it("finds the config at option config-index", function () {
+  it('finds the config at option config-index', function () {
     const settings = {
       config: path.join(__dirname, './files/webpack.config.multiple.js'),
       'config-index': 2,
@@ -66,7 +66,7 @@ describe("config", function () {
     expect(function () { resolve('foo', file, settings); }).to.throw(Error);
   });
 
-  it("finds config object when config is an object", function () {
+  it('finds config object when config is an object', function () {
     const settings = {
       config: require(path.join(__dirname, 'files', 'some', 'absolute.path.webpack.config.js')),
     };
@@ -74,7 +74,7 @@ describe("config", function () {
       .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
   });
 
-  it("finds config object when config uses a path relative to working dir", function () {
+  it('finds config object when config uses a path relative to working dir', function () {
     const settings = {
       config: './test/files/some/absolute.path.webpack.config.js',
     };
@@ -82,7 +82,7 @@ describe("config", function () {
       .and.equal(path.join(__dirname, 'files', 'some', 'absolutely', 'goofy', 'path', 'foo.js'));
   });
 
-  it("finds the first config with a resolve section when config is an array of config objects", function () {
+  it('finds the first config with a resolve section when config is an array of config objects', function () {
     const settings = {
       config: require(path.join(__dirname, './files/webpack.config.multiple.js')),
     };
@@ -91,7 +91,7 @@ describe("config", function () {
       .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
-  it("finds the config at option config-index when config is an array of config objects", function () {
+  it('finds the config at option config-index when config is an array of config objects', function () {
     const settings = {
       config: require(path.join(__dirname, './files/webpack.config.multiple.js')),
       'config-index': 2,
diff --git a/resolvers/webpack/test/example.js b/resolvers/webpack/test/example.js
index c7ae933f18..cd9ece0156 100644
--- a/resolvers/webpack/test/example.js
+++ b/resolvers/webpack/test/example.js
@@ -6,6 +6,6 @@ const resolve = require('../index').resolve;
 
 const file = path.join(__dirname, 'files', 'src', 'dummy.js');
 
-const webpackDir = path.join(__dirname, "different-package-location");
+const webpackDir = path.join(__dirname, 'different-package-location');
 
-console.log(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir }));
+console.log(resolve('main-module', file, { config: 'webpack.config.js', cwd: webpackDir }));
diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js
index 398feb2c83..c028f5c913 100644
--- a/resolvers/webpack/test/extensions.js
+++ b/resolvers/webpack/test/extensions.js
@@ -10,23 +10,23 @@ const resolve = require('../index').resolve;
 const file = path.join(__dirname, 'files', 'dummy.js');
 const extensions = path.join(__dirname, 'custom-extensions', 'dummy.js');
 
-describe("extensions", function () {
-  it("respects the defaults", function () {
+describe('extensions', function () {
+  it('respects the defaults', function () {
     expect(resolve('./foo', file)).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'foo.web.js'));
   });
 
-  describe("resolve.extensions set", function () {
-    it("works", function () {
+  describe('resolve.extensions set', function () {
+    it('works', function () {
       expect(resolve('./foo', extensions)).to.have.property('path')
         .and.equal(path.join(__dirname, 'custom-extensions', 'foo.js'));
     });
 
-    it("replaces defaults", function () {
+    it('replaces defaults', function () {
       expect(resolve('./baz', extensions)).to.have.property('found', false);
     });
 
-    it("finds .coffee", function () {
+    it('finds .coffee', function () {
       expect(resolve('./bar', extensions)).to.have.property('path')
         .and.equal(path.join(__dirname, 'custom-extensions', 'bar.coffee'));
     });
diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js
index ed407a7f79..9cad635241 100644
--- a/resolvers/webpack/test/externals.js
+++ b/resolvers/webpack/test/externals.js
@@ -8,26 +8,26 @@ const webpack = require('../index');
 
 const file = path.join(__dirname, 'files', 'dummy.js');
 
-describe("externals", function () {
-  it("works on just a string", function () {
+describe('externals', function () {
+  it('works on just a string', function () {
     const resolved = webpack.resolve('bootstrap', file);
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
   });
 
-  it("works on object-map", function () {
+  it('works on object-map', function () {
     const resolved = webpack.resolve('jquery', file);
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
   });
 
-  it("works on a function", function () {
+  it('works on a function', function () {
     const resolved = webpack.resolve('underscore', file);
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
   });
 
-  it("returns null for core modules", function () {
+  it('returns null for core modules', function () {
     const resolved = webpack.resolve('fs', file);
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
diff --git a/resolvers/webpack/test/fallback.js b/resolvers/webpack/test/fallback.js
index 31cbffd3ab..87c15eecd7 100644
--- a/resolvers/webpack/test/fallback.js
+++ b/resolvers/webpack/test/fallback.js
@@ -9,21 +9,21 @@ const resolve = require('../index').resolve;
 
 const file = path.join(__dirname, 'files', 'src', 'dummy.js');
 
-describe("fallback", function () {
-  it("works", function () {
+describe('fallback', function () {
+  it('works', function () {
     expect(resolve('fb-module', file)).property('path')
       .to.equal(path.join(__dirname, 'files', 'fallback', 'fb-module.js'));
   });
-  it("really works", function () {
+  it('really works', function () {
     expect(resolve('jsx/some-fb-file', file)).property('path')
       .to.equal(path.join(__dirname, 'files', 'fallback', 'jsx', 'some-fb-file.js'));
   });
-  it("prefer root", function () {
+  it('prefer root', function () {
     expect(resolve('jsx/some-file', file)).property('path')
       .to.equal(path.join(__dirname, 'files', 'src', 'jsx', 'some-file.js'));
   });
-  it("supports definition as an array", function () {
-    expect(resolve('fb-module', file, { config: "webpack.array-root.config.js" }))
+  it('supports definition as an array', function () {
+    expect(resolve('fb-module', file, { config: 'webpack.array-root.config.js' }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'fallback', 'fb-module.js'));
   });
diff --git a/resolvers/webpack/test/loaders.js b/resolvers/webpack/test/loaders.js
index ccf62f99c5..6b5604592d 100644
--- a/resolvers/webpack/test/loaders.js
+++ b/resolvers/webpack/test/loaders.js
@@ -9,29 +9,26 @@ const resolve = require('../index').resolve;
 
 const file = path.join(__dirname, 'files', 'dummy.js');
 
-describe("inline loader syntax", function () {
-
-  it("strips bang-loaders", function () {
+describe('inline loader syntax', function () {
+  it('strips bang-loaders', function () {
     expect(resolve('css-loader!./src/main-module', file)).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
-  it("strips loader query string", function () {
+  it('strips loader query string', function () {
     expect(resolve('some-loader?param=value!./src/main-module', file)).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
-  it("strips resource query string", function () {
+  it('strips resource query string', function () {
     expect(resolve('./src/main-module?otherParam=otherValue', file))
       .to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
 
-  it("strips everything", function () {
+  it('strips everything', function () {
     expect(resolve('some-loader?param=value!./src/main-module?otherParam=otherValue', file))
       .to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
-
 });
-
diff --git a/resolvers/webpack/test/modules.js b/resolvers/webpack/test/modules.js
index 9242865407..066e52a6f7 100644
--- a/resolvers/webpack/test/modules.js
+++ b/resolvers/webpack/test/modules.js
@@ -8,14 +8,14 @@ const resolve = require('../index').resolve;
 
 const file = path.join(__dirname, 'files', 'dummy.js');
 
-describe("resolve.moduleDirectories", function () {
+describe('resolve.moduleDirectories', function () {
 
-  it("finds a node module", function () {
+  it('finds a node module', function () {
     expect(resolve('some-module', file)).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'node_modules', 'some-module', 'index.js'));
   });
 
-  it("finds a bower module", function () {
+  it('finds a bower module', function () {
     expect(resolve('typeahead.js', file)).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
   });
diff --git a/resolvers/webpack/test/package-mains/webpack.alt.config.js b/resolvers/webpack/test/package-mains/webpack.alt.config.js
index 2bb1fc6717..b955d9d378 100644
--- a/resolvers/webpack/test/package-mains/webpack.alt.config.js
+++ b/resolvers/webpack/test/package-mains/webpack.alt.config.js
@@ -1,3 +1,3 @@
 exports.resolve = {
-  packageMains: ["main"], // override
+  packageMains: ['main'], // override
 };
diff --git a/resolvers/webpack/test/packageMains.js b/resolvers/webpack/test/packageMains.js
index dc30e3335a..ed9c79a398 100644
--- a/resolvers/webpack/test/packageMains.js
+++ b/resolvers/webpack/test/packageMains.js
@@ -9,39 +9,39 @@ const webpack = require('../');
 const file = path.join(__dirname, 'package-mains', 'dummy.js');
 
 
-describe("packageMains", function () {
+describe('packageMains', function () {
 
-  it("captures module", function () {
+  it('captures module', function () {
     expect(webpack.resolve('./module', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'));
   });
 
-  it("captures jsnext", function () {
+  it('captures jsnext', function () {
     expect(webpack.resolve('./jsnext', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
   });
 
-  it("captures webpack", function () {
+  it('captures webpack', function () {
     expect(webpack.resolve('./webpack', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'webpack.js'));
   });
 
-  it("captures jam (array path)", function () {
+  it('captures jam (array path)', function () {
     expect(webpack.resolve('./jam', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'jam', 'jam.js'));
   });
 
-  it("uses configured packageMains, if provided", function () {
+  it('uses configured packageMains, if provided', function () {
     expect(webpack.resolve('./webpack', file, { config: 'webpack.alt.config.js' })).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'index.js'));
   });
 
-  it("always defers to module, regardless of config", function () {
+  it('always defers to module, regardless of config', function () {
     expect(webpack.resolve('./module', file, { config: 'webpack.alt.config.js' })).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'));
   });
 
-  it("always defers to jsnext:main, regardless of config", function () {
+  it('always defers to jsnext:main, regardless of config', function () {
     expect(webpack.resolve('./jsnext', file, { config: 'webpack.alt.config.js' })).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
   });
diff --git a/resolvers/webpack/test/plugins.js b/resolvers/webpack/test/plugins.js
index d061d8df16..b964e7c30e 100644
--- a/resolvers/webpack/test/plugins.js
+++ b/resolvers/webpack/test/plugins.js
@@ -8,7 +8,7 @@ const webpack = require('../index');
 
 const file = path.join(__dirname, 'files', 'dummy.js');
 
-describe("plugins", function () {
+describe('plugins', function () {
   let resolved; let aliasResolved;
 
   before(function () {
@@ -16,16 +16,16 @@ describe("plugins", function () {
     aliasResolved = webpack.resolve('some-alias/bar', file);
   });
 
-  it("work", function () {
+  it('work', function () {
     expect(resolved).to.have.property('found', true);
   });
 
-  it("is correct", function () {
+  it('is correct', function () {
     expect(resolved).to.have.property('path')
       .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'));
   });
 
-  it("work with alias", function () {
+  it('work with alias', function () {
     expect(aliasResolved).to.have.property('found', true);
   });
 });
diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js
index 9fa34c24b3..154dbeef95 100644
--- a/resolvers/webpack/test/root.js
+++ b/resolvers/webpack/test/root.js
@@ -8,39 +8,39 @@ const resolve = require('../index').resolve;
 
 
 const file = path.join(__dirname, 'files', 'src', 'dummy.js');
-const webpackDir = path.join(__dirname, "different-package-location");
+const webpackDir = path.join(__dirname, 'different-package-location');
 
-describe("root", function () {
-  it("works", function () {
+describe('root', function () {
+  it('works', function () {
     expect(resolve('main-module', file)).property('path')
       .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
   });
-  it("really works", function () {
+  it('really works', function () {
     expect(resolve('jsx/some-file', file)).property('path')
       .to.equal(path.join(__dirname, 'files', 'src', 'jsx', 'some-file.js'));
   });
-  it("supports definition as an array", function () {
-    expect(resolve('main-module', file, { config: "webpack.array-root.config.js" }))
+  it('supports definition as an array', function () {
+    expect(resolve('main-module', file, { config: 'webpack.array-root.config.js' }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
-    expect(resolve('typeahead', file, { config: "webpack.array-root.config.js" }))
+    expect(resolve('typeahead', file, { config: 'webpack.array-root.config.js' }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
   });
-  it("supports definition as a function", function () {
-    expect(resolve('main-module', file, { config: "webpack.function.config.js" }))
+  it('supports definition as a function', function () {
+    expect(resolve('main-module', file, { config: 'webpack.function.config.js' }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
-    expect(resolve('typeahead', file, { config: "webpack.function.config.js" }))
+    expect(resolve('typeahead', file, { config: 'webpack.function.config.js' }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
   });
-  it("supports passing a different directory to load webpack from", function () {
+  it('supports passing a different directory to load webpack from', function () {
     // Webpack should still be able to resolve the config here
-    expect(resolve('main-module', file, { config: "webpack.config.js", cwd: webpackDir }))
+    expect(resolve('main-module', file, { config: 'webpack.config.js', cwd: webpackDir }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'src', 'main-module.js'));
-    expect(resolve('typeahead', file, { config: "webpack.config.js", cwd: webpackDir }))
+    expect(resolve('typeahead', file, { config: 'webpack.config.js', cwd: webpackDir }))
       .property('path')
       .to.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js'));
   });

From 1c6a7caf3c0d75b94ce79afd92165a42cce913ee Mon Sep 17 00:00:00 2001
From: Guillaume Clochard <guillaume.clochard@iadvize.com>
Date: Fri, 17 Jul 2020 17:58:39 +0200
Subject: [PATCH 243/767] [New] `no-internal-modules`: Add `forbid` option

Fixes #1842
---
 CHANGELOG.md                           |   5 +-
 docs/rules/no-internal-modules.md      |  66 ++++++++++-
 src/rules/no-internal-modules.js       |  78 ++++++++++---
 tests/src/rules/no-internal-modules.js | 148 +++++++++++++++++++++++++
 4 files changed, 278 insertions(+), 19 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 347034bbc6..ae9c0dfd0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Added
 - [`no-commonjs`]: Also detect require calls with expressionless template literals: ``` require(`x`) ``` ([#1958], thanks [@FloEdelmann])
+- [`no-internal-modules`]: Add `forbid` option ([#1846], thanks [@guillaumewuip])
 
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
@@ -765,6 +766,7 @@ for info on changes for earlier releases.
 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
 [#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
 [#1848]: https://github.com/benmosher/eslint-plugin-import/pull/1848
+[#1846]: https://github.com/benmosher/eslint-plugin-import/pull/1846
 [#1841]: https://github.com/benmosher/eslint-plugin-import/issues/1841
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
 [#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
@@ -1321,4 +1323,5 @@ for info on changes for earlier releases.
 [@MatthiasKunnen]: https://github.com/MatthiasKunnen
 [@paztis]: https://github.com/paztis
 [@FloEdelmann]: https://github.com/FloEdelmann
-[@bicstone]: https://github.com/bicstone
\ No newline at end of file
+[@bicstone]: https://github.com/bicstone
+[@guillaumewuip]: https://github.com/guillaumewuip
\ No newline at end of file
diff --git a/docs/rules/no-internal-modules.md b/docs/rules/no-internal-modules.md
index 7bbb2edd16..d957e26f36 100644
--- a/docs/rules/no-internal-modules.md
+++ b/docs/rules/no-internal-modules.md
@@ -4,7 +4,10 @@ Use this rule to prevent importing the submodules of other modules.
 
 ## Rule Details
 
-This rule has one option, `allow` which is an array of [minimatch/glob patterns](https://github.com/isaacs/node-glob#glob-primer) patterns that whitelist paths and import statements that can be imported with reaching.
+This rule has two mutally exclusive options that are arrays of [minimatch/glob patterns](https://github.com/isaacs/node-glob#glob-primer) patterns:
+
+- `allow` that include paths and import statements that can be imported with reaching.
+- `forbid` that exclude paths and import statements that can be imported with reaching.
 
 ### Examples
 
@@ -33,7 +36,7 @@ And the .eslintrc file:
   ...
   "rules": {
     "import/no-internal-modules": [ "error", {
-      "allow": [ "**/actions/*", "source-map-support/*" ]
+      "allow": [ "**/actions/*", "source-map-support/*" ],
     } ]
   }
 }
@@ -68,3 +71,62 @@ import getUser from '../actions/getUser';
 export * from 'source-map-support/register';
 export { settings } from '../app';
 ```
+
+Given the following folder structure:
+
+```
+my-project
+├── actions
+│   └── getUser.js
+│   └── updateUser.js
+├── reducer
+│   └── index.js
+│   └── user.js
+├── redux
+│   └── index.js
+│   └── configureStore.js
+└── app
+│   └── index.js
+│   └── settings.js
+└── entry.js
+```
+
+And the .eslintrc file:
+```
+{
+  ...
+  "rules": {
+    "import/no-internal-modules": [ "error", {
+      "forbid": [ "**/actions/*", "source-map-support/*" ],
+    } ]
+  }
+}
+```
+
+The following patterns are considered problems:
+
+```js
+/**
+ *  in my-project/entry.js
+ */
+
+import 'source-map-support/register';
+import getUser from '../actions/getUser';
+
+export * from 'source-map-support/register';
+export getUser from '../actions/getUser';
+```
+
+The following patterns are NOT considered problems:
+
+```js
+/**
+ *  in my-project/entry.js
+ */
+
+import 'source-map-support';
+import { getUser } from '../actions';
+
+export * from 'source-map-support';
+export { getUser } from '../actions';
+```
diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index d23bb36dd4..a33f23b475 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -14,16 +14,32 @@ module.exports = {
 
     schema: [
       {
-        type: 'object',
-        properties: {
-          allow: {
-            type: 'array',
-            items: {
-              type: 'string',
+        oneOf: [
+          {
+            type: 'object',
+            properties: {
+              allow: {
+                type: 'array',
+                items: {
+                  type: 'string',
+                },
+              },
             },
+            additionalProperties: false,
           },
-        },
-        additionalProperties: false,
+          {
+            type: 'object',
+            properties: {
+              forbid: {
+                type: 'array',
+                items: {
+                  type: 'string',
+                },
+              },
+            },
+            additionalProperties: false,
+          },
+        ],
       },
     ],
   },
@@ -31,11 +47,7 @@ module.exports = {
   create: function noReachingInside(context) {
     const options = context.options[0] || {};
     const allowRegexps = (options.allow || []).map(p => minimatch.makeRe(p));
-
-    // test if reaching to this destination is allowed
-    function reachingAllowed(importPath) {
-      return allowRegexps.some(re => re.test(importPath));
-    }
+    const forbidRegexps = (options.forbid || []).map(p => minimatch.makeRe(p));
 
     // minimatch patterns are expected to use / path separators, like import
     // statements, so normalize paths to use the same
@@ -43,9 +55,8 @@ module.exports = {
       return somePath.split('\\').join('/');
     }
 
-    // find a directory that is being reached into, but which shouldn't be
-    function isReachViolation(importPath) {
-      const steps = normalizeSep(importPath)
+    function toSteps(somePath) {
+      return  normalizeSep(somePath)
         .split('/')
         .reduce((acc, step) => {
           if (!step || step === '.') {
@@ -56,6 +67,20 @@ module.exports = {
             return acc.concat(step);
           }
         }, []);
+    }
+
+    // test if reaching to this destination is allowed
+    function reachingAllowed(importPath) {
+      return allowRegexps.some(re => re.test(importPath));
+    }
+
+    // test if reaching to this destination is forbidden
+    function reachingForbidden(importPath) {
+      return forbidRegexps.some(re => re.test(importPath));
+    }
+
+    function isAllowViolation(importPath) {
+      const steps = toSteps(importPath);
 
       const nonScopeSteps = steps.filter(step => step.indexOf('@') !== 0);
       if (nonScopeSteps.length <= 1) return false;
@@ -75,6 +100,27 @@ module.exports = {
       return true;
     }
 
+    function isForbidViolation(importPath) {
+      const steps = toSteps(importPath);
+
+      // before trying to resolve, see if the raw import (with relative
+      // segments resolved) matches a forbidden pattern
+      const justSteps = steps.join('/');
+
+      if (reachingForbidden(justSteps) || reachingForbidden(`/${justSteps}`)) return true;
+
+      // if the import statement doesn't match directly, try to match the
+      // resolved path if the import is resolvable
+      const resolved = resolve(importPath, context);
+      if (resolved && reachingForbidden(normalizeSep(resolved))) return true;
+
+      // this import was not forbidden by the forbidden paths so it is not a violation
+      return false;
+    }
+
+    // find a directory that is being reached into, but which shouldn't be
+    const isReachViolation = options.forbid ? isForbidViolation : isAllowViolation;
+
     function checkImportForReaching(importPath, node) {
       const potentialViolationTypes = ['parent', 'index', 'sibling', 'external', 'internal'];
       if (potentialViolationTypes.indexOf(importType(importPath, context)) !== -1 &&
diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js
index 1723f7df69..2bad32c460 100644
--- a/tests/src/rules/no-internal-modules.js
+++ b/tests/src/rules/no-internal-modules.js
@@ -59,6 +59,34 @@ ruleTester.run('no-internal-modules', rule, {
         allow: [ '**/index{.js,}' ],
       } ],
     }),
+    test({
+      code: 'import a from "./plugin2/thing"',
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      options: [ {
+        forbid: [ '**/api/*' ],
+      } ],
+    }),
+    test({
+      code: 'const a = require("./plugin2/thing")',
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      options: [ {
+        forbid: [ '**/api/*' ],
+      } ],
+    }),
+    test({
+      code: 'import b from "app/a"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ 'app/**/**' ],
+      } ],
+    }),
+    test({
+      code: 'import b from "@org/package"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ '@org/package/*' ],
+      } ],
+    }),
     // exports
     test({
       code: 'export {a} from "./internal.js"',
@@ -114,6 +142,34 @@ ruleTester.run('no-internal-modules', rule, {
         parser: parser,
       }),
     ]),
+    test({
+      code: 'export * from "./plugin2/thing"',
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      options: [ {
+        forbid: [ '**/api/*' ],
+      } ],
+    }),
+    test({
+      code: 'export * from "app/a"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ 'app/**/**' ],
+      } ],
+    }),
+    test({
+      code: 'export { b } from "@org/package"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ '@org/package/*' ],
+      } ],
+    }),
+    test({
+      code: 'export * from "./app/index.js";\nexport * from "./app/index"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ '**/index.ts' ],
+      } ],
+    }),
   ],
 
   invalid: [
@@ -184,6 +240,70 @@ ruleTester.run('no-internal-modules', rule, {
         },
       ],
     }),
+    test({
+      code: 'import "./app/index.js"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ '*/app/*' ],
+      } ],
+      errors: [ {
+        message: 'Reaching to "./app/index.js" is not allowed.',
+        line: 1,
+        column: 8,
+      } ],
+    }),
+    test({
+      code: 'import b from "@org/package"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ '@org/**' ],
+      } ],
+      errors: [ {
+        message: 'Reaching to "@org/package" is not allowed.',
+        line: 1,
+        column: 15,
+      } ],
+    }),
+    test({
+      code: 'import b from "app/a/b"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ 'app/**/**' ],
+      } ],
+      errors: [ {
+        message: 'Reaching to "app/a/b" is not allowed.',
+        line: 1,
+        column: 15,
+      } ],
+    }),
+    test({
+      code: 'import get from "lodash.get"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/index.js'),
+      options: [ {
+        forbid: [ 'lodash.*' ],
+      } ],
+      errors: [ {
+        message: 'Reaching to "lodash.get" is not allowed.',
+        line: 1,
+        column: 17,
+      } ],
+    }),
+    test({
+      code: 'import "./app/index.js";\nimport "./app/index"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ '**/index{.js,}' ],
+      } ],
+      errors: [ {
+        message: 'Reaching to "./app/index.js" is not allowed.',
+        line: 1,
+        column: 8,
+      }, {
+        message: 'Reaching to "./app/index" is not allowed.',
+        line: 2,
+        column: 8,
+      } ],
+    }),
     // exports
     test({
       code: 'export * from "./plugin2/index.js";\nexport * from "./plugin2/app/index"',
@@ -251,5 +371,33 @@ ruleTester.run('no-internal-modules', rule, {
         },
       ],
     }),
+    test({
+      code: 'export * from "./plugin2/thing"',
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      options: [ {
+        forbid: [ '**/plugin2/*' ],
+      } ],
+      errors: [
+        {
+          message: 'Reaching to "./plugin2/thing" is not allowed.',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    test({
+      code: 'export * from "app/a"',
+      filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
+      options: [ {
+        forbid: [ '**' ],
+      } ],
+      errors: [
+        {
+          message: 'Reaching to "app/a" is not allowed.',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
   ],
 });

From cecb58bc13495f481f10f9ea67b8fac8a30aaae9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 30 Jan 2021 13:06:52 -0800
Subject: [PATCH 244/767] [meta] add Automatic Rebase and Require Allow Edits
 workflows

---
 .github/workflows/rebase.yml              | 15 +++++++++++++++
 .github/workflows/require-allow-edits.yml | 12 ++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 .github/workflows/rebase.yml
 create mode 100644 .github/workflows/require-allow-edits.yml

diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml
new file mode 100644
index 0000000000..027aed0797
--- /dev/null
+++ b/.github/workflows/rebase.yml
@@ -0,0 +1,15 @@
+name: Automatic Rebase
+
+on: [pull_request_target]
+
+jobs:
+  _:
+    name: "Automatic Rebase"
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - uses: ljharb/rebase@master
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml
new file mode 100644
index 0000000000..549d7b4823
--- /dev/null
+++ b/.github/workflows/require-allow-edits.yml
@@ -0,0 +1,12 @@
+name: Require “Allow Edits”
+
+on: [pull_request_target]
+
+jobs:
+  _:
+    name: "Require “Allow Edits”"
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: ljharb/require-allow-edits@main

From 319d0ca9972c8e0d318e670b886bd779e4f5596f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 30 Jan 2021 13:22:35 -0800
Subject: [PATCH 245/767] [Tests] migrate tests to Github Actions

The OSX tests remain on travis.
---
 .github/workflows/node-4+.yml      | 86 ++++++++++++++++++++++++++++++
 .github/workflows/node-pretest.yml | 27 ++++++++++
 .github/workflows/packages.yml     | 49 +++++++++++++++++
 .gitignore                         |  4 ++
 .nycrc                             | 15 ++++++
 .travis.yml                        | 69 +-----------------------
 package.json                       | 11 ----
 resolvers/node/package.json        |  7 +--
 resolvers/webpack/package.json     |  7 +--
 scripts/copyMetafiles.js           |  1 +
 tests/dep-time-travel.sh           |  9 +++-
 11 files changed, 193 insertions(+), 92 deletions(-)
 create mode 100644 .github/workflows/node-4+.yml
 create mode 100644 .github/workflows/node-pretest.yml
 create mode 100644 .github/workflows/packages.yml
 create mode 100644 .nycrc

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
new file mode 100644
index 0000000000..a689e7923d
--- /dev/null
+++ b/.github/workflows/node-4+.yml
@@ -0,0 +1,86 @@
+name: 'Tests: node.js'
+
+on: [pull_request, push]
+
+jobs:
+  matrix:
+    runs-on: ubuntu-latest
+    outputs:
+      latest: ${{ steps.set-matrix.outputs.requireds }}
+      minors: ${{ steps.set-matrix.outputs.optionals }}
+    steps:
+      - uses: ljharb/actions/node/matrix@main
+        id: set-matrix
+        with:
+          versionsAsRoot: true
+          type: majors
+          preset: '>=4'
+
+  latest:
+    needs: [matrix]
+    name: 'latest majors'
+    runs-on: ubuntu-latest
+
+    strategy:
+      matrix:
+        node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
+        eslint:
+          - 7
+          - 6
+          - 5
+          - 4
+          - 3
+          - 2
+        include:
+          - node-version: 'lts/*'
+            eslint: 7
+            ts-parser: 2
+            env:
+              TS_PARSER: 2
+        exclude:
+          - node-version: 9
+            eslint: 7
+          - node-version: 8
+            eslint: 7
+          - node-version: 7
+            eslint: 7
+          - node-version: 7
+            eslint: 6
+          - node-version: 6
+            eslint: 7
+          - node-version: 6
+            eslint: 6
+          - node-version: 5
+            eslint: 7
+          - node-version: 5
+            eslint: 6
+          - node-version: 5
+            eslint: 5
+          - node-version: 4
+            eslint: 7
+          - node-version: 4
+            eslint: 6
+          - node-version: 4
+            eslint: 5
+
+    steps:
+      - uses: actions/checkout@v2
+      - uses: ljharb/actions/node/run@main
+        continue-on-error: ${{ matrix.eslint == 4 && matrix.node-version == 4 }}
+        name: 'npm install && npm run tests-only'
+        env:
+          ESLINT_VERSION: ${{ matrix.eslint }}
+          TRAVIS_NODE_VERSION: ${{ matrix.node-version }}
+        with:
+          node-version: ${{ matrix.node-version }}
+          after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh
+          command: 'tests-only'
+          after_success: 'npm run coveralls'
+          skip-ls-check: true
+
+  node:
+    name: 'node 4+'
+    needs: [latest]
+    runs-on: ubuntu-latest
+    steps:
+      - run: 'echo tests completed'
diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml
new file mode 100644
index 0000000000..2d10481804
--- /dev/null
+++ b/.github/workflows/node-pretest.yml
@@ -0,0 +1,27 @@
+name: 'Tests: pretest/posttest'
+
+on: [pull_request, push]
+
+jobs:
+  # pretest:
+  #   runs-on: ubuntu-latest
+
+  #   steps:
+  #     - uses: actions/checkout@v2
+  #     - uses: ljharb/actions/node/run@main
+  #       name: 'npm install && npm run pretest'
+  #       with:
+  #         node-version: 'lts/*'
+  #         command: 'pretest'
+
+  posttest:
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v2
+      - uses: ljharb/actions/node/run@main
+        name: 'npm install && npm run posttest'
+        with:
+          node-version: 'lts/*'
+          command: 'posttest'
+          skip-ls-check: true
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
new file mode 100644
index 0000000000..6046948c1c
--- /dev/null
+++ b/.github/workflows/packages.yml
@@ -0,0 +1,49 @@
+name: 'Tests: packages'
+
+on: [pull_request, push]
+
+jobs:
+  matrix:
+    runs-on: ubuntu-latest
+    outputs:
+      latest: ${{ steps.set-matrix.outputs.requireds }}
+      minors: ${{ steps.set-matrix.outputs.optionals }}
+    steps:
+      - uses: ljharb/actions/node/matrix@main
+        id: set-matrix
+        with:
+          type: 'majors'
+          preset: '>=4'
+          versionsAsRoot: true
+
+  tests:
+    needs: [matrix]
+    name: 'packages'
+    runs-on: ubuntu-latest
+
+    strategy:
+      matrix:
+        node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
+        package:
+          - resolvers/node
+          - resolvers/webpack
+          # - memo-parser
+          # - utils
+
+    steps:
+      - uses: actions/checkout@v2
+      - uses: ljharb/actions/node/run@main
+        name: 'npm install && npm run tests-only'
+        with:
+          node-version: ${{ matrix.node-version }}
+          after_install: npm run copy-metafiles && cd ${{ matrix.package }} && npm install
+          command: 'tests-only'
+          after_success: npm run coveralls
+          skip-ls-check: true
+
+  packages:
+    name: 'packages: all tests'
+    needs: [tests]
+    runs-on: ubuntu-latest
+    steps:
+      - run: 'echo tests completed'
diff --git a/.gitignore b/.gitignore
index bb59bce594..e1114fe9ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,9 +25,13 @@ resolvers/node/LICENSE
 resolvers/webpack/LICENSE
 utils/LICENSE
 memo-parser/.npmrc
+memo-parser/.nycrc
 resolvers/node/.npmrc
+resolvers/node/.nycrc
 resolvers/webpack/.npmrc
+resolvers/webpack/.nycrc
 utils/.npmrc
+utils/.nycrc
 
 # Dependency directory
 # Commenting this out is preferred by some people, see
diff --git a/.nycrc b/.nycrc
new file mode 100644
index 0000000000..8147f38718
--- /dev/null
+++ b/.nycrc
@@ -0,0 +1,15 @@
+{
+	"all": true,
+	"check-coverage": false,
+	"reporter": ["text-summary", "text", "html", "json"],
+	"require": [
+		"babel-register"
+	],
+	"sourceMap": true,
+	"instrument": false,
+	"exclude": [
+		"coverage",
+		"test",
+		"tests"
+	]
+}
diff --git a/.travis.yml b/.travis.yml
index 5aec9ffcad..583a411972 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,56 +1,8 @@
 language: node_js
-node_js:
-  - '14'
-  - '13'
-  - '12'
-  - '10'
-  - '8'
-  - '6'
-  - '4'
-
-os: linux
-
-env:
-  - ESLINT_VERSION=^7.0.0-0
-  - ESLINT_VERSION=6
-  - ESLINT_VERSION=5
-  - ESLINT_VERSION=4
-  - ESLINT_VERSION=3
-  - ESLINT_VERSION=2
 
 # osx backlog is often deep, so to be polite we can just hit these highlights
 matrix:
   include:
-  - env: LINT=true
-    node_js: lts/*
-  - env: TS_PARSER=2 ESLINT_VERSION=7
-    node_js: lts/*
-    before_script: 'npm install --no-save @typescript-eslint/parser@2'
-  - env: PACKAGE=resolvers/node
-    node_js: 14
-  - env: PACKAGE=resolvers/node
-    node_js: 12
-  - env: PACKAGE=resolvers/node
-    node_js: 10
-  - env: PACKAGE=resolvers/node
-    node_js: 8
-  - env: PACKAGE=resolvers/node
-    node_js: 6
-  - env: PACKAGE=resolvers/node
-    node_js: 4
-  - env: PACKAGE=resolvers/webpack
-    node_js: 14
-  - env: PACKAGE=resolvers/webpack
-    node_js: 12
-  - env: PACKAGE=resolvers/webpack
-    node_js: 10
-  - env: PACKAGE=resolvers/webpack
-    node_js: 8
-  - env: PACKAGE=resolvers/webpack
-    node_js: 6
-  - env: PACKAGE=resolvers/webpack
-    node_js: 4
-
   - os: osx
     env: ESLINT_VERSION=5
     node_js: 14
@@ -70,37 +22,18 @@ matrix:
     env: ESLINT_VERSION=2
     node_js: 4
 
-  exclude:
-  - node_js: '4'
-    env: ESLINT_VERSION=5
-  - node_js: '4'
-    env: ESLINT_VERSION=6
-  - node_js: '4'
-    env: ESLINT_VERSION=^7.0.0-0
-  - node_js: '6'
-    env: ESLINT_VERSION=6
-  - node_js: '6'
-    env: ESLINT_VERSION=^7.0.0-0
-  - node_js: '8'
-    env: ESLINT_VERSION=^7.0.0-0
-
   fast_finish: true
-  allow_failures:
-  # issues with TypeScript deps in this version intersection
-  - node_js: '4'
-    env: ESLINT_VERSION=4
 
 before_install:
   - 'nvm install-latest-npm'
   - 'npm install'
   - 'npm run copy-metafiles'
-  - 'if [ -n "${PACKAGE-}" ]; then cd "${PACKAGE}"; fi'
 install:
   - 'npm install'
   - 'if [ -n "${ESLINT_VERSION}" ]; then ./tests/dep-time-travel.sh; fi'
 
 script:
-  - 'if [ -n "${LINT-}" ]; then npm run posttest ; else npm run tests-only ; fi'
+  - npm run tests-only
 
 after_success:
   - npm run coveralls
diff --git a/package.json b/package.json
index eb259e4aaf..654e7fe1b0 100644
--- a/package.json
+++ b/package.json
@@ -112,16 +112,5 @@
     "read-pkg-up": "^2.0.0",
     "resolve": "^1.17.0",
     "tsconfig-paths": "^3.9.0"
-  },
-  "nyc": {
-    "require": [
-      "babel-register"
-    ],
-    "sourceMap": false,
-    "instrument": false,
-    "include": [
-      "src/",
-      "resolvers/"
-    ]
   }
 }
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 27daa907f9..5de34c49d6 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -37,11 +37,6 @@
     "chai": "^3.5.0",
     "coveralls": "^3.0.0",
     "mocha": "^3.5.3",
-    "nyc": "^11.7.1"
-  },
-  "nyc": {
-    "exclude": [
-      "test/"
-    ]
+    "nyc": "^11.9.0"
   }
 }
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 82ff610de5..0121fe44ad 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -54,11 +54,6 @@
     "chai": "^3.5.0",
     "coveralls": "^3.0.0",
     "mocha": "^3.5.3",
-    "nyc": "^11.7.1"
-  },
-  "nyc": {
-    "exclude": [
-      "test/"
-    ]
+    "nyc": "^11.9.0"
   }
 }
diff --git a/scripts/copyMetafiles.js b/scripts/copyMetafiles.js
index b2aa03f313..d14964f1c7 100644
--- a/scripts/copyMetafiles.js
+++ b/scripts/copyMetafiles.js
@@ -5,6 +5,7 @@ import resolverDirectories from './resolverDirectories';
 const files = [
   'LICENSE',
   '.npmrc',
+  '.nycrc',
 ];
 
 const directories = [
diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index 078d9059b8..5aa75c4aeb 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -2,7 +2,9 @@
 
 # expected: ESLINT_VERSION numeric env var
 
-npm install --no-save eslint@$ESLINT_VERSION --ignore-scripts || true
+echo "installing ${ESLINT_VERSION}..."
+
+npm install --no-save "eslint@${ESLINT_VERSION}" --ignore-scripts || true
 
 # completely remove the new TypeScript parser for ESLint < v5
 if [[ "$ESLINT_VERSION" -lt "5" ]]; then
@@ -24,3 +26,8 @@ if [[ "$TRAVIS_NODE_VERSION" -lt "8" ]]; then
   echo "Downgrading eslint-import-resolver-typescript..."
   npm i --no-save eslint-import-resolver-typescript@1.0.2
 fi
+
+if [[ -n "$TS_PARSER" ]]; then
+  echo "Downgrading @typescript-eslint/parser..."
+  npm i --no-save @typescript-eslint/parser@2
+fi

From 6f5c52cec32ba94558ea31faa7dc0b6a7c7af982 Mon Sep 17 00:00:00 2001
From: Rafal Lindemann <rl@stamina.pl>
Date: Thu, 2 Nov 2017 22:11:14 +0100
Subject: [PATCH 246/767] [New]: add `no-relative-packages`

Use this rule to prevent importing packages through relative paths.

It's useful in Yarn/Lerna workspaces, were it's possible to import a sibling package using `../package` relative path, while direct `package` is the correct one.

Co-authored-by: Rafal Lindemann <rl@stamina.pl>
Co-authored-by: Tom Payne <tom@tompayne.dev>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 CHANGELOG.md                            | 38 +++++++-----
 docs/rules/no-relative-packages.md      | 66 +++++++++++++++++++++
 src/index.js                            |  1 +
 src/rules/no-relative-packages.js       | 61 +++++++++++++++++++
 tests/files/package-named/index.js      |  1 +
 tests/files/package-named/package.json  |  5 ++
 tests/files/package-scoped/index.js     |  1 +
 tests/files/package-scoped/package.json |  5 ++
 tests/files/package/index.js            |  1 +
 tests/files/package/package.json        |  4 ++
 tests/src/rules/no-relative-packages.js | 79 +++++++++++++++++++++++++
 11 files changed, 246 insertions(+), 16 deletions(-)
 create mode 100644 docs/rules/no-relative-packages.md
 create mode 100644 src/rules/no-relative-packages.js
 create mode 100644 tests/files/package-named/index.js
 create mode 100644 tests/files/package-named/package.json
 create mode 100644 tests/files/package-scoped/index.js
 create mode 100644 tests/files/package-scoped/package.json
 create mode 100644 tests/files/package/index.js
 create mode 100644 tests/files/package/package.json
 create mode 100644 tests/src/rules/no-relative-packages.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae9c0dfd0d..486c0248ab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Added
 - [`no-commonjs`]: Also detect require calls with expressionless template literals: ``` require(`x`) ``` ([#1958], thanks [@FloEdelmann])
 - [`no-internal-modules`]: Add `forbid` option ([#1846], thanks [@guillaumewuip])
+- add [`no-relative-packages`] ([#1860], [#966], thanks [@tapayne88] [@panrafal])
 
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
@@ -739,6 +740,7 @@ for info on changes for earlier releases.
 [`no-named-export`]: ./docs/rules/no-named-export.md
 [`no-namespace`]: ./docs/rules/no-namespace.md
 [`no-nodejs-modules`]: ./docs/rules/no-nodejs-modules.md
+[`no-relative-packages`]: ./docs/rules/no-relative-packages.md
 [`no-relative-parent-imports`]: ./docs/rules/no-relative-parent-imports.md
 [`no-restricted-paths`]: ./docs/rules/no-restricted-paths.md
 [`no-self-import`]: ./docs/rules/no-self-import.md
@@ -754,23 +756,19 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
-[#1944]: https://github.com/benmosher/eslint-plugin-import/pull/1944
-[#1924]: https://github.com/benmosher/eslint-plugin-import/issues/1924
-[#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
 [#1958]: https://github.com/benmosher/eslint-plugin-import/pull/1958
 [#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
 [#1947]: https://github.com/benmosher/eslint-plugin-import/pull/1947
+[#1944]: https://github.com/benmosher/eslint-plugin-import/pull/1944
 [#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940
 [#1897]: https://github.com/benmosher/eslint-plugin-import/pull/1897
 [#1889]: https://github.com/benmosher/eslint-plugin-import/pull/1889
 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
-[#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
+[#1860]: https://github.com/benmosher/eslint-plugin-import/pull/1860
 [#1848]: https://github.com/benmosher/eslint-plugin-import/pull/1848
 [#1846]: https://github.com/benmosher/eslint-plugin-import/pull/1846
-[#1841]: https://github.com/benmosher/eslint-plugin-import/issues/1841
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
 [#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
-[#1834]: https://github.com/benmosher/eslint-plugin-import/issues/1834
 [#1833]: https://github.com/benmosher/eslint-plugin-import/pull/1833
 [#1831]: https://github.com/benmosher/eslint-plugin-import/pull/1831
 [#1830]: https://github.com/benmosher/eslint-plugin-import/pull/1830
@@ -780,7 +778,6 @@ for info on changes for earlier releases.
 [#1820]: https://github.com/benmosher/eslint-plugin-import/pull/1820
 [#1819]: https://github.com/benmosher/eslint-plugin-import/pull/1819
 [#1802]: https://github.com/benmosher/eslint-plugin-import/pull/1802
-[#1801]: https://github.com/benmosher/eslint-plugin-import/issues/1801
 [#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
 [#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
 [#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
@@ -794,10 +791,7 @@ for info on changes for earlier releases.
 [#1735]: https://github.com/benmosher/eslint-plugin-import/pull/1735
 [#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
 [#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
-[#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
 [#1719]: https://github.com/benmosher/eslint-plugin-import/pull/1719
-[#1704]: https://github.com/benmosher/eslint-plugin-import/issues/1704
-[#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
 [#1696]: https://github.com/benmosher/eslint-plugin-import/pull/1696
 [#1691]: https://github.com/benmosher/eslint-plugin-import/pull/1691
 [#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
@@ -808,17 +802,12 @@ for info on changes for earlier releases.
 [#1664]: https://github.com/benmosher/eslint-plugin-import/pull/1664
 [#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
 [#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
-[#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
-[#1631]: https://github.com/benmosher/eslint-plugin-import/issues/1631
 [#1626]: https://github.com/benmosher/eslint-plugin-import/pull/1626
 [#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
 [#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
-[#1616]: https://github.com/benmosher/eslint-plugin-import/issues/1616
-[#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
 [#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
 [#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
 [#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
-[#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
 [#1572]: https://github.com/benmosher/eslint-plugin-import/pull/1572
 [#1569]: https://github.com/benmosher/eslint-plugin-import/pull/1569
@@ -909,6 +898,7 @@ for info on changes for earlier releases.
 [#1068]: https://github.com/benmosher/eslint-plugin-import/pull/1068
 [#1049]: https://github.com/benmosher/eslint-plugin-import/pull/1049
 [#1046]: https://github.com/benmosher/eslint-plugin-import/pull/1046
+[#966]: https://github.com/benmosher/eslint-plugin-import/pull/966
 [#944]: https://github.com/benmosher/eslint-plugin-import/pull/944
 [#912]: https://github.com/benmosher/eslint-plugin-import/pull/912
 [#908]: https://github.com/benmosher/eslint-plugin-import/pull/908
@@ -985,10 +975,24 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
+[#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
+[#1924]: https://github.com/benmosher/eslint-plugin-import/issues/1924
+[#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
+[#1841]: https://github.com/benmosher/eslint-plugin-import/issues/1841
+[#1834]: https://github.com/benmosher/eslint-plugin-import/issues/1834
 [#1814]: https://github.com/benmosher/eslint-plugin-import/issues/1814
 [#1811]: https://github.com/benmosher/eslint-plugin-import/issues/1811
 [#1808]: https://github.com/benmosher/eslint-plugin-import/issues/1808
 [#1805]: https://github.com/benmosher/eslint-plugin-import/issues/1805
+[#1801]: https://github.com/benmosher/eslint-plugin-import/issues/1801
+[#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
+[#1704]: https://github.com/benmosher/eslint-plugin-import/issues/1704
+[#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
+[#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
+[#1631]: https://github.com/benmosher/eslint-plugin-import/issues/1631
+[#1616]: https://github.com/benmosher/eslint-plugin-import/issues/1616
+[#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
+[#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
 [#1565]: https://github.com/benmosher/eslint-plugin-import/issues/1565
 [#1366]: https://github.com/benmosher/eslint-plugin-import/issues/1366
 [#1334]: https://github.com/benmosher/eslint-plugin-import/issues/1334
@@ -1324,4 +1328,6 @@ for info on changes for earlier releases.
 [@paztis]: https://github.com/paztis
 [@FloEdelmann]: https://github.com/FloEdelmann
 [@bicstone]: https://github.com/bicstone
-[@guillaumewuip]: https://github.com/guillaumewuip
\ No newline at end of file
+[@guillaumewuip]: https://github.com/guillaumewuip
+[@tapayne88]: https://github.com/tapayne88
+[@panrafal]: https://github.com/panrafal
\ No newline at end of file
diff --git a/docs/rules/no-relative-packages.md b/docs/rules/no-relative-packages.md
new file mode 100644
index 0000000000..d5a0684932
--- /dev/null
+++ b/docs/rules/no-relative-packages.md
@@ -0,0 +1,66 @@
+# import/no-relative-packages
+
+Use this rule to prevent importing packages through relative paths.
+
+It's useful in Yarn/Lerna workspaces, were it's possible to import a sibling
+package using `../package` relative path, while direct `package` is the correct one.
+
+
+### Examples
+
+Given the following folder structure:
+
+```
+my-project
+├── packages
+│   ├── foo
+│   │   ├── index.js
+│   │   └── package.json
+│   └── bar
+│       ├── index.js
+│       └── package.json
+└── entry.js
+```
+
+And the .eslintrc file:
+```
+{
+  ...
+  "rules": {
+    "import/no-relative-packages": "error"
+  }
+}
+```
+
+The following patterns are considered problems:
+
+```js
+/**
+ *  in my-project/packages/foo.js
+ */
+
+import bar from '../bar'; // Import sibling package using relative path
+import entry from '../../entry.js'; // Import from parent package using relative path
+
+/**
+ *  in my-project/entry.js
+ */
+
+import bar from './packages/bar'; // Import child package using relative path
+```
+
+The following patterns are NOT considered problems:
+
+```js
+/**
+ *  in my-project/packages/foo.js
+ */
+
+import bar from 'bar'; // Import sibling package using package name
+
+/**
+ *  in my-project/entry.js
+ */
+
+import bar from 'bar'; // Import sibling package using package name
+```
diff --git a/src/index.js b/src/index.js
index dbddba8c01..17002337e4 100644
--- a/src/index.js
+++ b/src/index.js
@@ -10,6 +10,7 @@ export const rules = {
   'no-restricted-paths': require('./rules/no-restricted-paths'),
   'no-internal-modules': require('./rules/no-internal-modules'),
   'group-exports': require('./rules/group-exports'),
+  'no-relative-packages': require('./rules/no-relative-packages'),
   'no-relative-parent-imports': require('./rules/no-relative-parent-imports'),
 
   'no-self-import': require('./rules/no-self-import'),
diff --git a/src/rules/no-relative-packages.js b/src/rules/no-relative-packages.js
new file mode 100644
index 0000000000..a654c08393
--- /dev/null
+++ b/src/rules/no-relative-packages.js
@@ -0,0 +1,61 @@
+import path from 'path';
+import readPkgUp from 'read-pkg-up';
+
+import resolve from 'eslint-module-utils/resolve';
+import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
+import importType from '../core/importType';
+import docsUrl from '../docsUrl';
+
+function findNamedPackage(filePath) {
+  const found = readPkgUp.sync({ cwd: filePath, normalize: false });
+  if (found.pkg && !found.pkg.name) {
+    return findNamedPackage(path.join(found.path, '../..'));
+  }
+  return found;
+}
+
+function checkImportForRelativePackage(context, importPath, node) {
+  const potentialViolationTypes = ['parent', 'index', 'sibling'];
+  if (potentialViolationTypes.indexOf(importType(importPath, context)) === -1) {
+    return;
+  }
+
+  const resolvedImport = resolve(importPath, context);
+  const resolvedContext = context.getFilename();
+
+  if (!resolvedImport || !resolvedContext) {
+    return;
+  }
+
+  const importPkg = findNamedPackage(resolvedImport);
+  const contextPkg = findNamedPackage(resolvedContext);
+
+  if (importPkg.pkg && contextPkg.pkg && importPkg.pkg.name !== contextPkg.pkg.name) {
+    const importBaseName = path.basename(importPath);
+    const importRoot = path.dirname(importPkg.path);
+    const properPath = path.relative(importRoot, resolvedImport);
+    const properImport = path.join(
+      importPkg.pkg.name,
+      path.dirname(properPath),
+      importBaseName === path.basename(importRoot) ? '' : importBaseName
+    );
+    context.report({
+      node,
+      message: `Relative import from another package is not allowed. Use \`${properImport}\` instead of \`${importPath}\``,
+    });
+  }
+}
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      url: docsUrl('no-relative-packages'),
+    },
+    schema: [makeOptionsSchema()],
+  },
+
+  create(context) {
+    return moduleVisitor((source) => checkImportForRelativePackage(context, source.value, source), context.options[0]);
+  },
+};
diff --git a/tests/files/package-named/index.js b/tests/files/package-named/index.js
new file mode 100644
index 0000000000..ea9b101e1c
--- /dev/null
+++ b/tests/files/package-named/index.js
@@ -0,0 +1 @@
+export default function () {}
diff --git a/tests/files/package-named/package.json b/tests/files/package-named/package.json
new file mode 100644
index 0000000000..dbda7111f0
--- /dev/null
+++ b/tests/files/package-named/package.json
@@ -0,0 +1,5 @@
+{
+  "name": "package-named",
+  "description": "Standard, named package",
+  "main": "index.js"
+}
\ No newline at end of file
diff --git a/tests/files/package-scoped/index.js b/tests/files/package-scoped/index.js
new file mode 100644
index 0000000000..ea9b101e1c
--- /dev/null
+++ b/tests/files/package-scoped/index.js
@@ -0,0 +1 @@
+export default function () {}
diff --git a/tests/files/package-scoped/package.json b/tests/files/package-scoped/package.json
new file mode 100644
index 0000000000..a2d81cbae3
--- /dev/null
+++ b/tests/files/package-scoped/package.json
@@ -0,0 +1,5 @@
+{
+  "name": "@scope/package-named",
+  "description": "Scoped, named package",
+  "main": "index.js"
+}
diff --git a/tests/files/package/index.js b/tests/files/package/index.js
new file mode 100644
index 0000000000..ea9b101e1c
--- /dev/null
+++ b/tests/files/package/index.js
@@ -0,0 +1 @@
+export default function () {}
diff --git a/tests/files/package/package.json b/tests/files/package/package.json
new file mode 100644
index 0000000000..ad83f1ea7f
--- /dev/null
+++ b/tests/files/package/package.json
@@ -0,0 +1,4 @@
+{
+  "description": "Unnamed package for reaching through main field - rxjs style",
+  "main": "index.js"
+}
\ No newline at end of file
diff --git a/tests/src/rules/no-relative-packages.js b/tests/src/rules/no-relative-packages.js
new file mode 100644
index 0000000000..1a706387c0
--- /dev/null
+++ b/tests/src/rules/no-relative-packages.js
@@ -0,0 +1,79 @@
+import { RuleTester } from 'eslint';
+import rule from 'rules/no-relative-packages';
+import { normalize } from 'path';
+
+import { test, testFilePath } from '../utils';
+
+const ruleTester = new RuleTester();
+
+ruleTester.run('no-relative-packages', rule, {
+  valid: [
+    test({
+      code: 'import foo from "./index.js"',
+      filename: testFilePath('./package/index.js'),
+    }),
+    test({
+      code: 'import bar from "../bar"',
+      filename: testFilePath('./package/index.js'),
+    }),
+    test({
+      code: 'import {foo} from "a"',
+      filename: testFilePath('./package-named/index.js'),
+    }),
+    test({
+      code: 'const bar = require("../bar.js")',
+      filename: testFilePath('./package/index.js'),
+    }),
+    test({
+      code: 'const bar = require("../not/a/file/path.js")',
+      filename: testFilePath('./package/index.js'),
+    }),
+    test({
+      code: 'import "package"',
+      filename: testFilePath('./package/index.js'),
+    }),
+    test({
+      code: 'require("../bar.js")',
+      filename: testFilePath('./package/index.js'),
+    }),
+  ],
+
+  invalid: [
+    test({
+      code: 'import foo from "./package-named"',
+      filename: testFilePath('./bar.js'),
+      errors: [ {
+        message: 'Relative import from another package is not allowed. Use `package-named` instead of `./package-named`',
+        line: 1,
+        column: 17,
+      } ],
+    }),
+    test({
+      code: 'import foo from "../package-named"',
+      filename: testFilePath('./package/index.js'),
+      errors: [ {
+        message: 'Relative import from another package is not allowed. Use `package-named` instead of `../package-named`',
+        line: 1,
+        column: 17,
+      } ],
+    }),
+    test({
+      code: 'import foo from "../package-scoped"',
+      filename: testFilePath('./package/index.js'),
+      errors: [ {
+        message: `Relative import from another package is not allowed. Use \`${normalize('@scope/package-named')}\` instead of \`../package-scoped\``,
+        line: 1,
+        column: 17,
+      } ],
+    }),
+    test({
+      code: 'import bar from "../bar"',
+      filename: testFilePath('./package-named/index.js'),
+      errors: [ {
+        message: `Relative import from another package is not allowed. Use \`${normalize('eslint-plugin-import/tests/files/bar')}\` instead of \`../bar\``,
+        line: 1,
+        column: 17,
+      } ],
+    }),
+  ],
+});

From fe51583cb221a40e9eff613f96b84832025d1236 Mon Sep 17 00:00:00 2001
From: Corey Frang <gnarf@gnarf.net>
Date: Mon, 31 Oct 2016 10:59:36 -0400
Subject: [PATCH 247/767] [Tests] `no-extraneous-dependencies`: Add some
 core-module tests

---
 tests/src/rules/no-extraneous-dependencies.js | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index c94e9f977e..799698c0f9 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -127,6 +127,21 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({ code: 'export class Component extends React.Component {}' }),
     test({ code: 'export function Component() {}' }),
     test({ code: 'export const Component = () => {}' }),
+
+    test({
+      code: 'import "not-a-dependency"',
+      filename: path.join(packageDirMonoRepoRoot, 'foo.js'),
+      options: [{ packageDir: packageDirMonoRepoRoot }],
+      settings: { 'import/core-modules': ['not-a-dependency'] },
+    }),
+    test({
+      code: 'import "@generated/bar/module"',
+      settings: { 'import/core-modules': ['@generated/bar'] },
+    }),
+    test({
+      code: 'import "@generated/bar/and/sub/path"',
+      settings: { 'import/core-modules': ['@generated/bar'] },
+    }),
   ],
   invalid: [
     test({
@@ -322,6 +337,15 @@ ruleTester.run('no-extraneous-dependencies', rule, {
         message: "'chai' should be listed in the project's dependencies. Run 'npm i -S chai' to add it",
       }],
     }),
+
+    test({
+      code: 'import "not-a-dependency"',
+      filename: path.join(packageDirMonoRepoRoot, 'foo.js'),
+      options: [{ packageDir: packageDirMonoRepoRoot }],
+      errors: [{
+        message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
+      }],
+    }),
   ],
 });
 

From a45661bbb37e332511bd40854b2bf0377a608787 Mon Sep 17 00:00:00 2001
From: Thomas Marek <ttmarek@outlook.com>
Date: Fri, 14 Apr 2017 17:18:23 -0400
Subject: [PATCH 248/767] [New] add `no-import-module-exports` rule: report
 import declarations with CommonJS exports

Fixes #760
---
 CHANGELOG.md                                |   6 +-
 README.md                                   |   2 +
 docs/rules/no-import-module-exports.md      |  74 ++++++++++++++
 package.json                                |   1 +
 src/index.js                                |   1 +
 src/rules/no-import-module-exports.js       |  66 +++++++++++++
 tests/src/rules/no-import-module-exports.js | 101 ++++++++++++++++++++
 7 files changed, 250 insertions(+), 1 deletion(-)
 create mode 100644 docs/rules/no-import-module-exports.md
 create mode 100644 src/rules/no-import-module-exports.js
 create mode 100644 tests/src/rules/no-import-module-exports.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 486c0248ab..ac420f24c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-commonjs`]: Also detect require calls with expressionless template literals: ``` require(`x`) ``` ([#1958], thanks [@FloEdelmann])
 - [`no-internal-modules`]: Add `forbid` option ([#1846], thanks [@guillaumewuip])
 - add [`no-relative-packages`] ([#1860], [#966], thanks [@tapayne88] [@panrafal])
+- add [`no-import-module-exports`] rule: report import declarations with CommonJS exports ([#804], thanks [@kentcdodds] and [@ttmarek])
 
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
@@ -732,6 +733,7 @@ for info on changes for earlier releases.
 [`no-duplicates`]: ./docs/rules/no-duplicates.md
 [`no-dynamic-require`]: ./docs/rules/no-dynamic-require.md
 [`no-extraneous-dependencies`]: ./docs/rules/no-extraneous-dependencies.md
+[`no-import-module-exports`]: ./docs/rules/no-import-module-exports.md
 [`no-internal-modules`]: ./docs/rules/no-internal-modules.md
 [`no-mutable-exports`]: ./docs/rules/no-mutable-exports.md
 [`no-named-as-default-member`]: ./docs/rules/no-named-as-default-member.md
@@ -908,6 +910,7 @@ for info on changes for earlier releases.
 [#871]: https://github.com/benmosher/eslint-plugin-import/pull/871
 [#858]: https://github.com/benmosher/eslint-plugin-import/pull/858
 [#843]: https://github.com/benmosher/eslint-plugin-import/pull/843
+[#804]: https://github.com/benmosher/eslint-plugin-import/pull/804
 [#797]: https://github.com/benmosher/eslint-plugin-import/pull/797
 [#794]: https://github.com/benmosher/eslint-plugin-import/pull/794
 [#744]: https://github.com/benmosher/eslint-plugin-import/pull/744
@@ -1330,4 +1333,5 @@ for info on changes for earlier releases.
 [@bicstone]: https://github.com/bicstone
 [@guillaumewuip]: https://github.com/guillaumewuip
 [@tapayne88]: https://github.com/tapayne88
-[@panrafal]: https://github.com/panrafal
\ No newline at end of file
+[@panrafal]: https://github.com/panrafal
+[@ttmarek]: https://github.com/ttmarek
\ No newline at end of file
diff --git a/README.md b/README.md
index e08e72ffa2..7945546a6c 100644
--- a/README.md
+++ b/README.md
@@ -67,11 +67,13 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 * Report CommonJS `require` calls and `module.exports` or `exports.*`. ([`no-commonjs`])
 * Report AMD `require` and `define` calls. ([`no-amd`])
 * No Node.js builtin modules. ([`no-nodejs-modules`])
+* Forbid imports with CommonJS exports ([`no-import-module-exports`])
 
 [`unambiguous`]: ./docs/rules/unambiguous.md
 [`no-commonjs`]: ./docs/rules/no-commonjs.md
 [`no-amd`]: ./docs/rules/no-amd.md
 [`no-nodejs-modules`]: ./docs/rules/no-nodejs-modules.md
+[`no-import-module-exports`]: ./docs/rules/no-import-module-exports.md
 
 
 ### Style guide
diff --git a/docs/rules/no-import-module-exports.md b/docs/rules/no-import-module-exports.md
new file mode 100644
index 0000000000..8131fd5f78
--- /dev/null
+++ b/docs/rules/no-import-module-exports.md
@@ -0,0 +1,74 @@
+# no-import-module-exports
+
+Reports the use of import declarations with CommonJS exports in any module
+except for the [main module](https://docs.npmjs.com/files/package.json#main).
+
+If you have multiple entry points or are using `js:next` this rule includes an
+`exceptions` option which you can use to exclude those files from the rule.
+
+## Options
+
+#### `exceptions`
+ - An array of globs. The rule will be omitted from any file that matches a glob
+   in the options array. For example, the following setting will omit the rule
+   in the `some-file.js` file.
+
+```json
+"import/no-import-module-exports": ["error", {
+    "exceptions": ["**/*/some-file.js"]
+}]
+```
+
+## Rule Details
+
+### Fail
+
+```js
+import { stuff } from 'starwars'
+module.exports = thing
+
+import * as allThings from 'starwars'
+exports.bar = thing
+
+import thing from 'other-thing'
+exports.foo = bar
+
+import thing from 'starwars'
+const baz = module.exports = thing
+console.log(baz)
+```
+
+### Pass
+Given the following package.json:
+
+```json
+{
+  "main": "lib/index.js",
+}
+```
+
+```js
+import thing from 'other-thing'
+export default thing
+
+const thing = require('thing')
+module.exports = thing
+
+const thing = require('thing')
+exports.foo = bar
+
+import thing from 'otherthing'
+console.log(thing.module.exports)
+
+// in lib/index.js
+import foo from 'path';
+module.exports = foo;
+
+// in some-file.js
+// eslint import/no-import-module-exports: ["error", {"exceptions": ["**/*/some-file.js"]}]
+import foo from 'path';
+module.exports = foo;
+```
+
+### Further Reading
+ - [webpack issue #4039](https://github.com/webpack/webpack/issues/4039)
diff --git a/package.json b/package.json
index 654e7fe1b0..70afd11721 100644
--- a/package.json
+++ b/package.json
@@ -109,6 +109,7 @@
     "is-core-module": "^1.0.2",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.1",
+    "pkg-up": "^1.0.0",
     "read-pkg-up": "^2.0.0",
     "resolve": "^1.17.0",
     "tsconfig-paths": "^3.9.0"
diff --git a/src/index.js b/src/index.js
index 17002337e4..7fa3710d64 100644
--- a/src/index.js
+++ b/src/index.js
@@ -40,6 +40,7 @@ export const rules = {
   'no-unassigned-import': require('./rules/no-unassigned-import'),
   'no-useless-path-segments': require('./rules/no-useless-path-segments'),
   'dynamic-import-chunkname': require('./rules/dynamic-import-chunkname'),
+  'no-import-module-exports': require('./rules/no-import-module-exports'),
 
   // export
   'exports-last': require('./rules/exports-last'),
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
new file mode 100644
index 0000000000..7ac56da396
--- /dev/null
+++ b/src/rules/no-import-module-exports.js
@@ -0,0 +1,66 @@
+import minimatch from 'minimatch';
+import path from 'path';
+import pkgUp from 'pkg-up';
+
+function getEntryPoint(context) {
+  const pkgPath = pkgUp.sync(context.getFilename());
+  return require.resolve(path.dirname(pkgPath));
+}
+
+module.exports = {
+  meta: {
+    type: 'problem',
+    docs: {
+      description: 'Disallow import statements with module.exports',
+      category: 'Best Practices',
+      recommended: true,
+    },
+    fixable: 'code',
+    schema: [
+      {
+        'type': 'object',
+        'properties': {
+          'exceptions': { 'type': 'array' },
+        },
+        'additionalProperties': false,
+      },
+    ],
+  },
+  create(context) {
+    const importDeclarations = [];
+    const entryPoint = getEntryPoint(context);
+    const options = context.options[0] || {};
+    let alreadyReported = false;
+
+    function report(node) {
+      const fileName = context.getFilename();
+      const isEntryPoint = entryPoint === fileName;
+      const isIdentifier = node.object.type === 'Identifier';
+      const hasKeywords = (/^(module|exports)$/).test(node.object.name);
+      const isException = options.exceptions &&
+        options.exceptions.some(glob => minimatch(fileName, glob));
+
+      if (isIdentifier && hasKeywords && !isEntryPoint && !isException) {
+        importDeclarations.forEach(importDeclaration => {
+          context.report({
+            node: importDeclaration,
+            message: `Cannot use import declarations in modules that export using ` +
+              `CommonJS (module.exports = 'foo' or exports.bar = 'hi')`,
+          });
+        });
+        alreadyReported = true;
+      }
+    }
+
+    return {
+      ImportDeclaration(node) {
+        importDeclarations.push(node);
+      },
+      MemberExpression(node) {
+        if (!alreadyReported) {
+          report(node);
+        }
+      },
+    };
+  },
+};
diff --git a/tests/src/rules/no-import-module-exports.js b/tests/src/rules/no-import-module-exports.js
new file mode 100644
index 0000000000..bd18bf4777
--- /dev/null
+++ b/tests/src/rules/no-import-module-exports.js
@@ -0,0 +1,101 @@
+import path from 'path';
+import { RuleTester } from 'eslint';
+
+import { test } from '../utils';
+
+const ruleTester = new RuleTester({
+  parserOptions: { ecmaVersion: 6, sourceType: 'module' },
+});
+const rule = require('rules/no-import-module-exports');
+
+const error = {
+  message: `Cannot use import declarations in modules that export using CommonJS ` +
+    `(module.exports = 'foo' or exports.bar = 'hi')`,
+  type: 'ImportDeclaration',
+};
+
+ruleTester.run('no-import-module-exports', rule, {
+  valid: [
+    test({
+      code: `
+        const thing = require('thing')
+        module.exports = thing
+      `,
+    }),
+    test({
+      code: `
+        import thing from 'otherthing'
+        console.log(thing.module.exports)
+      `,
+    }),
+    test({
+      code: `
+        import thing from 'other-thing'
+        export default thing
+      `,
+    }),
+    test({
+      code: `
+        const thing = require('thing')
+        exports.foo = bar
+      `,
+    }),
+    test({
+      code: `
+        import foo from 'path';
+        module.exports = foo;
+      `,
+      // When the file matches the entry point defined in package.json
+      // See tests/files/package.json
+      filename: path.join(process.cwd(), 'tests/files/index.js'),
+    }),
+    test({
+      code: `
+        import foo from 'path';
+        module.exports = foo;
+      `,
+      filename: path.join(process.cwd(), 'tests/files/some/other/entry-point.js'),
+      options: [{ exceptions: ['**/*/other/entry-point.js'] }],
+    }),
+  ],
+  invalid: [
+    test({
+      code: `
+        import { stuff } from 'starwars'
+        module.exports = thing
+      `,
+      errors: [error],
+    }),
+    test({
+      code: `
+        import thing from 'starwars'
+        const baz = module.exports = thing
+        console.log(baz)
+      `,
+      errors: [error],
+    }),
+    test({
+      code: `
+        import * as allThings from 'starwars'
+        exports.bar = thing
+      `,
+      errors: [error],
+    }),
+    test({
+      code: `
+        import thing from 'other-thing'
+        exports.foo = bar
+      `,
+      errors: [error],
+    }),
+    test({
+      code: `
+        import foo from 'path';
+        module.exports = foo;
+      `,
+      filename: path.join(process.cwd(), 'tests/files/some/other/entry-point.js'),
+      options: [{ exceptions: ['**/*/other/file.js'] }],
+      errors: [error],
+    }),
+  ],
+});

From 4c92c479d63e49611c7ae2b6261fe906620e0d98 Mon Sep 17 00:00:00 2001
From: Christian Vuerings <cvuerings@pinterest.com>
Date: Mon, 1 Feb 2021 07:45:39 -0800
Subject: [PATCH 249/767] [Fix] `no-named-default`: ignore Flow import type and
 typeof

---
 CHANGELOG.md                        |  5 ++++-
 docs/rules/no-named-default.md      |  4 ++++
 src/rules/no-named-default.js       |  4 ++++
 tests/src/rules/no-named-default.js | 10 ++++++++++
 4 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac420f24c4..d3e97ae695 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`first`]: fix handling of `import = require` ([#1963], thanks [@MatthiasKunnen])
 - [`no-cycle`]/[`extensions`]: fix isExternalModule usage ([#1696], thanks [@paztis])
 - [`extensions`]/[`no-cycle`]/[`no-extraneous-dependencies`]: Correct module real path resolution ([#1696], thanks [@paztis])
+- [`no-named-default`]: ignore Flow import type and typeof ([#1983], thanks [@christianvuerings])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
@@ -757,6 +758,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1983]: https://github.com/benmosher/eslint-plugin-import/pull/1983
 [#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
 [#1958]: https://github.com/benmosher/eslint-plugin-import/pull/1958
 [#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
@@ -1334,4 +1336,5 @@ for info on changes for earlier releases.
 [@guillaumewuip]: https://github.com/guillaumewuip
 [@tapayne88]: https://github.com/tapayne88
 [@panrafal]: https://github.com/panrafal
-[@ttmarek]: https://github.com/ttmarek
\ No newline at end of file
+[@ttmarek]: https://github.com/ttmarek
+[@christianvuerings]: https://github.com/christianvuerings
diff --git a/docs/rules/no-named-default.md b/docs/rules/no-named-default.md
index 86fb41d615..bb8b13bca4 100644
--- a/docs/rules/no-named-default.md
+++ b/docs/rules/no-named-default.md
@@ -4,6 +4,10 @@ Reports use of a default export as a locally named import.
 
 Rationale: the syntax exists to import default exports expressively, let's use it.
 
+Note that type imports, as used by [Flow], are always ignored.
+
+[Flow]: https://flow.org/
+
 ## Rule Details
 
 Given:
diff --git a/src/rules/no-named-default.js b/src/rules/no-named-default.js
index db046f0aee..d1c15d62e0 100644
--- a/src/rules/no-named-default.js
+++ b/src/rules/no-named-default.js
@@ -13,6 +13,10 @@ module.exports = {
     return {
       'ImportDeclaration': function (node) {
         node.specifiers.forEach(function (im) {
+          if (im.importKind === 'type' || im.importKind === 'typeof') {
+            return;
+          }
+
           if (im.type === 'ImportSpecifier' && im.imported.name === 'default') {
             context.report({
               node: im.local,
diff --git a/tests/src/rules/no-named-default.js b/tests/src/rules/no-named-default.js
index ee8e0959ee..56470f2bac 100644
--- a/tests/src/rules/no-named-default.js
+++ b/tests/src/rules/no-named-default.js
@@ -9,6 +9,16 @@ ruleTester.run('no-named-default', rule, {
     test({ code: 'import bar from "./bar";' }),
     test({ code: 'import bar, { foo } from "./bar";' }),
 
+    // Should ignore imported flow types
+    test({
+      code: 'import { type default as Foo } from "./bar";',
+      parser: require.resolve('babel-eslint'),
+    }),
+    test({
+      code: 'import { typeof default as Foo } from "./bar";',
+      parser: require.resolve('babel-eslint'),
+    }),
+
     ...SYNTAX_CASES,
   ],
 

From 1031e1c22079e1397224ca651632915e05a2d0ad Mon Sep 17 00:00:00 2001
From: Wenfang <duwenfangcn@163.com>
Date: Wed, 14 Oct 2020 13:37:04 +0800
Subject: [PATCH 250/767] [Tests] `extensions`: add cases to verify
 `@/configs/chart` is treated as a package

See #1851.
---
 tests/src/rules/extensions.js | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 34960ea54d..4070c6a6bc 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -339,6 +339,7 @@ ruleTester.run('extensions', rule, {
         import Component from './Component'
         import baz from 'foo/baz'
         import baw from '@scoped/baw/import'
+        import chart from '@/configs/chart'
         import express from 'express'
       `,
       options: [ 'always', { ignorePackages: true } ],
@@ -358,6 +359,7 @@ ruleTester.run('extensions', rule, {
         import Component from './Component'
         import baz from 'foo/baz'
         import baw from '@scoped/baw/import'
+        import chart from '@/configs/chart'
         import express from 'express'
       `,
       options: [ 'ignorePackages' ],
@@ -503,12 +505,19 @@ ruleTester.run('extensions', rule, {
       ],
     }),
     test({
-      code: 'import foo from "@/ImNotAScopedModule"',
+      code: `
+        import foo from "@/ImNotAScopedModule";
+        import chart from '@/configs/chart';
+      `,
       options: ['always'],
       errors: [
         {
           message: 'Missing file extension for "@/ImNotAScopedModule"',
-          line: 1,
+          line: 2,
+        },
+        {
+          message: 'Missing file extension for "@/configs/chart"',
+          line: 3,
         },
       ],
     }),

From f2db74a347a030c15a387826500cdc98203eac1e Mon Sep 17 00:00:00 2001
From: Devon Govett <devongovett@gmail.com>
Date: Sat, 2 Nov 2019 16:25:47 -0700
Subject: [PATCH 251/767] [Fix] `no-extraneous-dependencies`: Exclude flow
 `typeof` imports

Co-authored-by: Devon Govett <devongovett@gmail.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 CHANGELOG.md                                  | 3 +++
 src/rules/no-extraneous-dependencies.js       | 2 +-
 tests/src/rules/no-extraneous-dependencies.js | 8 ++++++++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3e97ae695..bb38ab5ab7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-cycle`]/[`extensions`]: fix isExternalModule usage ([#1696], thanks [@paztis])
 - [`extensions`]/[`no-cycle`]/[`no-extraneous-dependencies`]: Correct module real path resolution ([#1696], thanks [@paztis])
 - [`no-named-default`]: ignore Flow import type and typeof ([#1983], thanks [@christianvuerings])
+- [`no-extraneous-dependencies`]: Exclude flow `typeof` imports ([#1534], thanks [@devongovett])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
@@ -819,6 +820,7 @@ for info on changes for earlier releases.
 [#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
 [#1542]: https://github.com/benmosher/eslint-plugin-import/pull/1542
+[#1534]: https://github.com/benmosher/eslint-plugin-import/pull/1534
 [#1528]: https://github.com/benmosher/eslint-plugin-import/pull/1528
 [#1526]: https://github.com/benmosher/eslint-plugin-import/pull/1526
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
@@ -1338,3 +1340,4 @@ for info on changes for earlier releases.
 [@panrafal]: https://github.com/panrafal
 [@ttmarek]: https://github.com/ttmarek
 [@christianvuerings]: https://github.com/christianvuerings
+[@devongovett]: https://github.com/devongovett
\ No newline at end of file
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 2e541584f1..5fd2674843 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -128,7 +128,7 @@ function getModuleRealName(resolved) {
 
 function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types
-  if (node.importKind === 'type' || (node.parent && node.parent.importKind === 'type')) {
+  if (node.importKind === 'type' || (node.parent && node.parent.importKind === 'type') || node.importKind === 'typeof') {
     return;
   }
 
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 799698c0f9..174cf6f8cf 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -86,6 +86,14 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       options: [{ packageDir: packageDirWithFlowTyped }],
       parser: require.resolve('babel-eslint'),
     }),
+    test({
+      code: `
+        // @flow                                                                                                                                                                                                   
+        import typeof TypeScriptModule from 'typescript';
+      `,
+      options: [{ packageDir: packageDirWithFlowTyped }],
+      parser: require.resolve('babel-eslint'),
+    }),
     test({
       code: 'import react from "react";',
       options: [{ packageDir: packageDirMonoRepoWithNested }],

From 4f642740df0a2322882abf17ec591aa19609ba18 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 2 Feb 2021 12:54:13 -0800
Subject: [PATCH 252/767] [Tests] use `--legacy-peer-deps` for npm 7

This is needed because we test on eslint < 5, and `@typescript-eslint/parser` has peer dep requirements of eslint >= 5.
---
 tests/dep-time-travel.sh | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index 5aa75c4aeb..ad00568e4c 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -4,7 +4,9 @@
 
 echo "installing ${ESLINT_VERSION}..."
 
-npm install --no-save "eslint@${ESLINT_VERSION}" --ignore-scripts || true
+export NPM_CONFIG_LEGACY_PEER_DEPS=true
+
+npm install --no-save "eslint@${ESLINT_VERSION}" --ignore-scripts
 
 # completely remove the new TypeScript parser for ESLint < v5
 if [[ "$ESLINT_VERSION" -lt "5" ]]; then

From 3c23c4c95103902c42a5307a8e2ed4846724344c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 7 Feb 2021 13:18:10 -0800
Subject: [PATCH 253/767] [Tests] `resolvers/webpack`: avoid npm 7
 autoinstalling webpack in the root

TODO: figure out why having webpack available breaks the webpack resolver tests :-/
---
 resolvers/webpack/package.json | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 0121fe44ad..b26774e2f6 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -54,6 +54,7 @@
     "chai": "^3.5.0",
     "coveralls": "^3.0.0",
     "mocha": "^3.5.3",
-    "nyc": "^11.9.0"
+    "nyc": "^11.9.0",
+    "webpack": "https://gist.github.com/ljharb/9cdb687f3806f8e6cb8a365d0b7840eb"
   }
 }

From 85c137bda343c20646f91da67298b54c9fdfcc88 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 7 Feb 2021 13:51:46 -0800
Subject: [PATCH 254/767] [Tests] `order`/`no-duplicates`: make tests check
 actual eslint version instead of env var

---
 tests/src/rules/no-duplicates.js | 5 ++++-
 tests/src/rules/order.js         | 8 ++++++--
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index ed8204cf76..6b5bc739d5 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -2,11 +2,14 @@ import * as path from 'path';
 import { test as testUtil, getNonDefaultParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-duplicates');
 
-const test = process.env.ESLINT_VERSION === '3' || process.env.ESLINT_VERSION === '2'
+// autofix only possible with eslint 4+
+const test = semver.satisfies(eslintPkg.version, '< 4')
   ? t => testUtil(Object.assign({}, t, { output: t.code }))
   : testUtil;
 
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index c599a73c82..42f99c2db8 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2257,7 +2257,9 @@ context('TypeScript', function () {
               ],
               errors: [
                 {
-                  message: process.env.ESLINT_VERSION === '2' ? '`bar` import should occur after import of `Bar`' : /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,
+                  message: semver.satisfies(eslintPkg.version, '< 3')
+                    ? '`bar` import should occur after import of `Bar`'
+                    : /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,
                 },
               ],
             },
@@ -2293,7 +2295,9 @@ context('TypeScript', function () {
               ],
               errors: [
                 {
-                  message: process.env.ESLINT_VERSION === '2' ? '`bar` import should occur before import of `Bar`' : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
+                  message: semver.satisfies(eslintPkg.version, '< 3')
+                    ? '`bar` import should occur before import of `Bar`'
+                    : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
                 },
               ],
             },

From 7a37fb265854d568c50a3571dff8e668f9f9f2a0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 24 Feb 2021 09:11:50 -0800
Subject: [PATCH 255/767] [Tests] widen dev dep ranges to allow for
 dep-time-travel.sh

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 70afd11721..8926092e92 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,7 @@
     "array.prototype.flatmap": "^1.2.3",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
-    "babel-eslint": "^8.2.6",
+    "babel-eslint": "=8.0.3 || ^8.2.6",
     "babel-plugin-istanbul": "^4.1.6",
     "babel-plugin-module-resolver": "^2.7.1",
     "babel-preset-es2015-argon": "latest",
@@ -71,7 +71,7 @@
     "cross-env": "^4.0.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0",
     "eslint-import-resolver-node": "file:./resolvers/node",
-    "eslint-import-resolver-typescript": "^1.1.1",
+    "eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
     "eslint-import-test-order-redirect": "file:./tests/files/order-redirect",
     "eslint-module-utils": "file:./utils",
@@ -90,8 +90,8 @@
     "rimraf": "^2.7.1",
     "semver": "^6.3.0",
     "sinon": "^2.4.1",
-    "typescript": "~3.9.5",
-    "typescript-eslint-parser": "^22.0.0"
+    "typescript": "^2.8.1 || ~3.9.5",
+    "typescript-eslint-parser": "^15 || ^22.0.0"
   },
   "peerDependencies": {
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0"

From e871a9a2e18fd4d67a5a237789131b44cc705b5b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 28 Feb 2021 20:12:57 -0800
Subject: [PATCH 256/767] [Tests] temporarily disable some tests in eslint 4

---
 .github/workflows/node-4+.yml                 |  1 +
 tests/src/rules/no-extraneous-dependencies.js |  7 ++++---
 tests/src/rules/no-unused-modules.js          | 19 ++++++++++++-------
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index a689e7923d..6e99312d80 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -22,6 +22,7 @@ jobs:
     runs-on: ubuntu-latest
 
     strategy:
+      fail-fast: false
       matrix:
         node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
         eslint:
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 174cf6f8cf..96ce533ac3 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -357,7 +357,8 @@ ruleTester.run('no-extraneous-dependencies', rule, {
   ],
 });
 
-describe('TypeScript', function () {
+// TODO: figure out why these tests fail in eslint 4
+describe('TypeScript', { skip: semver.satisfies(eslintPkg.version, '^4') }, function () {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
       parser: parser,
@@ -390,14 +391,14 @@ describe('TypeScript', function () {
         valid: [],
         invalid: [
           test(Object.assign({
-            code: 'import { JSONSchema7Type } from "@types/json-schema";',
+            code: 'import { JSONSchema7Type } from "@types/json-schema"; /* typescript-eslint-parser */',
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             errors: [{
               message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
             }],
           }, parserConfig)),
           test(Object.assign({
-            code: 'import type { JSONSchema7Type } from "@types/json-schema";',
+            code: 'import type { JSONSchema7Type } from "@types/json-schema"; /* typescript-eslint-parser */',
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             errors: [{
               message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 5906c9afbf..e1f1ddb6c9 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -4,6 +4,11 @@ import typescriptConfig from '../../../config/typescript';
 
 import { RuleTester } from 'eslint';
 import fs from 'fs';
+import semver from 'semver';
+import eslintPkg from 'eslint/package.json';
+
+// TODO: figure out why these tests fail in eslint 4
+const isESLint4TODO = semver.satisfies(eslintPkg.version, '^4');
 
 const ruleTester = new RuleTester();
 const typescriptRuleTester = new RuleTester(typescriptConfig);
@@ -747,7 +752,7 @@ describe('Avoid errors if re-export all from umd compiled library', () => {
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     typescriptRuleTester.run('no-unused-modules', rule, {
-      valid: [
+      valid: [].concat(
         test({
           options: unusedExportsTypescriptOptions,
           code: `
@@ -828,7 +833,7 @@ context('TypeScript', function () {
           filename: testFilePath('./no-unused-modules/typescript/file-ts-e-used-as-type.ts'),
         }),
         // Should also be valid when the exporting files are linted before the importing ones
-        test({
+        isESLint4TODO ? [] : test({
           options: unusedExportsTypescriptOptions,
           code: `export interface g {}`,
           parser,
@@ -840,9 +845,9 @@ context('TypeScript', function () {
           parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-f.ts'),
         }),
-        test({
+        isESLint4TODO ? [] : test({
           options: unusedExportsTypescriptOptions,
-          code: `export interface g {};`,
+          code: `export interface g {}; /* used-as-type */`,
           parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-g-used-as-type.ts'),
         }),
@@ -852,8 +857,8 @@ context('TypeScript', function () {
           parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-f-import-type.ts'),
         }),
-      ],
-      invalid: [
+      ),
+      invalid: [].concat(
         test({
           options: unusedExportsTypescriptOptions,
           code: `export const b = 2;`,
@@ -890,7 +895,7 @@ context('TypeScript', function () {
             error(`exported declaration 'e' not used within other modules`),
           ],
         }),
-      ],
+      ),
     });
   });
 });

From 5a2fd289e096af4b5b93042da59a2c70779f3dcd Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 11 May 2021 22:12:54 -0700
Subject: [PATCH 257/767] [Deps] update `array-includes`,
 `array.prototype.flat`, `object.values`, `resolve`

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 8926092e92..20828ca233 100644
--- a/package.json
+++ b/package.json
@@ -97,8 +97,8 @@
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0"
   },
   "dependencies": {
-    "array-includes": "^3.1.1",
-    "array.prototype.flat": "^1.2.3",
+    "array-includes": "^3.1.3",
+    "array.prototype.flat": "^1.2.4",
     "contains-path": "^0.1.0",
     "debug": "^2.6.9",
     "doctrine": "1.5.0",
@@ -108,10 +108,10 @@
     "has": "^1.0.3",
     "is-core-module": "^1.0.2",
     "minimatch": "^3.0.4",
-    "object.values": "^1.1.1",
+    "object.values": "^1.1.3",
     "pkg-up": "^1.0.0",
     "read-pkg-up": "^2.0.0",
-    "resolve": "^1.17.0",
+    "resolve": "^1.20.0",
     "tsconfig-paths": "^3.9.0"
   }
 }

From 93a8b455e091b7dba5bf9ebf2d200adeb1aeddf1 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 11 May 2021 22:13:20 -0700
Subject: [PATCH 258/767] [Deps] update `is-core-module`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 20828ca233..8bb9c41a27 100644
--- a/package.json
+++ b/package.json
@@ -106,7 +106,7 @@
     "eslint-module-utils": "^2.6.0",
     "find-up": "^2.0.0",
     "has": "^1.0.3",
-    "is-core-module": "^1.0.2",
+    "is-core-module": "^2.4.0",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.3",
     "pkg-up": "^1.0.0",

From b44d9c2f040564be278fb109482f671d9f5c7fc2 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 11 May 2021 22:15:20 -0700
Subject: [PATCH 259/767] [Dev Deps] update `array.prototype.flatmap`, `chai`,
 `glob`

---
 package.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 8bb9c41a27..b485d58e35 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,7 @@
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "^2.23.0 || ^3.3.0",
-    "array.prototype.flatmap": "^1.2.3",
+    "array.prototype.flatmap": "^1.2.4",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
     "babel-eslint": "=8.0.3 || ^8.2.6",
@@ -66,7 +66,7 @@
     "babel-preset-flow": "^6.23.0",
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
-    "chai": "^4.2.0",
+    "chai": "^4.3.4",
     "coveralls": "^3.1.0",
     "cross-env": "^4.0.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0",
@@ -79,7 +79,7 @@
     "eslint-plugin-import": "2.x",
     "eslint-plugin-json": "^2.1.2",
     "fs-copy-file-sync": "^1.1.1",
-    "glob": "^7.1.6",
+    "glob": "^7.1.7",
     "in-publish": "^2.0.1",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",

From cd48ef60697b40e2cd4528d34ed9cd3ae6aaaaf2 Mon Sep 17 00:00:00 2001
From: Edward Grech <dwardu@gmail.com>
Date: Wed, 24 Feb 2021 09:37:06 +0100
Subject: [PATCH 260/767] [Docs] `no-extraneous-dependencies`: correct
 peerDependencies option default to `true`

---
 CHANGELOG.md                             | 5 ++++-
 docs/rules/no-extraneous-dependencies.md | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bb38ab5ab7..3b9edced61 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
 - [Docs] [`no-named-as-default`]: add semicolon ([#1897], thanks [@bicstone])
+- [Docs] `no-extraneous-dependencies`: correct peerDependencies option default to `true` ([#1993], thanks [@dwardu])
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -759,6 +760,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993
 [#1983]: https://github.com/benmosher/eslint-plugin-import/pull/1983
 [#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
 [#1958]: https://github.com/benmosher/eslint-plugin-import/pull/1958
@@ -1340,4 +1342,5 @@ for info on changes for earlier releases.
 [@panrafal]: https://github.com/panrafal
 [@ttmarek]: https://github.com/ttmarek
 [@christianvuerings]: https://github.com/christianvuerings
-[@devongovett]: https://github.com/devongovett
\ No newline at end of file
+[@devongovett]: https://github.com/devongovett
+[@dwardu]: https://github.com/dwardu
diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index 295590ccd0..e9743a7619 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -13,7 +13,7 @@ This rule supports the following options:
 
 `optionalDependencies`: If set to `false`, then the rule will show an error when `optionalDependencies` are imported. Defaults to `true`.
 
-`peerDependencies`: If set to `false`, then the rule will show an error when `peerDependencies` are imported. Defaults to `false`.
+`peerDependencies`: If set to `false`, then the rule will show an error when `peerDependencies` are imported. Defaults to `true`.
 
 `bundledDependencies`: If set to `false`, then the rule will show an error when `bundledDependencies` are imported. Defaults to `true`.
 

From d31d615e63e2e76d56d6c69b6eedfc94bc3f35a3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 11 May 2021 23:12:50 -0700
Subject: [PATCH 261/767] [Tests] remove failing node 10 WSL test

---
 appveyor.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/appveyor.yml b/appveyor.yml
index b79315b7be..de79234eb4 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -16,6 +16,8 @@ image: Visual Studio 2019
 matrix:
   fast_finish: false
   exclude:
+    - configuration: WSL
+      nodejs_version: "10"
     - configuration: WSL
       nodejs_version: "8"
 

From ab0181d79c6959e6c5cfe25343d8648c1b275bf6 Mon Sep 17 00:00:00 2001
From: Andreas Opferkuch <andreas.opferkuch@gmail.com>
Date: Sun, 28 Feb 2021 16:27:27 +0100
Subject: [PATCH 262/767] [New] `no-unused-modules`: Support destructuring

---
 CHANGELOG.md                                  |  3 +++
 src/rules/no-unused-modules.js                | 14 +++++++++++--
 .../no-unused-modules/destructuring-a.js      |  1 +
 .../no-unused-modules/destructuring-b.js      |  2 ++
 tests/src/rules/no-unused-modules.js          | 20 +++++++++++++++++++
 5 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 tests/files/no-unused-modules/destructuring-a.js
 create mode 100644 tests/files/no-unused-modules/destructuring-b.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3b9edced61..edcde85339 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-internal-modules`]: Add `forbid` option ([#1846], thanks [@guillaumewuip])
 - add [`no-relative-packages`] ([#1860], [#966], thanks [@tapayne88] [@panrafal])
 - add [`no-import-module-exports`] rule: report import declarations with CommonJS exports ([#804], thanks [@kentcdodds] and [@ttmarek])
+- [`no-unused-modules`]: Support destructuring assignment for `export`. ([#1997], thanks [@s-h-a-d-o-w])
 
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
@@ -760,6 +761,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997
 [#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993
 [#1983]: https://github.com/benmosher/eslint-plugin-import/pull/1983
 [#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
@@ -1344,3 +1346,4 @@ for info on changes for earlier releases.
 [@christianvuerings]: https://github.com/christianvuerings
 [@devongovett]: https://github.com/devongovett
 [@dwardu]: https://github.com/dwardu
+[@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index dfea6de6df..99b564edab 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -4,7 +4,7 @@
  * @author René Fermann
  */
 
-import Exports from '../ExportMap';
+import Exports, { recursivePatternCapture } from '../ExportMap';
 import { getFileExtensions } from 'eslint-module-utils/ignore';
 import resolve from 'eslint-module-utils/resolve';
 import docsUrl from '../docsUrl';
@@ -63,6 +63,8 @@ const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier';
 const VARIABLE_DECLARATION = 'VariableDeclaration';
 const FUNCTION_DECLARATION = 'FunctionDeclaration';
 const CLASS_DECLARATION = 'ClassDeclaration';
+const IDENTIFIER = 'Identifier';
+const OBJECT_PATTERN = 'ObjectPattern';
 const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration';
 const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration';
 const TS_ENUM_DECLARATION = 'TSEnumDeclaration';
@@ -80,7 +82,15 @@ function forEachDeclarationIdentifier(declaration, cb) {
       cb(declaration.id.name);
     } else if (declaration.type === VARIABLE_DECLARATION) {
       declaration.declarations.forEach(({ id }) => {
-        cb(id.name);
+        if (id.type === OBJECT_PATTERN) {
+          recursivePatternCapture(id, (pattern) => {
+            if (pattern.type === IDENTIFIER) {
+              cb(pattern.name);
+            }
+          });
+        } else {
+          cb(id.name);
+        }
       });
     }
   }
diff --git a/tests/files/no-unused-modules/destructuring-a.js b/tests/files/no-unused-modules/destructuring-a.js
new file mode 100644
index 0000000000..1da867deff
--- /dev/null
+++ b/tests/files/no-unused-modules/destructuring-a.js
@@ -0,0 +1 @@
+import {a, b} from "./destructuring-b";
diff --git a/tests/files/no-unused-modules/destructuring-b.js b/tests/files/no-unused-modules/destructuring-b.js
new file mode 100644
index 0000000000..b477a5b6f2
--- /dev/null
+++ b/tests/files/no-unused-modules/destructuring-b.js
@@ -0,0 +1,2 @@
+const obj = {a: 1, dummy: {b: 2}};
+export const {a, dummy: {b}} = obj;
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index e1f1ddb6c9..cd054ecb9d 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -970,3 +970,23 @@ describe('ignore flow types', () => {
     invalid: [],
   });
 });
+
+describe('support (nested) destructuring assignment', () => {
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsOptions,
+        code: 'import {a, b} from "./destructuring-b";',
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/destructuring-a.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: 'const obj = {a: 1, dummy: {b: 2}}; export const {a, dummy: {b}} = obj;',
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/destructuring-b.js'),
+      }),
+    ],
+    invalid: [],
+  });
+});

From 1c10e79dc4761d69c5ce26736541f8d024ce7339 Mon Sep 17 00:00:00 2001
From: Geraint White <geraint.white@bt.com>
Date: Thu, 1 Apr 2021 10:59:27 +0100
Subject: [PATCH 263/767] [New] `order`: support type imports

Fixes #645.
---
 CHANGELOG.md             |  3 +++
 docs/rules/order.md      |  6 +++--
 src/rules/order.js       |  8 +++---
 tests/src/rules/order.js | 54 ++++++++++++++++++++++------------------
 4 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index edcde85339..fb347894fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - add [`no-relative-packages`] ([#1860], [#966], thanks [@tapayne88] [@panrafal])
 - add [`no-import-module-exports`] rule: report import declarations with CommonJS exports ([#804], thanks [@kentcdodds] and [@ttmarek])
 - [`no-unused-modules`]: Support destructuring assignment for `export`. ([#1997], thanks [@s-h-a-d-o-w])
+- [`order`]: support type imports ([#2021], thanks [@grit96])
 
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
@@ -761,6 +762,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021
 [#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997
 [#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993
 [#1983]: https://github.com/benmosher/eslint-plugin-import/pull/1983
@@ -1347,3 +1349,4 @@ for info on changes for earlier releases.
 [@devongovett]: https://github.com/devongovett
 [@dwardu]: https://github.com/dwardu
 [@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w
+[@grit96]: https://github.com/grit96
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 7d91efd6f5..d760c2c0f5 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -24,6 +24,8 @@ import baz from './bar/baz';
 import main from './';
 // 7. "object"-imports (only available in TypeScript)
 import log = console.log;
+// 8. "type" imports (only available in Flow and TypeScript)
+import type { Foo } from 'foo';
 ```
 
 Unassigned imports are ignored, as the order they are imported in may be important.
@@ -80,7 +82,7 @@ This rule supports the following options:
 ### `groups: [array]`:
 
 How groups are defined, and the order to respect. `groups` must be an array of `string` or [`string`]. The only allowed `string`s are:
-`"builtin"`, `"external"`, `"internal"`, `"unknown"`, `"parent"`, `"sibling"`, `"index"`, `"object"`.
+`"builtin"`, `"external"`, `"internal"`, `"unknown"`, `"parent"`, `"sibling"`, `"index"`, `"object"`, `"type"`.
 The enforced order is the same as the order of each element in a group. Omitted types are implicitly grouped together as the last element. Example:
 ```js
 [
@@ -96,7 +98,7 @@ The default value is `["builtin", "external", "parent", "sibling", "index"]`.
 You can set the options like this:
 
 ```js
-"import/order": ["error", {"groups": ["index", "sibling", "parent", "internal", "external", "builtin", "object"]}]
+"import/order": ["error", {"groups": ["index", "sibling", "parent", "internal", "external", "builtin", "object", "type"]}]
 ```
 
 ### `pathGroups: [array of objects]`:
diff --git a/src/rules/order.js b/src/rules/order.js
index bad382945c..3aabbc74c7 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -265,7 +265,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
     if (!Array.isArray(acc[importedItem.rank])) {
       acc[importedItem.rank] = [];
     }
-    acc[importedItem.rank].push(importedItem.value);
+    acc[importedItem.rank].push(`${importedItem.value}-${importedItem.node.importKind}`);
     return acc;
   }, {});
 
@@ -290,7 +290,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
 
   // mutate the original group-rank with alphabetized-rank
   imported.forEach(function(importedItem) {
-    importedItem.rank = alphabetizedRanks[importedItem.value];
+    importedItem.rank = alphabetizedRanks[`${importedItem.value}-${importedItem.node.importKind}`];
   });
 }
 
@@ -310,6 +310,8 @@ function computeRank(context, ranks, importEntry, excludedImportTypes) {
   let rank;
   if (importEntry.type === 'import:object') {
     impType = 'object';
+  } else if (importEntry.node.importKind === 'type') {
+    impType = 'type';
   } else {
     impType = importType(importEntry.value, context);
   }
@@ -350,7 +352,7 @@ function isModuleLevelRequire(node) {
   );
 }
 
-const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object'];
+const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object', 'type'];
 
 // Creates an object with type-rank pairs.
 // Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 42f99c2db8..4fcbb29d73 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2186,12 +2186,13 @@ context('TypeScript', function () {
             {
               code: `
                 import c from 'Bar';
-                import type { C } from 'Bar';
                 import b from 'bar';
                 import a from 'foo';
-                import type { A } from 'foo';
 
                 import index from './';
+
+                import type { C } from 'Bar';
+                import type { A } from 'foo';
               `,
               parser,
               options: [
@@ -2208,12 +2209,13 @@ context('TypeScript', function () {
             {
               code: `
                 import a from 'foo';
-                import type { A } from 'foo';
                 import b from 'bar';
                 import c from 'Bar';
-                import type { C } from 'Bar';
 
                 import index from './';
+
+                import type { A } from 'foo';
+                import type { C } from 'Bar';
               `,
               parser,
               options: [
@@ -2233,20 +2235,22 @@ context('TypeScript', function () {
               code: `
               import b from 'bar';
               import c from 'Bar';
-              import type { C } from 'Bar';
               import a from 'foo';
-              import type { A } from 'foo';
 
               import index from './';
+
+              import type { A } from 'foo';
+              import type { C } from 'Bar';
             `,
               output: `
               import c from 'Bar';
-              import type { C } from 'Bar';
               import b from 'bar';
               import a from 'foo';
-              import type { A } from 'foo';
 
               import index from './';
+
+              import type { C } from 'Bar';
+              import type { A } from 'foo';
             `,
               parser,
               options: [
@@ -2255,12 +2259,12 @@ context('TypeScript', function () {
                   alphabetize: { order: 'asc' },
                 },
               ],
-              errors: [
-                {
-                  message: semver.satisfies(eslintPkg.version, '< 3')
-                    ? '`bar` import should occur after import of `Bar`'
-                    : /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,
-                },
+              errors: semver.satisfies(eslintPkg.version, '< 3') ? [
+                { message: '`Bar` import should occur before import of `bar`' },
+                { message: '`Bar` import should occur before import of `foo`' },
+              ] : [
+                { message: /(`Bar` import should occur before import of `bar`)|(`bar` import should occur after import of `Bar`)/ },
+                { message: /(`Bar` import should occur before import of `foo`)|(`foo` import should occur after import of `Bar`)/ },
               ],
             },
             parserConfig,
@@ -2270,21 +2274,23 @@ context('TypeScript', function () {
             {
               code: `
               import a from 'foo';
-              import type { A } from 'foo';
               import c from 'Bar';
-              import type { C } from 'Bar';
               import b from 'bar';
 
               import index from './';
+
+              import type { C } from 'Bar';
+              import type { A } from 'foo';
             `,
               output: `
               import a from 'foo';
-              import type { A } from 'foo';
               import b from 'bar';
               import c from 'Bar';
-              import type { C } from 'Bar';
 
               import index from './';
+
+              import type { A } from 'foo';
+              import type { C } from 'Bar';
             `,
               parser,
               options: [
@@ -2293,12 +2299,12 @@ context('TypeScript', function () {
                   alphabetize: { order: 'desc' },
                 },
               ],
-              errors: [
-                {
-                  message: semver.satisfies(eslintPkg.version, '< 3')
-                    ? '`bar` import should occur before import of `Bar`'
-                    : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
-                },
+              errors: semver.satisfies(eslintPkg.version, '< 3') ? [
+                { message: '`bar` import should occur before import of `Bar`' },
+                { message: '`foo` import should occur before import of `Bar`' },
+              ] : [
+                { message: /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/ },
+                { message: /(`foo` import should occur before import of `Bar`)|(`Bar` import should occur after import of `foo`)/ },
               ],
             },
             parserConfig,

From 359b6e5b0d8b6312aea31ad4315c6e08816d94ab Mon Sep 17 00:00:00 2001
From: lilling <yonatanliling@gmail.com>
Date: Tue, 2 Feb 2021 22:01:16 +0200
Subject: [PATCH 264/767] [Fix] `newline-after-import`: respect decorator
 annotations

Fixes #1784.
---
 CHANGELOG.md                            |  3 +++
 src/rules/newline-after-import.js       |  6 ++++-
 tests/src/rules/newline-after-import.js | 30 ++++++++++++++++++++++---
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb347894fd..f54e6c07ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extensions`]/[`no-cycle`]/[`no-extraneous-dependencies`]: Correct module real path resolution ([#1696], thanks [@paztis])
 - [`no-named-default`]: ignore Flow import type and typeof ([#1983], thanks [@christianvuerings])
 - [`no-extraneous-dependencies`]: Exclude flow `typeof` imports ([#1534], thanks [@devongovett])
+- [`newline-after-import`]: respect decorator annotations ([#1985], thanks [@lilling])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
@@ -765,6 +766,7 @@ for info on changes for earlier releases.
 [#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021
 [#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997
 [#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993
+[#1985]: https://github.com/benmosher/eslint-plugin-import/pull/1985
 [#1983]: https://github.com/benmosher/eslint-plugin-import/pull/1983
 [#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
 [#1958]: https://github.com/benmosher/eslint-plugin-import/pull/1958
@@ -1350,3 +1352,4 @@ for info on changes for earlier releases.
 [@dwardu]: https://github.com/dwardu
 [@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w
 [@grit96]: https://github.com/grit96
+[@lilling]: https://github.com/lilling
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 1e698f13e5..935572aa47 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -47,6 +47,10 @@ function isExportDefaultClass(node) {
   return node.type === 'ExportDefaultDeclaration' && node.declaration.type === 'ClassDeclaration';
 }
 
+function isExportNameClass(node) {
+  return node.type === 'ExportNamedDeclaration' && node.declaration.type === 'ClassDeclaration';
+}
+
 module.exports = {
   meta: {
     type: 'layout',
@@ -72,7 +76,7 @@ module.exports = {
     const requireCalls = [];
 
     function checkForNewLine(node, nextNode, type) {
-      if (isExportDefaultClass(nextNode)) {
+      if (isExportDefaultClass(nextNode) || isExportNameClass(nextNode)) {
         const classNode = nextNode.declaration;
 
         if (isClassWithDecorator(classNode)) {
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 58f5ef1dd8..a01bfead60 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -1,7 +1,7 @@
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
 
-import { getTSParsers } from '../utils';
+import { getTSParsers, testVersion } from '../utils';
 
 const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.';
 const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => {
@@ -234,7 +234,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
     ]),
   ],
 
-  invalid: [
+  invalid: [].concat(
     {
       code: `import foo from 'foo';\nexport default function() {};`,
       output: `import foo from 'foo';\n\nexport default function() {};`,
@@ -429,5 +429,29 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { sourceType: 'module' },
       parser: require.resolve('babel-eslint'),
     },
-  ],
+    testVersion('>= 6', () => ({
+      code: `
+        // issue 1784
+        import { map } from 'rxjs/operators';
+        @Component({})
+        export class Test {}
+      `,
+      output: `
+        // issue 1784
+        import { map } from 'rxjs/operators';
+
+        @Component({})
+        export class Test {}
+      `,
+      errors: [
+        {
+          line: 3,
+          column: 9,
+          message: IMPORT_ERROR_MESSAGE,
+        },
+      ],
+      parserOptions: { sourceType: 'module' },
+      parser: require.resolve('babel-eslint'),
+    })) || [],
+  ),
 });

From 17a445d2b37f91b5feda9c23adc0b366eb56055d Mon Sep 17 00:00:00 2001
From: Vasily Malykhin <malykhinvi@gmail.com>
Date: Fri, 2 Apr 2021 09:05:02 +0300
Subject: [PATCH 265/767] [Fix] `no-restricted-paths`: enhance performance for
 exceptions

---
 CHANGELOG.md                     |  2 ++
 src/rules/no-restricted-paths.js | 22 +++++++++++++++-------
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f54e6c07ed..438efefc98 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-named-default`]: ignore Flow import type and typeof ([#1983], thanks [@christianvuerings])
 - [`no-extraneous-dependencies`]: Exclude flow `typeof` imports ([#1534], thanks [@devongovett])
 - [`newline-after-import`]: respect decorator annotations ([#1985], thanks [@lilling])
+- [`no-restricted-paths`]: enhance performance for zones with `except` paths ([#2022], thanks [@malykhinvi])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
@@ -763,6 +764,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2022]: https://github.com/benmosher/eslint-plugin-import/pull/2022
 [#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021
 [#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997
 [#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index a856a8bb43..e2b11957f7 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -68,6 +68,19 @@ module.exports = {
       });
     }
 
+    const zoneExceptions = matchingZones.map((zone) => {
+      const exceptionPaths = zone.except || [];
+      const absoluteFrom = path.resolve(basePath, zone.from);
+      const absoluteExceptionPaths = exceptionPaths.map((exceptionPath) => path.resolve(absoluteFrom, exceptionPath));
+      const hasValidExceptionPaths = absoluteExceptionPaths
+        .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
+
+      return {
+        absoluteExceptionPaths,
+        hasValidExceptionPaths,
+      };
+    });
+
     function checkForRestrictedImportPath(importPath, node) {
       const absoluteImportPath = resolve(importPath, context);
 
@@ -75,19 +88,14 @@ module.exports = {
         return;
       }
 
-      matchingZones.forEach((zone) => {
-        const exceptionPaths = zone.except || [];
+      matchingZones.forEach((zone, index) => {
         const absoluteFrom = path.resolve(basePath, zone.from);
 
         if (!containsPath(absoluteImportPath, absoluteFrom)) {
           return;
         }
 
-        const absoluteExceptionPaths = exceptionPaths.map((exceptionPath) =>
-          path.resolve(absoluteFrom, exceptionPath)
-        );
-        const hasValidExceptionPaths = absoluteExceptionPaths
-          .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
+        const { hasValidExceptionPaths, absoluteExceptionPaths } = zoneExceptions[index];
 
         if (!hasValidExceptionPaths) {
           reportInvalidExceptionPath(node);

From 5898e28a113ce24d62bfa9ee808cfd1694bf3785 Mon Sep 17 00:00:00 2001
From: Dmitry Semigradsky <semigradskyd@gmail.com>
Date: Mon, 26 Apr 2021 19:11:57 +0300
Subject: [PATCH 266/767] [Deps] update `contains-path`, `doctrine`, `pkg-up`,
 `read-pkg-up`

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index b485d58e35..6f02ab8a52 100644
--- a/package.json
+++ b/package.json
@@ -99,9 +99,9 @@
   "dependencies": {
     "array-includes": "^3.1.3",
     "array.prototype.flat": "^1.2.4",
-    "contains-path": "^0.1.0",
+    "contains-path": "^1.0.0",
     "debug": "^2.6.9",
-    "doctrine": "1.5.0",
+    "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.4",
     "eslint-module-utils": "^2.6.0",
     "find-up": "^2.0.0",
@@ -109,8 +109,8 @@
     "is-core-module": "^2.4.0",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.3",
-    "pkg-up": "^1.0.0",
-    "read-pkg-up": "^2.0.0",
+    "pkg-up": "^2.0.0",
+    "read-pkg-up": "^3.0.0",
     "resolve": "^1.20.0",
     "tsconfig-paths": "^3.9.0"
   }

From 2057c05fabdb0924b3bd0bd50c2cf434c7b67f9e Mon Sep 17 00:00:00 2001
From: Kristjan Tammekivi <kristjantammekivi@gmail.com>
Date: Tue, 27 Apr 2021 14:05:15 +0300
Subject: [PATCH 267/767]  [Tests] add passing `no-unused-modules` tests

---
 docs/rules/no-extraneous-dependencies.md      |  2 +-
 .../no-unused-modules/file-destructured-1.js  |  2 ++
 .../no-unused-modules/file-destructured-2.js  |  1 +
 tests/src/rules/no-unused-modules.js          | 29 +++++++++++++++----
 4 files changed, 28 insertions(+), 6 deletions(-)
 create mode 100644 tests/files/no-unused-modules/file-destructured-1.js
 create mode 100644 tests/files/no-unused-modules/file-destructured-2.js

diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index e9743a7619..cdc0a913fe 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -1,7 +1,7 @@
 # import/no-extraneous-dependencies: Forbid the use of extraneous packages
 
 Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`, or `bundledDependencies`.
-The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behaviour can be changed with the rule option `packageDir`.
+The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behavior can be changed with the rule option `packageDir`.
 
 Modules have to be installed for this rule to work.
 
diff --git a/tests/files/no-unused-modules/file-destructured-1.js b/tests/files/no-unused-modules/file-destructured-1.js
new file mode 100644
index 0000000000..f2223ac3b0
--- /dev/null
+++ b/tests/files/no-unused-modules/file-destructured-1.js
@@ -0,0 +1,2 @@
+export const { destructured } = {};
+export const { destructured2 } = {};
diff --git a/tests/files/no-unused-modules/file-destructured-2.js b/tests/files/no-unused-modules/file-destructured-2.js
new file mode 100644
index 0000000000..06dc48a9dc
--- /dev/null
+++ b/tests/files/no-unused-modules/file-destructured-2.js
@@ -0,0 +1 @@
+import { destructured } from './file-destructured-1';
\ No newline at end of file
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index cd054ecb9d..283fa3e984 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -500,7 +500,7 @@ describe('renameDefault', () => {
   });
 });
 
-describe('test behaviour for new file', () => {
+describe('test behavior for new file', () => {
   before(() => {
     fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', { encoding: 'utf8' });
   });
@@ -588,7 +588,7 @@ describe('test behaviour for new file', () => {
   });
 
 
-  describe('test behaviour for new file', () => {
+  describe('test behavior for new file', () => {
     before(() => {
       fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', { encoding: 'utf8' });
     });
@@ -619,7 +619,7 @@ describe('test behaviour for new file', () => {
   });
 });
 
-describe('test behaviour for new file', () => {
+describe('test behavior for new file', () => {
   before(() => {
     fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', { encoding: 'utf8' });
   });
@@ -641,7 +641,7 @@ describe('test behaviour for new file', () => {
   });
 });
 
-describe('test behaviour for new file', () => {
+describe('test behavior for new file', () => {
   before(() => {
     fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', { encoding: 'utf8' });
   });
@@ -663,7 +663,26 @@ describe('test behaviour for new file', () => {
   });
 });
 
-describe('test behaviour for new file', () => {
+describe('test behavior for destructured exports', () => {
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({ options: unusedExportsOptions,
+        code: `import { destructured } from '${testFilePath('./no-unused-modules/file-destructured-1.js')}'`,
+        filename: testFilePath('./no-unused-modules/file-destructured-2.js') }),
+      test({ options: unusedExportsOptions,
+        code: `export const { destructured } = {};`,
+        filename: testFilePath('./no-unused-modules/file-destructured-1.js') }),
+    ],
+    invalid: [
+      test({ options: unusedExportsOptions,
+        code: `export const { destructured2 } = {};`,
+        filename: testFilePath('./no-unused-modules/file-destructured-1.js'),
+        errors: [`exported declaration 'destructured2' not used within other modules`] }),
+    ],
+  });
+});
+
+describe('test behavior for new file', () => {
   before(() => {
     fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', { encoding: 'utf8' });
   });

From 44c7abcdbf105aa9a4e5c4b0c8182d10c5b03507 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 12 May 2021 22:21:47 -0700
Subject: [PATCH 268/767] [utils, resolvers/webpack] [Refactor] use
 `Array.isArray` instead of `instanceof Array`

---
 resolvers/webpack/index.js | 2 +-
 utils/hash.js              | 2 +-
 utils/resolve.js           | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index b1d7e15134..75daa19053 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -329,7 +329,7 @@ function findExternal(source, externals, context) {
   if (typeof externals === 'string') return (source === externals);
 
   // array: recurse
-  if (externals instanceof Array) {
+  if (Array.isArray(externals)) {
     return externals.some(function (e) { return findExternal(source, e, context); });
   }
 
diff --git a/utils/hash.js b/utils/hash.js
index ae7e885b68..fcf00de38c 100644
--- a/utils/hash.js
+++ b/utils/hash.js
@@ -12,7 +12,7 @@ const stringify = JSON.stringify;
 function hashify(value, hash) {
   if (!hash) hash = createHash('sha256');
 
-  if (value instanceof Array) {
+  if (Array.isArray(value)) {
     hashArray(value, hash);
   } else if (value instanceof Object) {
     hashObject(value, hash);
diff --git a/utils/resolve.js b/utils/resolve.js
index 33a755fcd5..ea5bf5a150 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -152,7 +152,7 @@ function fullResolve(modulePath, sourceFile, settings) {
 exports.relative = relative;
 
 function resolverReducer(resolvers, map) {
-  if (resolvers instanceof Array) {
+  if (Array.isArray(resolvers)) {
     resolvers.forEach(r => resolverReducer(r, map));
     return map;
   }

From 7974acc610542f21bd69a3493d1469b2a1fa8464 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 12 May 2021 22:24:42 -0700
Subject: [PATCH 269/767] [resolvers/webpack] [Refactor] use `is-regex` instead
 of `instanceof RegExp`

---
 resolvers/webpack/index.js     | 3 ++-
 resolvers/webpack/package.json | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 75daa19053..710630fdc7 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -11,6 +11,7 @@ const isCore = require('is-core-module');
 const resolve = require('resolve');
 const semver = require('semver');
 const has = require('has');
+const isRegex = require('is-regex');
 
 const log = require('debug')('eslint-plugin-import:resolver:webpack');
 
@@ -333,7 +334,7 @@ function findExternal(source, externals, context) {
     return externals.some(function (e) { return findExternal(source, e, context); });
   }
 
-  if (externals instanceof RegExp) {
+  if (isRegex(externals)) {
     return externals.test(source);
   }
 
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index b26774e2f6..91b96fecf2 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -39,6 +39,7 @@
     "has": "^1.0.3",
     "interpret": "^1.2.0",
     "is-core-module": "^2.0.0",
+    "is-regex": "^1.1.3",
     "lodash": "^4.17.15",
     "resolve": "^1.13.1",
     "semver": "^5.7.1"

From da647d7af71cb153fe248cccd450a00119f2109b Mon Sep 17 00:00:00 2001
From: jet2jet <34238471+jet2jet@users.noreply.github.com>
Date: Sat, 3 Apr 2021 21:32:32 +0900
Subject: [PATCH 270/767] [resolvers/webpack] [New] add support for webpack5
 'externals function'

---
 resolvers/webpack/.eslintrc                   |  3 ++
 resolvers/webpack/CHANGELOG.md                |  9 +++-
 resolvers/webpack/index.js                    | 47 ++++++++++++++++---
 resolvers/webpack/test/externals.js           | 29 ++++++++++++
 ...webpack.config.webpack5.async-externals.js | 21 +++++++++
 .../test/files/webpack.config.webpack5.js     | 27 +++++++++++
 6 files changed, 127 insertions(+), 9 deletions(-)
 create mode 100644 resolvers/webpack/test/files/webpack.config.webpack5.async-externals.js
 create mode 100644 resolvers/webpack/test/files/webpack.config.webpack5.js

diff --git a/resolvers/webpack/.eslintrc b/resolvers/webpack/.eslintrc
index 743d5c949e..544167c4bb 100644
--- a/resolvers/webpack/.eslintrc
+++ b/resolvers/webpack/.eslintrc
@@ -3,4 +3,7 @@
     "import/no-extraneous-dependencies": 1,
     "no-console": 1,
   },
+  "env": {
+    "es6": true,
+  },
 }
diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 8ab56e1a01..6485b171ee 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,8 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Added
+- add support for webpack5 'externals function' ([#2023], thanks [@jet2jet])
+
 ### Changed
- - Add warning about async Webpack configs ([#1962], thanks [@ogonkov])
+- Add warning about async Webpack configs ([#1962], thanks [@ogonkov])
 - Replace node-libs-browser with is-core-module ([#1967], thanks [@andersk])
 
 ## 0.13.0 - 2020-09-27
@@ -141,6 +144,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - `interpret` configs (such as `.babel.js`).
   Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
+[#2023]: https://github.com/benmosher/eslint-plugin-import/pull/2023
 [#1967]: https://github.com/benmosher/eslint-plugin-import/pull/1967
 [#1962]: https://github.com/benmosher/eslint-plugin-import/pull/1962
 [#1705]: https://github.com/benmosher/eslint-plugin-import/pull/1705
@@ -200,4 +204,5 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@migueloller]: https://github.com/migueloller
 [@opichals]: https://github.com/opichals
 [@andersk]: https://github.com/andersk
-[@ogonkov]: https://github.com/ogonkov
\ No newline at end of file
+[@ogonkov]: https://github.com/ogonkov
+[@jet2jet]: https://github.com/jet2jet
\ No newline at end of file
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 710630fdc7..fb03fc4d19 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -140,13 +140,14 @@ exports.resolve = function (source, file, settings) {
 
   log('Using config: ', webpackConfig);
 
+  const resolveSync = getResolveSync(configPath, webpackConfig, cwd);
+
   // externals
-  if (findExternal(source, webpackConfig.externals, path.dirname(file))) {
+  if (findExternal(source, webpackConfig.externals, path.dirname(file), resolveSync)) {
     return { found: true, path: null };
   }
 
   // otherwise, resolve "normally"
-  const resolveSync = getResolveSync(configPath, webpackConfig, cwd);
 
   try {
     return { found: true, path: resolveSync(path.dirname(file), source) };
@@ -323,7 +324,7 @@ function makeRootPlugin(ModulesInRootPlugin, name, root) {
 }
 /* eslint-enable */
 
-function findExternal(source, externals, context) {
+function findExternal(source, externals, context, resolveSync) {
   if (!externals) return false;
 
   // string match
@@ -331,7 +332,7 @@ function findExternal(source, externals, context) {
 
   // array: recurse
   if (Array.isArray(externals)) {
-    return externals.some(function (e) { return findExternal(source, e, context); });
+    return externals.some(function (e) { return findExternal(source, e, context, resolveSync); });
   }
 
   if (isRegex(externals)) {
@@ -340,13 +341,45 @@ function findExternal(source, externals, context) {
 
   if (typeof externals === 'function') {
     let functionExternalFound = false;
-    externals.call(null, context, source, function(err, value) {
+    const callback = function (err, value) {
       if (err) {
         functionExternalFound = false;
       } else {
-        functionExternalFound = findExternal(source, value, context);
+        functionExternalFound = findExternal(source, value, context, resolveSync);
       }
-    });
+    };
+    // - for prior webpack 5, 'externals function' uses 3 arguments
+    // - for webpack 5, the count of arguments is less than 3
+    if (externals.length === 3) {
+      externals.call(null, context, source, callback);
+    } else {
+      const ctx = {
+        context,
+        request: source,
+        contextInfo: {
+          issuer: '',
+          issuerLayer: null,
+          compiler: '',
+        },
+        getResolve: () => (resolveContext, requestToResolve, cb) => {
+          if (cb) {
+            try {
+              cb(null, resolveSync(resolveContext, requestToResolve));
+            } catch (e) {
+              cb(e);
+            }
+          } else {
+            log('getResolve without callback not supported');
+            return Promise.reject(new Error('Not supported'));
+          }
+        },
+      };
+      const result = externals.call(null, ctx, callback);
+      // todo handling Promise object (using synchronous-promise package?)
+      if (result && typeof result.then === 'function') {
+        log('Asynchronous functions for externals not supported');
+      }
+    }
     return functionExternalFound;
   }
 
diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js
index 9cad635241..9c5b001eec 100644
--- a/resolvers/webpack/test/externals.js
+++ b/resolvers/webpack/test/externals.js
@@ -9,6 +9,13 @@ const webpack = require('../index');
 const file = path.join(__dirname, 'files', 'dummy.js');
 
 describe('externals', function () {
+  const settingsWebpack5 = {
+    config: require(path.join(__dirname, './files/webpack.config.webpack5.js')),
+  };
+  const settingsWebpack5Async = {
+    config: require(path.join(__dirname, './files/webpack.config.webpack5.async-externals.js')),
+  };
+
   it('works on just a string', function () {
     const resolved = webpack.resolve('bootstrap', file);
     expect(resolved).to.have.property('found', true);
@@ -32,4 +39,26 @@ describe('externals', function () {
     expect(resolved).to.have.property('found', true);
     expect(resolved).to.have.property('path', null);
   });
+
+  it('works on a function (synchronous) for webpack 5', function () {
+    const resolved = webpack.resolve('underscore', file, settingsWebpack5);
+    expect(resolved).to.have.property('found', true);
+    expect(resolved).to.have.property('path', null);
+  });
+
+  it('works on a function (synchronous) which uses getResolve for webpack 5', function () {
+    const resolved = webpack.resolve('graphql', file, settingsWebpack5);
+    expect(resolved).to.have.property('found', true);
+    expect(resolved).to.have.property('path', null);
+  });
+
+  it('prevents using an asynchronous function for webpack 5', function () {
+    const resolved = webpack.resolve('underscore', file, settingsWebpack5Async);
+    expect(resolved).to.have.property('found', false);
+  });
+
+  it('prevents using a function which uses Promise returned by getResolve for webpack 5', function () {
+    const resolved = webpack.resolve('graphql', file, settingsWebpack5Async);
+    expect(resolved).to.have.property('found', false);
+  });
 });
diff --git a/resolvers/webpack/test/files/webpack.config.webpack5.async-externals.js b/resolvers/webpack/test/files/webpack.config.webpack5.async-externals.js
new file mode 100644
index 0000000000..ba2902b83b
--- /dev/null
+++ b/resolvers/webpack/test/files/webpack.config.webpack5.async-externals.js
@@ -0,0 +1,21 @@
+module.exports = {
+  externals: [
+    { 'jquery': 'jQuery' },
+    'bootstrap',
+    async function ({ request },) {
+      if (request === 'underscore') {
+        return 'underscore'
+      }
+    },
+    function ({ request, getResolve }, callback) {
+      if (request === 'graphql') {
+        const resolve = getResolve()
+        // dummy call (some-module should be resolved on __dirname)
+        resolve(__dirname, 'some-module').then(
+          function () { callback(null, 'graphql') },
+          function (e) { callback(e) }
+        )
+      }
+    },
+  ],
+}
diff --git a/resolvers/webpack/test/files/webpack.config.webpack5.js b/resolvers/webpack/test/files/webpack.config.webpack5.js
new file mode 100644
index 0000000000..88a12567a1
--- /dev/null
+++ b/resolvers/webpack/test/files/webpack.config.webpack5.js
@@ -0,0 +1,27 @@
+module.exports = {
+  externals: [
+    { 'jquery': 'jQuery' },
+    'bootstrap',
+    function ({ request }, callback) {
+      if (request === 'underscore') {
+        return callback(null, 'underscore')
+      }
+      callback()
+    },
+    function ({ request, getResolve }, callback) {
+      if (request === 'graphql') {
+        const resolve = getResolve()
+        // dummy call (some-module should be resolved on __dirname)
+        resolve(__dirname, 'some-module', function (err, value) {
+          if (err) {
+            callback(err)
+          } else {
+            callback(null, 'graphql')
+          }
+        })
+      } else {
+        callback()
+      }
+    },
+  ],
+}

From dfb0f6fc4b585f76aa14e2dbd5bbc4e4b488e86e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 12 May 2021 22:47:09 -0700
Subject: [PATCH 271/767] [resolvers/webpack] [meta] add "engines" field to
 document existing requirements

---
 resolvers/webpack/CHANGELOG.md | 1 +
 resolvers/webpack/package.json | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 6485b171ee..acc4bbfb39 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - Add warning about async Webpack configs ([#1962], thanks [@ogonkov])
 - Replace node-libs-browser with is-core-module ([#1967], thanks [@andersk])
+- [meta] add "engines" field to document existing requirements
 
 ## 0.13.0 - 2020-09-27
 
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 91b96fecf2..3c6b303ebc 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -57,5 +57,8 @@
     "mocha": "^3.5.3",
     "nyc": "^11.9.0",
     "webpack": "https://gist.github.com/ljharb/9cdb687f3806f8e6cb8a365d0b7840eb"
+  },
+  "engines": {
+    "node": "^16 || ^15 || ^14 || ^13 || ^12 || ^11 || ^10 || ^9 || ^8 || ^7 || ^6"
   }
 }

From cf3b7e2174a13dd8744fc22521801c7a1a6032fe Mon Sep 17 00:00:00 2001
From: Silvio <silviogutierrez@gmail.com>
Date: Thu, 18 Feb 2021 18:47:31 -0500
Subject: [PATCH 272/767] [Docs] `order`: Document options required to match
 ordering example

---
 CHANGELOG.md        | 2 ++
 docs/rules/order.md | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 438efefc98..ea766cc340 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
 - [Docs] [`no-named-as-default`]: add semicolon ([#1897], thanks [@bicstone])
 - [Docs] `no-extraneous-dependencies`: correct peerDependencies option default to `true` ([#1993], thanks [@dwardu])
+- [Docs] `order`: Document options required to match ordering example ([#1992], thanks [@silviogutierrez])
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -1355,3 +1356,4 @@ for info on changes for earlier releases.
 [@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w
 [@grit96]: https://github.com/grit96
 [@lilling]: https://github.com/lilling
+[@silviogutierrez]: https://github.com/silviogutierrez
diff --git a/docs/rules/order.md b/docs/rules/order.md
index d760c2c0f5..c2358edc13 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -2,7 +2,8 @@
 
 Enforce a convention in the order of `require()` / `import` statements.
 +(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule.
-The order is as shown in the following example:
+
+With the [`groups`](#groups-array) option set to `["builtin", "external", "internal", "parent", "sibling", "index", "object"]` the order is as shown in the following example:
 
 ```js
 // 1. node "builtin" modules

From dd2f0876070378a04ef65f02d5e224d080f6cb70 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 07:05:42 -0700
Subject: [PATCH 273/767] [actions] use `node/install` instead of `node/run`

---
 .github/workflows/node-4+.yml      |  8 ++++----
 .github/workflows/node-pretest.yml | 13 +++++++------
 .github/workflows/packages.yml     | 13 ++++++++-----
 3 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 6e99312d80..ae2ab7e5cf 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -66,18 +66,18 @@ jobs:
 
     steps:
       - uses: actions/checkout@v2
-      - uses: ljharb/actions/node/run@main
+      - uses: ljharb/actions/node/install@main
         continue-on-error: ${{ matrix.eslint == 4 && matrix.node-version == 4 }}
-        name: 'npm install && npm run tests-only'
+        name: 'nvm install ${{ matrix.node-version }} && npm install, with eslint ${{ matrix.eslint }}'
         env:
           ESLINT_VERSION: ${{ matrix.eslint }}
           TRAVIS_NODE_VERSION: ${{ matrix.node-version }}
         with:
           node-version: ${{ matrix.node-version }}
           after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh
-          command: 'tests-only'
-          after_success: 'npm run coveralls'
           skip-ls-check: true
+      - run: npm run tests-only
+      - run: npm run coveralls
 
   node:
     name: 'node 4+'
diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml
index 2d10481804..cea20ec385 100644
--- a/.github/workflows/node-pretest.yml
+++ b/.github/workflows/node-pretest.yml
@@ -8,20 +8,21 @@ jobs:
 
   #   steps:
   #     - uses: actions/checkout@v2
-  #     - uses: ljharb/actions/node/run@main
-  #       name: 'npm install && npm run pretest'
+  #     - uses: ljharb/actions/node/install@main
+  #       name: 'nvm install lts/* && npm install'
   #       with:
   #         node-version: 'lts/*'
-  #         command: 'pretest'
+  #         skip-ls-check: true
+  #     - run: npm run pretest
 
   posttest:
     runs-on: ubuntu-latest
 
     steps:
       - uses: actions/checkout@v2
-      - uses: ljharb/actions/node/run@main
-        name: 'npm install && npm run posttest'
+      - uses: ljharb/actions/node/install@main
+        name: 'nvm install lts/* && npm install'
         with:
           node-version: 'lts/*'
-          command: 'posttest'
           skip-ls-check: true
+      - run: npm run posttest
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index 6046948c1c..80df39833c 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -22,6 +22,7 @@ jobs:
     runs-on: ubuntu-latest
 
     strategy:
+      fail-fast: false
       matrix:
         node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
         package:
@@ -32,14 +33,16 @@ jobs:
 
     steps:
       - uses: actions/checkout@v2
-      - uses: ljharb/actions/node/run@main
-        name: 'npm install && npm run tests-only'
+      - uses: ljharb/actions/node/install@main
+        name: 'nvm install ${{ matrix.node-version }} && npm install'
+        env:
+          ESLINT_VERSION: ${{ matrix.eslint }}
+          TRAVIS_NODE_VERSION: ${{ matrix.node-version }}
         with:
           node-version: ${{ matrix.node-version }}
-          after_install: npm run copy-metafiles && cd ${{ matrix.package }} && npm install
-          command: 'tests-only'
-          after_success: npm run coveralls
+          after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh && cd ${{ matrix.package }} && npm install
           skip-ls-check: true
+      - run: cd ${{ matrix.package }} && npm run tests-only && npm run coveralls
 
   packages:
     name: 'packages: all tests'

From 9539a5d65614519a497918c86738785a910b815e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 09:10:38 -0700
Subject: [PATCH 274/767] [Tests] temporarily disable node 4 and 5 tests

See #2053
---
 .github/workflows/node-4+.yml  | 2 +-
 .github/workflows/packages.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index ae2ab7e5cf..02c11a0708 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -14,7 +14,7 @@ jobs:
         with:
           versionsAsRoot: true
           type: majors
-          preset: '>=4'
+          preset: '>= 6' # preset: '>=4' # see https://github.com/benmosher/eslint-plugin-import/issues/2053
 
   latest:
     needs: [matrix]
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index 80df39833c..c85e928e82 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -13,7 +13,7 @@ jobs:
         id: set-matrix
         with:
           type: 'majors'
-          preset: '>=4'
+          preset: '>= 6' # preset: '>=4' # see https://github.com/benmosher/eslint-plugin-import/issues/2053
           versionsAsRoot: true
 
   tests:

From 3f9dd99275f4da2ca88c94a9101479bc0a07bfac Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 10:18:30 -0700
Subject: [PATCH 275/767] [Tests] skip coveralls on packages tests

---
 .github/workflows/packages.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index c85e928e82..2add24b49c 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -42,7 +42,7 @@ jobs:
           node-version: ${{ matrix.node-version }}
           after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh && cd ${{ matrix.package }} && npm install
           skip-ls-check: true
-      - run: cd ${{ matrix.package }} && npm run tests-only && npm run coveralls
+      - run: cd ${{ matrix.package }} && npm run tests-only
 
   packages:
     name: 'packages: all tests'

From ab82094f574d54887cbf71877bf828129e8d9d54 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 10:26:45 -0700
Subject: [PATCH 276/767] [Tests] skip webpack 5 `async function` test on node
 <7

---
 resolvers/webpack/test/externals.js | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js
index 9c5b001eec..27dec2033d 100644
--- a/resolvers/webpack/test/externals.js
+++ b/resolvers/webpack/test/externals.js
@@ -3,6 +3,7 @@
 const chai = require('chai');
 const expect = chai.expect;
 const path = require('path');
+const semver = require('semver');
 
 const webpack = require('../index');
 
@@ -12,9 +13,6 @@ describe('externals', function () {
   const settingsWebpack5 = {
     config: require(path.join(__dirname, './files/webpack.config.webpack5.js')),
   };
-  const settingsWebpack5Async = {
-    config: require(path.join(__dirname, './files/webpack.config.webpack5.async-externals.js')),
-  };
 
   it('works on just a string', function () {
     const resolved = webpack.resolve('bootstrap', file);
@@ -52,13 +50,19 @@ describe('externals', function () {
     expect(resolved).to.have.property('path', null);
   });
 
-  it('prevents using an asynchronous function for webpack 5', function () {
-    const resolved = webpack.resolve('underscore', file, settingsWebpack5Async);
-    expect(resolved).to.have.property('found', false);
-  });
+  (semver.satisfies(process.version, '> 6') ? describe : describe.skip)('async function in webpack 5', function () {
+    const settingsWebpack5Async = () => ({
+      config: require(path.join(__dirname, './files/webpack.config.webpack5.async-externals.js')),
+    });
+
+    it('prevents using an asynchronous function for webpack 5', function () {
+      const resolved = webpack.resolve('underscore', file, settingsWebpack5Async());
+      expect(resolved).to.have.property('found', false);
+    });
 
-  it('prevents using a function which uses Promise returned by getResolve for webpack 5', function () {
-    const resolved = webpack.resolve('graphql', file, settingsWebpack5Async);
-    expect(resolved).to.have.property('found', false);
+    it('prevents using a function which uses Promise returned by getResolve for webpack 5', function () {
+      const resolved = webpack.resolve('graphql', file, settingsWebpack5Async());
+      expect(resolved).to.have.property('found', false);
+    });
   });
 });

From 96ed3c7b5da3d0280964d516f970d579209d9fcd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=94=AF=E7=84=B6?= <weiran.zsd@outlook.com>
Date: Mon, 12 Apr 2021 17:36:54 +0800
Subject: [PATCH 277/767] [Fix] `no-unresolved`: check import()

Fixes #2024.

refs: https://github.com/estree/estree/blob/master/es2020.md#importexpression
---
 CHANGELOG.md                     |  3 +++
 tests/src/rules/no-unresolved.js | 20 ++++++++++++++++++--
 utils/moduleVisitor.js           | 14 +++++++++++---
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea766cc340..34bb5fb569 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-extraneous-dependencies`]: Exclude flow `typeof` imports ([#1534], thanks [@devongovett])
 - [`newline-after-import`]: respect decorator annotations ([#1985], thanks [@lilling])
 - [`no-restricted-paths`]: enhance performance for zones with `except` paths ([#2022], thanks [@malykhinvi])
+- [`no-unresolved`]: check import() ([#2026], thanks [@aladdin-add])
 
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
@@ -765,6 +766,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
 [#2022]: https://github.com/benmosher/eslint-plugin-import/pull/2022
 [#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021
 [#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997
@@ -1357,3 +1359,4 @@ for info on changes for earlier releases.
 [@grit96]: https://github.com/grit96
 [@lilling]: https://github.com/lilling
 [@silviogutierrez]: https://github.com/silviogutierrez
+[@aladdin-add]: https://github.com/aladdin-add
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index da7d4dc5ae..518a454cc2 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -1,6 +1,6 @@
 import * as path from 'path';
 
-import { test, SYNTAX_CASES } from '../utils';
+import { test, SYNTAX_CASES, testVersion } from '../utils';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
@@ -93,7 +93,6 @@ function runResolverTests(resolver) {
                             '\'./reallyfake/module\'.' }],
       }),
 
-
       rest({
         code: "import bar from './baz';",
         errors: [{ message: "Unable to resolve path to module './baz'.",
@@ -382,3 +381,20 @@ ruleTester.run('no-unresolved syntax verification', rule, {
   valid: SYNTAX_CASES,
   invalid:[],
 });
+
+// https://github.com/benmosher/eslint-plugin-import/issues/2024
+ruleTester.run('import() with built-in parser', rule, {
+  valid: [].concat(
+    testVersion('>=7', () => ({
+      code: "import('fs');",
+      parserOptions: { ecmaVersion: 2021 },
+    })) || [],
+  ),
+  invalid: [].concat(
+    testVersion('>=7', () => ({
+      code: 'import("./does-not-exist-l0w9ssmcqy9").then(() => {})',
+      parserOptions: { ecmaVersion: 2021 },
+      errors: ["Unable to resolve path to module './does-not-exist-l0w9ssmcqy9'."],
+    })) || [],
+  ),
+});
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index d801515bce..69269985bd 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -36,10 +36,17 @@ exports.default = function visitModules(visitor, options) {
 
   // for esmodule dynamic `import()` calls
   function checkImportCall(node) {
-    if (node.callee.type !== 'Import') return;
-    if (node.arguments.length !== 1) return;
+    let modulePath;
+    // refs https://github.com/estree/estree/blob/master/es2020.md#importexpression
+    if (node.type === 'ImportExpression') {
+      modulePath = node.source;
+    } else if (node.type === 'CallExpression') {
+      if (node.callee.type !== 'Import') return;
+      if (node.arguments.length !== 1) return;
+
+      modulePath = node.arguments[0];
+    }
 
-    const modulePath = node.arguments[0];
     if (modulePath.type !== 'Literal') return;
     if (typeof modulePath.value !== 'string') return;
 
@@ -87,6 +94,7 @@ exports.default = function visitModules(visitor, options) {
       'ExportNamedDeclaration': checkSource,
       'ExportAllDeclaration': checkSource,
       'CallExpression': checkImportCall,
+      'ImportExpression': checkImportCall,
     });
   }
 

From ad2a619c4257f47fc733264c20aed8397d075c80 Mon Sep 17 00:00:00 2001
From: David Bonnet <davidbonnet@users.noreply.github.com>
Date: Wed, 24 Mar 2021 13:44:38 +0100
Subject: [PATCH 278/767] [Tests] `no-unresolved`: add tests for `import()`

---
 CHANGELOG.md                     |  3 +++
 tests/src/rules/no-unresolved.js | 30 +++++++++++++++++++++++-------
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 34bb5fb569..11c2ce82f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Docs] [`no-named-as-default`]: add semicolon ([#1897], thanks [@bicstone])
 - [Docs] `no-extraneous-dependencies`: correct peerDependencies option default to `true` ([#1993], thanks [@dwardu])
 - [Docs] `order`: Document options required to match ordering example ([#1992], thanks [@silviogutierrez])
+- [Tests] `no-unresolved`: add tests for `import()` ([#2012], thanks [@davidbonnet])
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -769,6 +770,7 @@ for info on changes for earlier releases.
 [#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
 [#2022]: https://github.com/benmosher/eslint-plugin-import/pull/2022
 [#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021
+[#2012]: https://github.com/benmosher/eslint-plugin-import/pull/2012
 [#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997
 [#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993
 [#1985]: https://github.com/benmosher/eslint-plugin-import/pull/1985
@@ -1360,3 +1362,4 @@ for info on changes for earlier releases.
 [@lilling]: https://github.com/lilling
 [@silviogutierrez]: https://github.com/silviogutierrez
 [@aladdin-add]: https://github.com/aladdin-add
+[@davidbonnet]: https://github.com/davidbonnet
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 518a454cc2..a3ac4b19b8 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -22,7 +22,7 @@ function runResolverTests(resolver) {
   }
 
   ruleTester.run(`no-unresolved (${resolver})`, rule, {
-    valid: [
+    valid: [].concat(
       test({ code: 'import "./malformed.js"' }),
 
       rest({ code: 'import foo from "./bar";' }),
@@ -32,6 +32,12 @@ function runResolverTests(resolver) {
       rest({ code: "import('fs');",
         parser: require.resolve('babel-eslint') }),
 
+      // check with eslint parser
+      testVersion('>= 7', () => rest({
+        code: "import('fs');",
+        parserOptions: { ecmaVersion: 2021 },
+      })) || [],
+
       rest({ code: 'import * as foo from "a"' }),
 
       rest({ code: 'export { foo } from "./bar"' }),
@@ -83,9 +89,9 @@ function runResolverTests(resolver) {
         options: [{ commonjs: true }] }),
       rest({ code: 'require(foo)',
         options: [{ commonjs: true }] }),
-    ],
+    ),
 
-    invalid: [
+    invalid: [].concat(
       rest({
         code: 'import reallyfake from "./reallyfake/module"',
         settings: { 'import/ignore': ['^\\./fake/'] },
@@ -117,9 +123,9 @@ function runResolverTests(resolver) {
         }] }),
       rest({
         code: "import('in-alternate-root').then(function({DEEP}){});",
-        errors: [{ message: 'Unable to resolve path to ' +
-                          "module 'in-alternate-root'.",
-        type: 'Literal',
+        errors: [{
+          message: 'Unable to resolve path to module \'in-alternate-root\'.',
+          type: 'Literal',
         }],
         parser: require.resolve('babel-eslint') }),
 
@@ -130,6 +136,16 @@ function runResolverTests(resolver) {
         errors: ["Unable to resolve path to module './does-not-exist'."],
       }),
 
+      // check with eslint parser
+      testVersion('>= 7', () => rest({
+        code: "import('in-alternate-root').then(function({DEEP}){});",
+        errors: [{
+          message: 'Unable to resolve path to module \'in-alternate-root\'.',
+          type: 'Literal',
+        }],
+        parserOptions: { ecmaVersion: 2021 },
+      })) || [],
+
       // export symmetry proposal
       rest({ code: 'export * as bar from "./does-not-exist"',
         parser: require.resolve('babel-eslint'),
@@ -186,7 +202,7 @@ function runResolverTests(resolver) {
           type: 'Literal',
         }],
       }),
-    ],
+    ),
   });
 
   ruleTester.run(`issue #333 (${resolver})`, rule, {

From a943fd0a259070c7638d9a3d12d250bacb7b57b1 Mon Sep 17 00:00:00 2001
From: Michael Hayes <michael.hayes@thetradedesk.com>
Date: Fri, 12 Feb 2021 12:40:41 -0800
Subject: [PATCH 279/767] [New] `order`: Add `warnOnUnassignedImports` option
 to enable warnings for out of order unassigned imports

Fixes #1639
---
 CHANGELOG.md             |   3 ++
 docs/rules/order.md      |  27 +++++++++++
 src/rules/order.js       |  11 +++--
 tests/src/rules/order.js | 102 +++++++++++++++++++++++++++++++++++++--
 4 files changed, 136 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 11c2ce82f1..645018580b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - add [`no-import-module-exports`] rule: report import declarations with CommonJS exports ([#804], thanks [@kentcdodds] and [@ttmarek])
 - [`no-unused-modules`]: Support destructuring assignment for `export`. ([#1997], thanks [@s-h-a-d-o-w])
 - [`order`]: support type imports ([#2021], thanks [@grit96])
+- [`order`]: Add `warnOnUnassignedImports` option to enable warnings for out of order unassigned imports ([#1990], thanks [@hayes])
 
 ### Fixed
 - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella])
@@ -773,6 +774,7 @@ for info on changes for earlier releases.
 [#2012]: https://github.com/benmosher/eslint-plugin-import/pull/2012
 [#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997
 [#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993
+[#1990]: https://github.com/benmosher/eslint-plugin-import/pull/1990
 [#1985]: https://github.com/benmosher/eslint-plugin-import/pull/1985
 [#1983]: https://github.com/benmosher/eslint-plugin-import/pull/1983
 [#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
@@ -1363,3 +1365,4 @@ for info on changes for earlier releases.
 [@silviogutierrez]: https://github.com/silviogutierrez
 [@aladdin-add]: https://github.com/aladdin-add
 [@davidbonnet]: https://github.com/davidbonnet
+[@hayes]: https://github.com/hayes
diff --git a/docs/rules/order.md b/docs/rules/order.md
index c2358edc13..848c91ddef 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -256,6 +256,33 @@ import React, { PureComponent } from 'react';
 import { compose, apply } from 'xcompose';
 ```
 
+### `warnOnUnassignedImports: true|false`:
+
+* default: `false`
+
+Warns when unassigned imports are out of order.  These warning will not be fixed
+with `--fix` because unassigned imports are used for side-effects and changing the
+import of order of modules with side effects can not be done automatically in a
+way that is safe.
+
+This will fail the rule check:
+
+```js
+/* eslint import/order: ["error", {"warnOnUnassignedImports": true}] */
+import fs from 'fs';
+import './styles.css';
+import path from 'path';
+```
+
+While this will pass:
+
+```js
+/* eslint import/order: ["error", {"warnOnUnassignedImports": true}] */
+import fs from 'fs';
+import path from 'path';
+import './styles.css';
+```
+
 ## Related
 
 - [`import/external-module-folders`] setting
diff --git a/src/rules/order.js b/src/rules/order.js
index 3aabbc74c7..34cc992e8e 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -339,7 +339,7 @@ function isModuleLevelRequire(node) {
   let n = node;
   // Handle cases like `const baz = require('foo').bar.baz`
   // and `const foo = require('foo')()`
-  while ( 
+  while (
     (n.parent.type === 'MemberExpression' && n.parent.object === n) ||
     (n.parent.type === 'CallExpression' && n.parent.callee === n)
   ) {
@@ -348,7 +348,7 @@ function isModuleLevelRequire(node) {
   return (
     n.parent.type === 'VariableDeclarator' &&
     n.parent.parent.type === 'VariableDeclaration' &&
-    n.parent.parent.parent.type === 'Program' 
+    n.parent.parent.parent.type === 'Program'
   );
 }
 
@@ -568,6 +568,10 @@ module.exports = {
             },
             additionalProperties: false,
           },
+          warnOnUnassignedImports: {
+            type: 'boolean',
+            default: false,
+          },
         },
         additionalProperties: false,
       },
@@ -600,7 +604,8 @@ module.exports = {
 
     return {
       ImportDeclaration: function handleImports(node) {
-        if (node.specifiers.length) { // Ignoring unassigned imports
+        // Ignoring unassigned imports unless warnOnUnassignedImports is set
+        if (node.specifiers.length || options.warnOnUnassignedImports) {
           const name = node.source.value;
           registerNode(
             context,
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 4fcbb29d73..9b4103127a 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -854,10 +854,10 @@ ruleTester.run('order', rule, {
     test({
       code:
         `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n` +
-        `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n`,      
+        `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n`,
       output:
         `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n` +
-        `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n`,      
+        `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n`,
       errors: [{
         message: '`fs` import should occur before import of `async`',
       }],
@@ -1530,7 +1530,8 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
-    // Option newlines-between: 'never' cannot fix if there are other statements between imports
+    // Option newlines-between: 'never' with unassigned imports and warnOnUnassignedImports disabled
+    // newline is preserved to match existing behavior
     test({
       code: `
         import path from 'path';
@@ -1546,6 +1547,53 @@ ruleTester.run('order', rule, {
         import 'something-else';
         import _ from 'lodash';
       `,
+      options: [{ 'newlines-between': 'never', warnOnUnassignedImports: false }],
+      errors: [
+        {
+          line: 2,
+          message: 'There should be no empty line between import groups',
+        },
+      ],
+    }),
+    // Option newlines-between: 'never' with unassigned imports and warnOnUnassignedImports enabled
+    test({
+      code: `
+        import path from 'path';
+        import 'loud-rejection';
+
+        import 'something-else';
+        import _ from 'lodash';
+      `,
+      output: `
+        import path from 'path';
+        import 'loud-rejection';
+        import 'something-else';
+        import _ from 'lodash';
+      `,
+      options: [{ 'newlines-between': 'never', warnOnUnassignedImports: true }],
+      errors: [
+        {
+          line: 3,
+          message: 'There should be no empty line between import groups',
+        },
+      ],
+    }),
+    // Option newlines-between: 'never' cannot fix if there are other statements between imports
+    test({
+      code: `
+        import path from 'path';
+        export const abc = 123;
+
+        import 'something-else';
+        import _ from 'lodash';
+      `,
+      output: `
+        import path from 'path';
+        export const abc = 123;
+
+        import 'something-else';
+        import _ from 'lodash';
+      `,
       options: [{ 'newlines-between': 'never' }],
       errors: [
         {
@@ -1764,7 +1812,6 @@ ruleTester.run('order', rule, {
         '`./local2` import should occur after import of `global4`',
       ],
     }),
-
     // pathGroup with position 'after'
     test({
       code: `
@@ -2309,6 +2356,53 @@ context('TypeScript', function () {
             },
             parserConfig,
           ),
+          // warns for out of order unassigned imports (warnOnUnassignedImports enabled)
+          test({
+            code: `
+              import './local1';
+              import global from 'global1';
+              import local from './local2';
+              import 'global2';
+            `,
+            output: `
+              import './local1';
+              import global from 'global1';
+              import local from './local2';
+              import 'global2';
+            `,
+            errors: [
+              {
+                message: '`global1` import should occur before import of `./local1`',
+              },
+              {
+                message: '`global2` import should occur before import of `./local1`',
+              },
+            ],
+            options: [{ warnOnUnassignedImports: true }],
+          }),
+          // fix cannot move below unassigned import (warnOnUnassignedImports enabled)
+          test({
+            code: `
+              import local from './local';
+
+              import 'global1';
+
+              import global2 from 'global2';
+              import global3 from 'global3';
+            `,
+            output: `
+              import local from './local';
+
+              import 'global1';
+
+              import global2 from 'global2';
+              import global3 from 'global3';
+            `,
+            errors: [{
+              message: '`./local` import should occur after import of `global3`',
+            }],
+            options: [{ warnOnUnassignedImports: true }],
+          }),
         ],
       });
     });

From 7c1e8e4818f1adc2bca1f84e05d78e2b5e274678 Mon Sep 17 00:00:00 2001
From: Erik Demaine <edemaine@mit.edu>
Date: Sun, 25 Apr 2021 09:40:01 -0400
Subject: [PATCH 280/767] [Docs] Add import/recommended ruleset to README

Fixes #2032
---
 CHANGELOG.md | 3 +++
 README.md    | 5 +++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 645018580b..4c6740ef48 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -38,6 +38,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Docs] `no-extraneous-dependencies`: correct peerDependencies option default to `true` ([#1993], thanks [@dwardu])
 - [Docs] `order`: Document options required to match ordering example ([#1992], thanks [@silviogutierrez])
 - [Tests] `no-unresolved`: add tests for `import()` ([#2012], thanks [@davidbonnet])
+- [Docs] Add import/recommended ruleset to README ([#2034], thanks [@edemaine])
 
 ## [2.22.1] - 2020-09-27
 ### Fixed
@@ -768,6 +769,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2034]: https://github.com/benmosher/eslint-plugin-import/pull/2034
 [#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
 [#2022]: https://github.com/benmosher/eslint-plugin-import/pull/2022
 [#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021
@@ -1366,3 +1368,4 @@ for info on changes for earlier releases.
 [@aladdin-add]: https://github.com/aladdin-add
 [@davidbonnet]: https://github.com/davidbonnet
 [@hayes]: https://github.com/hayes
+[@edemaine]: https://github.com/edemaine
\ No newline at end of file
diff --git a/README.md b/README.md
index 7945546a6c..8ee4dedd4b 100644
--- a/README.md
+++ b/README.md
@@ -138,6 +138,8 @@ in your `.eslintrc.(yml|json|js)`, or extend one of the canned configs:
 ---
 extends:
   - eslint:recommended
+  - plugin:import/recommended
+  # alternatively, 'recommended' is the combination of these two rule sets:
   - plugin:import/errors
   - plugin:import/warnings
 
@@ -163,8 +165,7 @@ Make sure you have installed [`@typescript-eslint/parser`] which is used in the
 ```yaml
 extends:
   - eslint:recommended
-  - plugin:import/errors
-  - plugin:import/warnings
+  - plugin:import/recommended
   - plugin:import/typescript # this line does the trick
 ```
 

From 5eb0dcac619b33e2058797eb3c823c23b5a185ce Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 22:44:50 -0700
Subject: [PATCH 281/767] [utils] [deps] update `debug`

---
 utils/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/utils/package.json b/utils/package.json
index 6e8ebddfb9..5a50146202 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -26,7 +26,7 @@
   },
   "homepage": "https://github.com/benmosher/eslint-plugin-import#readme",
   "dependencies": {
-    "debug": "^2.6.9",
+    "debug": "^3.2.7",
     "pkg-dir": "^2.0.0"
   }
 }

From 36407c46e46c48922f878d9bbeb7fcba6cffe17c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 22:45:31 -0700
Subject: [PATCH 282/767] [resolvers/node] [deps] update `debug`, `resolve`

---
 resolvers/node/package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 5de34c49d6..3d108f9aaf 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -30,8 +30,8 @@
   },
   "homepage": "https://github.com/benmosher/eslint-plugin-import",
   "dependencies": {
-    "debug": "^2.6.9",
-    "resolve": "^1.13.1"
+    "debug": "^3.2.7",
+    "resolve": "^1.20.0"
   },
   "devDependencies": {
     "chai": "^3.5.0",

From be24ab8a389780bc3cef301a091718cef77fba32 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 22:46:43 -0700
Subject: [PATCH 283/767] [resolvers/*] [dev deps] update `coveralls`

---
 resolvers/node/package.json    | 2 +-
 resolvers/webpack/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 3d108f9aaf..336e8fb0e9 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -35,7 +35,7 @@
   },
   "devDependencies": {
     "chai": "^3.5.0",
-    "coveralls": "^3.0.0",
+    "coveralls": "^3.1.0",
     "mocha": "^3.5.3",
     "nyc": "^11.9.0"
   }
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 3c6b303ebc..3f48567733 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -53,7 +53,7 @@
     "babel-preset-es2015-argon": "latest",
     "babel-register": "^6.26.0",
     "chai": "^3.5.0",
-    "coveralls": "^3.0.0",
+    "coveralls": "^3.1.0",
     "mocha": "^3.5.3",
     "nyc": "^11.9.0",
     "webpack": "https://gist.github.com/ljharb/9cdb687f3806f8e6cb8a365d0b7840eb"

From 4d47169da45a3fa8e1a9bc4069e70ede2c485651 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 22:48:05 -0700
Subject: [PATCH 284/767] [resolvers/webpack] [deps] update `debug`,
 `interpret`, `is-core-module`, `lodash`, `resolve`

---
 resolvers/webpack/package.json | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 3f48567733..b2632dfe26 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -33,15 +33,15 @@
   "homepage": "https://github.com/benmosher/eslint-plugin-import/tree/master/resolvers/webpack",
   "dependencies": {
     "array-find": "^1.0.0",
-    "debug": "^2.6.9",
+    "debug": "^3.2.7",
     "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",
     "has": "^1.0.3",
-    "interpret": "^1.2.0",
-    "is-core-module": "^2.0.0",
+    "interpret": "^1.4.0",
+    "is-core-module": "^2.4.0",
     "is-regex": "^1.1.3",
-    "lodash": "^4.17.15",
-    "resolve": "^1.13.1",
+    "lodash": "^4.17.21",
+    "resolve": "^1.20.0",
     "semver": "^5.7.1"
   },
   "peerDependencies": {

From 6417cfd8109e2c6926691ab507cd84ab100e2d19 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 23:00:53 -0700
Subject: [PATCH 285/767] utils: v2.6.1

---
 utils/CHANGELOG.md | 16 +++++++++++++++-
 utils/package.json |  2 +-
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index f337d3850a..949fa8d582 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,10 +5,20 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v2.6.1 - 2021-05-13
+
+### Fixed
+- `no-unresolved`: check `import()` ([#2026], thanks [@aladdin-add])
+- Add fix for Windows Subsystem for Linux ([#1786], thanks [@manuth])
+
+### Changed
+- [deps] update `debug`
+- [Refactor] use `Array.isArray` instead of `instanceof Array`
+
 ## v2.6.0 - 2020-03-28
 
 ### Added
-[New] Print more helpful info if parsing fails ([#1671], thanks [@kaiyoma])
+- Print more helpful info if parsing fails ([#1671], thanks [@kaiyoma])
 
 ## v2.5.2 - 2020-01-12
 
@@ -75,6 +85,8 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
+[#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
 [#1671]: https://github.com/benmosher/eslint-plugin-import/pull/1671
 [#1606]: https://github.com/benmosher/eslint-plugin-import/pull/1606
 [#1602]: https://github.com/benmosher/eslint-plugin-import/pull/1602
@@ -101,3 +113,5 @@ Yanked due to critical issue with cache key resulting from #839.
 [@sompylasar]: https://github.com/sompylasar
 [@iamnapo]: https://github.com/iamnapo
 [@kaiyoma]: https://github.com/kaiyoma
+[@manuth]: https://github.com/manuth
+[@aladdin-add]: https://github.com/aladdin-add
\ No newline at end of file
diff --git a/utils/package.json b/utils/package.json
index 5a50146202..2ec00e60a4 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.6.0",
+  "version": "2.6.1",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From aa379047ed339875e7756e0c1c8dae7ac50d214c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 23:02:22 -0700
Subject: [PATCH 286/767] [deps] update `eslint-module-utils`

---
 memo-parser/package.json | 2 +-
 package.json             | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/memo-parser/package.json b/memo-parser/package.json
index 69996d33eb..9aa7647b8d 100644
--- a/memo-parser/package.json
+++ b/memo-parser/package.json
@@ -29,6 +29,6 @@
     "eslint": ">=3.5.0"
   },
   "dependencies": {
-    "eslint-module-utils": "^2.5.0"
+    "eslint-module-utils": "^2.6.1"
   }
 }
diff --git a/package.json b/package.json
index 6f02ab8a52..f104ee3fdd 100644
--- a/package.json
+++ b/package.json
@@ -103,7 +103,7 @@
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.4",
-    "eslint-module-utils": "^2.6.0",
+    "eslint-module-utils": "^2.6.1",
     "find-up": "^2.0.0",
     "has": "^1.0.3",
     "is-core-module": "^2.4.0",

From 7b264c0547a007e33d6242531c73799c4f3b782c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 23:04:47 -0700
Subject: [PATCH 287/767] [resolvers/webpack] v0.13.1

---
 resolvers/webpack/CHANGELOG.md | 7 ++++++-
 resolvers/webpack/package.json | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index acc4bbfb39..edc67627ff 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,13 +5,18 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## 0.13.1 - 2021-05-13
+
 ### Added
 - add support for webpack5 'externals function' ([#2023], thanks [@jet2jet])
 
 ### Changed
 - Add warning about async Webpack configs ([#1962], thanks [@ogonkov])
-- Replace node-libs-browser with is-core-module ([#1967], thanks [@andersk])
+- Replace `node-libs-browser` with `is-core-module` ([#1967], thanks [@andersk])
 - [meta] add "engines" field to document existing requirements
+- [Refactor] use `is-regex` instead of `instanceof RegExp`
+- [Refactor] use `Array.isArray` instead of `instanceof Array`
+- [deps] update `debug`, `interpret`, `is-core-module`, `lodash`, `resolve`
 
 ## 0.13.0 - 2020-09-27
 
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index b2632dfe26..fc8c42e6da 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.0",
+  "version": "0.13.1",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From e9e755d085111004db2e3a79f2812484f5c0cf4e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 May 2021 23:06:13 -0700
Subject: [PATCH 288/767] Bump to v2.23.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c6740ef48..766516416d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.23.0] - 2021-05-13
+
 ### Added
 - [`no-commonjs`]: Also detect require calls with expressionless template literals: ``` require(`x`) ``` ([#1958], thanks [@FloEdelmann])
 - [`no-internal-modules`]: Add `forbid` option ([#1846], thanks [@guillaumewuip])
@@ -1104,7 +1106,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.1...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.0...HEAD
+[2.23.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.1...v2.23.0
 [2.22.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.0...v2.22.1
 [2.22.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.22.0
 [2.21.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.21.2
diff --git a/package.json b/package.json
index f104ee3fdd..7f0a4f0005 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.22.1",
+  "version": "2.23.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 8d7ec179c2ba2672d4d06200166ab64e1821527c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 May 2021 09:12:21 -0700
Subject: [PATCH 289/767] [Fix] `newline-after-import`: fix crash with `export
 {}` syntax

Fixes #2063. Fixes #2065.
---
 CHANGELOG.md                            |  5 +++++
 src/rules/newline-after-import.js       |  3 ++-
 tests/src/rules/newline-after-import.js | 21 +++++++++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 766516416d..a21c4f3eac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`newline-after-import`]: fix crash with `export {}` syntax ([#2063], [#2065], thanks [@ljharb])
+
 ## [2.23.0] - 2021-05-13
 
 ### Added
@@ -1003,6 +1006,8 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
+[#2065]: https://github.com/benmosher/eslint-plugin-import/issues/2065
+[#2063]: https://github.com/benmosher/eslint-plugin-import/issues/2063
 [#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
 [#1924]: https://github.com/benmosher/eslint-plugin-import/issues/1924
 [#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 935572aa47..f9a817846b 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -48,7 +48,8 @@ function isExportDefaultClass(node) {
 }
 
 function isExportNameClass(node) {
-  return node.type === 'ExportNamedDeclaration' && node.declaration.type === 'ClassDeclaration';
+  
+  return node.type === 'ExportNamedDeclaration' && node.declaration && node.declaration.type === 'ClassDeclaration';
 }
 
 module.exports = {
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index a01bfead60..867a648575 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -231,7 +231,28 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         parser: parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
+      {
+        code: `
+          import stub from './stub';
+
+          export {
+              stub
+          }
+        `,
+        parser: parser,
+        parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      },
     ]),
+    {
+      code: `
+        import stub from './stub';
+
+        export {
+            stub
+        }
+      `,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
   ],
 
   invalid: [].concat(

From dd0e8cbcb489c1c0f111444627c4db5b3dfd5bed Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 May 2021 09:14:39 -0700
Subject: [PATCH 290/767] [meta] correct #2065 -> #2056

---
 CHANGELOG.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a21c4f3eac..454d55e62c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 
 ### Fixed
-- [`newline-after-import`]: fix crash with `export {}` syntax ([#2063], [#2065], thanks [@ljharb])
+- [`newline-after-import`]: fix crash with `export {}` syntax ([#2063], [#2056], thanks [@ljharb])
 
 ## [2.23.0] - 2021-05-13
 
@@ -1006,7 +1006,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
-[#2065]: https://github.com/benmosher/eslint-plugin-import/issues/2065
+[#2056]: https://github.com/benmosher/eslint-plugin-import/issues/2056
 [#2063]: https://github.com/benmosher/eslint-plugin-import/issues/2063
 [#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
 [#1924]: https://github.com/benmosher/eslint-plugin-import/issues/1924

From d903477f4e31be71e016f8af56cbe2a8d4f11c9c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 May 2021 11:24:13 -0700
Subject: [PATCH 291/767] [Fix] ExportMap: do not crash when tsconfig lacks
 `.compilerOptions`

Fixes #2067
---
 CHANGELOG.md               |  2 ++
 src/ExportMap.js           |  2 +-
 tests/src/rules/default.js | 20 ++++++++++++++++++++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 454d55e62c..44ab437d4f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`newline-after-import`]: fix crash with `export {}` syntax ([#2063], [#2056], thanks [@ljharb])
+- `ExportMap`: do not crash when tsconfig lacks `.compilerOptions` ([#2067], thanks [@ljharb])
 
 ## [2.23.0] - 2021-05-13
 
@@ -1006,6 +1007,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
+[#2067]: https://github.com/benmosher/eslint-plugin-import/issues/2067
 [#2056]: https://github.com/benmosher/eslint-plugin-import/issues/2056
 [#2063]: https://github.com/benmosher/eslint-plugin-import/issues/2063
 [#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 215f3de716..9cc7a089e1 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -472,7 +472,7 @@ ExportMap.parse = function (path, content, context) {
       tsConfigCache.set(cacheKey, tsConfig);
     }
 
-    return tsConfig !== null ? tsConfig.compilerOptions.esModuleInterop : false;
+    return tsConfig && tsConfig.compilerOptions ? tsConfig.compilerOptions.esModuleInterop : false;
   }
 
   ast.body.forEach(function (n) {
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index 7ff6549725..c7eb780d00 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -258,6 +258,26 @@ context('TypeScript', function () {
           },
           errors: ['No default export found in imported module "./typescript-export-as-default-namespace".'],
         }),
+        test({
+          code: `import Foo from "./typescript-export-as-default-namespace"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+          parserOptions: {
+            tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-no-compiler-options/'),
+          },
+          errors: [
+            {
+              message: 'No default export found in imported module "./typescript-export-as-default-namespace".',
+              line: 1,
+              column: 8,
+              endLine: 1,
+              endColumn: 11,
+            },
+          ],
+        }),
       ],
     });
   });

From 821354381f3e1108bca7670cb8d84a95769d035b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 May 2021 11:32:50 -0700
Subject: [PATCH 292/767] [Tests] add missing fixture from
 d903477f4e31be71e016f8af56cbe2a8d4f11c9c

---
 tests/files/typescript-no-compiler-options/index.d.ts    | 3 +++
 tests/files/typescript-no-compiler-options/tsconfig.json | 2 ++
 2 files changed, 5 insertions(+)
 create mode 100644 tests/files/typescript-no-compiler-options/index.d.ts
 create mode 100644 tests/files/typescript-no-compiler-options/tsconfig.json

diff --git a/tests/files/typescript-no-compiler-options/index.d.ts b/tests/files/typescript-no-compiler-options/index.d.ts
new file mode 100644
index 0000000000..953c3410b1
--- /dev/null
+++ b/tests/files/typescript-no-compiler-options/index.d.ts
@@ -0,0 +1,3 @@
+export as namespace Foo
+
+export function bar(): void
diff --git a/tests/files/typescript-no-compiler-options/tsconfig.json b/tests/files/typescript-no-compiler-options/tsconfig.json
new file mode 100644
index 0000000000..2c63c08510
--- /dev/null
+++ b/tests/files/typescript-no-compiler-options/tsconfig.json
@@ -0,0 +1,2 @@
+{
+}

From 83f3c3eca60169ace2609c05506fe1ad37029bbe Mon Sep 17 00:00:00 2001
From: Geraint White <geraintwhite@gmail.com>
Date: Fri, 14 May 2021 21:04:02 +0000
Subject: [PATCH 293/767] [Fix] `order`: fix alphabetical sorting

Fixes #2064. See #2065.
---
 CHANGELOG.md             |  2 ++
 src/rules/order.js       | 13 ++++++++-----
 tests/src/rules/order.js | 29 +++++++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44ab437d4f..5ec3252b27 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`newline-after-import`]: fix crash with `export {}` syntax ([#2063], [#2056], thanks [@ljharb])
 - `ExportMap`: do not crash when tsconfig lacks `.compilerOptions` ([#2067], thanks [@ljharb])
+- [`order`]: fix alphabetical sorting ([#2071], thanks [@grit96])
 
 ## [2.23.0] - 2021-05-13
 
@@ -775,6 +776,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2071]: https://github.com/benmosher/eslint-plugin-import/pull/2071
 [#2034]: https://github.com/benmosher/eslint-plugin-import/pull/2034
 [#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
 [#2022]: https://github.com/benmosher/eslint-plugin-import/pull/2022
diff --git a/src/rules/order.js b/src/rules/order.js
index 34cc992e8e..515c089f7f 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -265,14 +265,17 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
     if (!Array.isArray(acc[importedItem.rank])) {
       acc[importedItem.rank] = [];
     }
-    acc[importedItem.rank].push(`${importedItem.value}-${importedItem.node.importKind}`);
+    acc[importedItem.rank].push(importedItem);
     return acc;
   }, {});
 
   const groupRanks = Object.keys(groupedByRanks);
 
   const sorterFn = getSorter(alphabetizeOptions.order === 'asc');
-  const comparator = alphabetizeOptions.caseInsensitive ? (a, b) => sorterFn(String(a).toLowerCase(), String(b).toLowerCase()) : (a, b) => sorterFn(a, b);
+  const comparator = alphabetizeOptions.caseInsensitive
+    ? (a, b) => sorterFn(String(a.value).toLowerCase(), String(b.value).toLowerCase())
+    : (a, b) => sorterFn(a.value, b.value);
+
   // sort imports locally within their group
   groupRanks.forEach(function(groupRank) {
     groupedByRanks[groupRank].sort(comparator);
@@ -281,8 +284,8 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
   // assign globally unique rank to each import
   let newRank = 0;
   const alphabetizedRanks = groupRanks.sort().reduce(function(acc, groupRank) {
-    groupedByRanks[groupRank].forEach(function(importedItemName) {
-      acc[importedItemName] = parseInt(groupRank, 10) + newRank;
+    groupedByRanks[groupRank].forEach(function(importedItem) {
+      acc[`${importedItem.value}|${importedItem.node.importKind}`] = parseInt(groupRank, 10) + newRank;
       newRank += 1;
     });
     return acc;
@@ -290,7 +293,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
 
   // mutate the original group-rank with alphabetized-rank
   imported.forEach(function(importedItem) {
-    importedItem.rank = alphabetizedRanks[`${importedItem.value}-${importedItem.node.importKind}`];
+    importedItem.rank = alphabetizedRanks[`${importedItem.value}|${importedItem.node.importKind}`];
   });
 }
 
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 9b4103127a..f621c811d6 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -706,6 +706,20 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    // Order of imports with similar names
+    test({
+      code: `
+        import React from 'react';
+        import { BrowserRouter } from 'react-router-dom';
+      `,
+      options: [
+        {
+          alphabetize: {
+            order: 'asc',
+          },
+        },
+      ],
+    }),
     ...flatMap(getTSParsers, parser => [
       // Order of the `import ... = require(...)` syntax
       test({
@@ -2274,6 +2288,21 @@ context('TypeScript', function () {
             },
             parserConfig,
           ),
+          test(
+            {
+              code: `
+                import { Partner } from '@models/partner/partner';
+                import { PartnerId } from '@models/partner/partner-id';
+              `,
+              parser,
+              options: [
+                {
+                  alphabetize: { order: 'asc' },
+                },
+              ],
+            },
+            parserConfig,
+          ),
         ],
         invalid: [
           // Option alphabetize: {order: 'asc'}

From 8431b46a8bfe1c5498937a57fe9a35dbcca0c71c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 May 2021 20:29:46 -0700
Subject: [PATCH 294/767] Bump to v2.23.1

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ec3252b27..7572309ca8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.23.0] - 2021-05-14
+
 ### Fixed
 - [`newline-after-import`]: fix crash with `export {}` syntax ([#2063], [#2056], thanks [@ljharb])
 - `ExportMap`: do not crash when tsconfig lacks `.compilerOptions` ([#2067], thanks [@ljharb])
@@ -1115,7 +1117,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.0...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.1...HEAD
+[2.23.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.0...v2.23.1
 [2.23.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.1...v2.23.0
 [2.22.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.0...v2.22.1
 [2.22.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.22.0
diff --git a/package.json b/package.json
index 7f0a4f0005..4ba95f4592 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.23.0",
+  "version": "2.23.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 5af181f13ffa421382641e92e56f0daba0de4218 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 15 May 2021 08:43:05 -0700
Subject: [PATCH 295/767] [meta] add `safe-publish-latest`; use
 `prepublishOnly` script for npm 7+

---
 package.json | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 4ba95f4592..42411d0977 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,8 @@
     "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
     "test-all": "node --require babel-register ./scripts/testAll",
-    "prepublish": "not-in-publish || npm run build",
+    "prepublishOnly": "safe-publish-latest && npm run build",
+    "prepublish": "not-in-publish || npm run prepublishOnly",
     "coveralls": "nyc report --reporter lcovonly && coveralls < ./coverage/lcov.info"
   },
   "repository": {
@@ -88,6 +89,7 @@
     "nyc": "^11.9.0",
     "redux": "^3.7.2",
     "rimraf": "^2.7.1",
+    "safe-publish-latest": "^1.1.4",
     "semver": "^6.3.0",
     "sinon": "^2.4.1",
     "typescript": "^2.8.1 || ~3.9.5",

From a332f20fa2a58baafc0e41b5bec91bd5f68d25ba Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 15 May 2021 09:05:24 -0700
Subject: [PATCH 296/767] Bump to v2.23.2

---
 CHANGELOG.md | 14 ++++++++++----
 package.json |  2 +-
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7572309ca8..826e5c4a54 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,12 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
-## [2.23.0] - 2021-05-14
+## [2.23.2] - 2021-05-15
+
+### Changed
+- [meta] add `safe-publish-latest`; use `prepublishOnly` script for npm 7+
+
+## [2.23.1] - 2021-05-14
 
 ### Fixed
 - [`newline-after-import`]: fix crash with `export {}` syntax ([#2063], [#2056], thanks [@ljharb])
@@ -1117,8 +1122,9 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.1...HEAD
-[2.23.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.0...v2.23.1
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.2...HEAD
+[2.23.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.1...v2.23.2
+[2.23.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.0...v2.23.1
 [2.23.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.1...v2.23.0
 [2.22.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.0...v2.22.1
 [2.22.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.22.0
@@ -1383,4 +1389,4 @@ for info on changes for earlier releases.
 [@aladdin-add]: https://github.com/aladdin-add
 [@davidbonnet]: https://github.com/davidbonnet
 [@hayes]: https://github.com/hayes
-[@edemaine]: https://github.com/edemaine
\ No newline at end of file
+[@edemaine]: https://github.com/edemaine
diff --git a/package.json b/package.json
index 42411d0977..a1712e2b12 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.23.1",
+  "version": "2.23.2",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From bc99b86123d0ecd289dcf25f6d0e3772620059fa Mon Sep 17 00:00:00 2001
From: Nikolay Stoynov <arvigeus@gmail.com>
Date: Sat, 15 May 2021 12:02:15 +0300
Subject: [PATCH 297/767] [Docs] Add `no-relative-packages` to list of to the
 list of rules

---
 CHANGELOG.md | 4 ++++
 README.md    | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 826e5c4a54..7ad8bab491 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Changed
+- [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])
+
 ## [2.23.2] - 2021-05-15
 
 ### Changed
@@ -783,6 +786,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2075]: https://github.com/benmosher/eslint-plugin-import/pull/2075
 [#2071]: https://github.com/benmosher/eslint-plugin-import/pull/2071
 [#2034]: https://github.com/benmosher/eslint-plugin-import/pull/2034
 [#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
diff --git a/README.md b/README.md
index 8ee4dedd4b..d7d50eaf51 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 * Forbid a module from importing a module with a dependency path back to itself ([`no-cycle`])
 * Prevent unnecessary path segments in import and require statements ([`no-useless-path-segments`])
 * Forbid importing modules from parent directories ([`no-relative-parent-imports`])
+* Prevent importing packages through relative paths ([`no-relative-packages`])
 
 [`no-unresolved`]: ./docs/rules/no-unresolved.md
 [`named`]: ./docs/rules/named.md
@@ -41,6 +42,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 [`no-cycle`]: ./docs/rules/no-cycle.md
 [`no-useless-path-segments`]: ./docs/rules/no-useless-path-segments.md
 [`no-relative-parent-imports`]: ./docs/rules/no-relative-parent-imports.md
+[`no-relative-packages`]: ./docs/rules/no-relative-packages.md
 
 ### Helpful warnings
 

From ddb21327a01b3f5781600b4d9e9933c706aaeab2 Mon Sep 17 00:00:00 2001
From: Vasily Malykhin <malykhinvi@gmail.com>
Date: Tue, 18 May 2021 14:55:15 +0300
Subject: [PATCH 298/767] [Fix] `no-restricted-paths`: fix false positive
 matches

Fixes #2089
---
 CHANGELOG.md                                     |  5 ++++-
 package.json                                     |  1 -
 src/rules/no-restricted-paths.js                 |  6 +++++-
 tests/files/restricted-paths/server/two-new/a.js |  0
 tests/src/rules/no-restricted-paths.js           | 11 +++++++++++
 5 files changed, 20 insertions(+), 3 deletions(-)
 create mode 100644 tests/files/restricted-paths/server/two-new/a.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7ad8bab491..50213a8ad7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`no-restricted-paths`]: fix false positive matches ([#2090], thanks [@malykhinvi])
+
 ### Changed
 - [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])
 
@@ -786,6 +789,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2090]: https://github.com/benmosher/eslint-plugin-import/pull/2090
 [#2075]: https://github.com/benmosher/eslint-plugin-import/pull/2075
 [#2071]: https://github.com/benmosher/eslint-plugin-import/pull/2071
 [#2034]: https://github.com/benmosher/eslint-plugin-import/pull/2034
@@ -1238,7 +1242,6 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@duncanbeevers]: https://github.com/duncanbeevers
 [@giodamelio]: https://github.com/giodamelio
-[@ntdb]: https://github.com/ntdb
 [@ramasilveyra]: https://github.com/ramasilveyra
 [@sompylasar]: https://github.com/sompylasar
 [@kevin940726]: https://github.com/kevin940726
diff --git a/package.json b/package.json
index a1712e2b12..1edec2bc38 100644
--- a/package.json
+++ b/package.json
@@ -101,7 +101,6 @@
   "dependencies": {
     "array-includes": "^3.1.3",
     "array.prototype.flat": "^1.2.4",
-    "contains-path": "^1.0.0",
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.4",
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index e2b11957f7..6409ff57ac 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -1,4 +1,3 @@
-import containsPath from 'contains-path';
 import path from 'path';
 
 import resolve from 'eslint-module-utils/resolve';
@@ -6,6 +5,11 @@ import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 import importType from '../core/importType';
 
+const containsPath = (filepath, target) => {
+  const relative = path.relative(target, filepath);
+  return relative === '' || !relative.startsWith('..');
+};
+
 module.exports = {
   meta: {
     type: 'problem',
diff --git a/tests/files/restricted-paths/server/two-new/a.js b/tests/files/restricted-paths/server/two-new/a.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index e39f4326d4..3ee728c5c7 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -50,6 +50,17 @@ ruleTester.run('no-restricted-paths', rule, {
         } ],
       } ],
     }),
+    test({
+      code: 'import a from "../one/a.js"',
+      filename: testFilePath('./restricted-paths/server/two-new/a.js'),
+      options: [ {
+        zones: [ {
+          target: './tests/files/restricted-paths/server/two',
+          from: './tests/files/restricted-paths/server',
+          except: [],
+        } ],
+      } ],
+    }),
 
 
     // irrelevant function calls

From 3cf913d087a58caf99b4719ee41f50a92c2be38b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 18 May 2021 10:59:45 -0700
Subject: [PATCH 299/767] [meta] sort and uniquify usernames in changelog

---
 CHANGELOG.md | 340 +++++++++++++++++++++++++--------------------------
 1 file changed, 169 insertions(+), 171 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 50213a8ad7..7397bc727d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1206,194 +1206,192 @@ for info on changes for earlier releases.
 [0.12.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.11.0...v0.12.0
 [0.11.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.10.1...v0.11.0
 
-[@mathieudutour]: https://github.com/mathieudutour
-[@gausie]: https://github.com/gausie
-[@singles]: https://github.com/singles
-[@jfmengels]: https://github.com/jfmengels
-[@lo1tuma]: https://github.com/lo1tuma
-[@dmnd]: https://github.com/dmnd
-[@lemonmade]: https://github.com/lemonmade
-[@jimbolla]: https://github.com/jimbolla
-[@jquense]: https://github.com/jquense
-[@jonboiser]: https://github.com/jonboiser
-[@taion]: https://github.com/taion
-[@strawbrary]: https://github.com/strawbrary
-[@SimenB]: https://github.com/SimenB
-[@josh]: https://github.com/josh
-[@borisyankov]: https://github.com/borisyankov
-[@gavriguy]: https://github.com/gavriguy
-[@jkimbo]: https://github.com/jkimbo
-[@le0nik]: https://github.com/le0nik
-[@scottnonnenberg]: https://github.com/scottnonnenberg
-[@sindresorhus]: https://github.com/sindresorhus
-[@ljharb]: https://github.com/ljharb
-[@rhettlivingston]: https://github.com/rhettlivingston
-[@zloirock]: https://github.com/zloirock
-[@rhys-vdw]: https://github.com/rhys-vdw
-[@wKich]: https://github.com/wKich
-[@tizmagik]: https://github.com/tizmagik
-[@knpwrs]: https://github.com/knpwrs
-[@spalger]: https://github.com/spalger
-[@preco21]: https://github.com/preco21
-[@skyrpex]: https://github.com/skyrpex
-[@fson]: https://github.com/fson
-[@ntdb]: https://github.com/ntdb
-[@jakubsta]: https://github.com/jakubsta
-[@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
-[@duncanbeevers]: https://github.com/duncanbeevers
-[@giodamelio]: https://github.com/giodamelio
-[@ramasilveyra]: https://github.com/ramasilveyra
-[@sompylasar]: https://github.com/sompylasar
-[@kevin940726]: https://github.com/kevin940726
-[@eelyafi]: https://github.com/eelyafi
-[@mastilver]: https://github.com/mastilver
-[@jseminck]: https://github.com/jseminck
-[@laysent]: https://github.com/laysent
-[@k15a]: https://github.com/k15a
-[@mplewis]: https://github.com/mplewis
-[@rosswarren]: https://github.com/rosswarren
-[@alexgorbatchev]: https://github.com/alexgorbatchev
-[@tihonove]: https://github.com/tihonove
-[@robertrossmann]: https://github.com/robertrossmann
-[@isiahmeadows]: https://github.com/isiahmeadows
-[@graingert]: https://github.com/graingert
-[@danny-andrews]: https://github.com/dany-andrews
-[@fengkfengk]: https://github.com/fengkfengk
-[@futpib]: https://github.com/futpib
-[@klimashkin]: https://github.com/klimashkin
-[@lukeapage]: https://github.com/lukeapage
-[@manovotny]: https://github.com/manovotny
-[@mattijsbliek]: https://github.com/mattijsbliek
-[@hulkish]: https://github.com/hulkish
-[@chrislloyd]: https://github.com/chrislloyd
-[@ai]: https://github.com/ai
-[@syymza]: https://github.com/syymza
-[@justinanastos]: https://github.com/justinanastos
 [@1pete]: https://github.com/1pete
-[@gajus]: https://github.com/gajus
-[@jf248]: https://github.com/jf248
+[@3nuc]: https://github.com/3nuc
+[@aamulumi]: https://github.com/aamulumi
+[@adamborowski]: https://github.com/adamborowski
+[@adjerbetian]: https://github.com/adjerbetian
+[@ai]: https://github.com/ai
+[@aladdin-add]: https://github.com/aladdin-add
+[@alex-page]: https://github.com/alex-page
+[@alexgorbatchev]: https://github.com/alexgorbatchev
+[@andreubotella]: https://github.com/andreubotella
+[@AndrewLeedham]: https://github.com/AndrewLeedham
 [@aravindet]: https://github.com/aravindet
-[@pzhine]: https://github.com/pzhine
-[@st-sloth]: https://github.com/st-sloth
-[@ljqx]: https://github.com/ljqx
-[@kirill-konshin]: https://github.com/kirill-konshin
+[@arvigeus]: https://github.com/arvigeus
 [@asapach]: https://github.com/asapach
-[@sergei-startsev]: https://github.com/sergei-startsev
-[@ephys]: https://github.com/ephys
-[@lydell]: https://github.com/lydell
-[@jeffshaver]: https://github.com/jeffshaver
-[@timkraut]: https://github.com/timkraut
-[@TakeScoop]: https://github.com/TakeScoop
-[@rfermann]: https://github.com/rfermann
-[@bradennapier]: https://github.com/bradennapier
-[@schmod]: https://github.com/schmod
-[@echenley]: https://github.com/echenley
-[@vikr01]: https://github.com/vikr01
-[@bradzacher]: https://github.com/bradzacher
-[@feychenie]: https://github.com/feychenie
-[@kiwka]: https://github.com/kiwka
-[@loganfsmyth]: https://github.com/loganfsmyth
-[@golopot]: https://github.com/golopot
-[@johndevedu]: https://github.com/johndevedu
-[@charlessuh]: https://github.com/charlessuh
-[@kgregory]: https://github.com/kgregory
-[@christophercurrie]: https://github.com/christophercurrie
-[@alex-page]: https://github.com/alex-page
-[@benmosher]: https://github.com/benmosher
-[@fooloomanzoo]: https://github.com/fooloomanzoo
-[@sheepsteak]: https://github.com/sheepsteak
-[@sharmilajesupaul]: https://github.com/sharmilajesupaul
-[@lencioni]: https://github.com/lencioni
-[@JounQin]: https://github.com/JounQin
+[@astorije]: https://github.com/astorije
 [@atikenny]: https://github.com/atikenny
-[@schmidsi]: https://github.com/schmidsi
-[@TrevorBurnham]: https://github.com/TrevorBurnham
+[@atos1990]: https://github.com/atos1990
+[@barbogast]: https://github.com/barbogast
+[@be5invis]: https://github.com/be5invis
+[@beatrizrezener]: https://github.com/beatrizrezener
+[@benmosher]: https://github.com/benmosher
 [@benmunro]: https://github.com/benmunro
-[@tihonove]: https://github.com/tihonove
+[@bicstone]: https://github.com/bicstone
+[@Blasz]: https://github.com/Blasz
+[@bmish]: https://github.com/bmish
+[@borisyankov]: https://github.com/borisyankov
+[@bradennapier]: https://github.com/bradennapier
+[@bradzacher]: https://github.com/bradzacher
 [@brendo]: https://github.com/brendo
-[@saschanaz]: https://github.com/saschanaz
 [@brettz9]: https://github.com/brettz9
-[@Taranys]: https://github.com/Taranys
-[@maxmalov]: https://github.com/maxmalov
-[@marcusdarmstrong]: https://github.com/marcusdarmstrong
-[@Mairu]: https://github.com/Mairu
-[@aamulumi]: https://github.com/aamulumi
-[@pcorpet]: https://github.com/pcorpet
-[@stropho]: https://github.com/stropho
-[@luczsoma]: https://github.com/luczsoma
+[@charlessuh]: https://github.com/charlessuh
+[@cherryblossom000]: https://github.com/cherryblossom000
+[@chrislloyd]: https://github.com/chrislloyd
+[@christianvuerings]: https://github.com/christianvuerings
 [@christophercurrie]: https://github.com/christophercurrie
-[@randallreedjr]: https://github.com/randallreedjr
-[@Pessimistress]: https://github.com/Pessimistress
-[@stekycz]: https://github.com/stekycz
+[@danny-andrews]: https://github.com/dany-andrews
+[@darkartur]: https://github.com/darkartur
+[@davidbonnet]: https://github.com/davidbonnet
 [@dbrewer5]: https://github.com/dbrewer5
-[@rsolomon]: https://github.com/rsolomon
-[@joaovieira]: https://github.com/joaovieira
-[@ivo-stefchev]: https://github.com/ivo-stefchev
-[@skozin]: https://github.com/skozin
-[@yordis]: https://github.com/yordis
-[@sveyret]: https://github.com/sveyret
-[@bmish]: https://github.com/bmish
-[@redbugz]: https://github.com/redbugz
-[@kentcdodds]: https://github.com/kentcdodds
-[@IvanGoncharov]: https://github.com/IvanGoncharov
-[@wschurman]: https://github.com/wschurman
-[@fisker]: https://github.com/fisker
-[@richardxia]: https://github.com/richardxia
-[@TheCrueltySage]: https://github.com/TheCrueltySage
+[@devongovett]: https://github.com/devongovett
+[@dmnd]: https://github.com/dmnd
+[@duncanbeevers]: https://github.com/duncanbeevers
+[@dwardu]: https://github.com/dwardu
+[@echenley]: https://github.com/echenley
+[@edemaine]: https://github.com/edemaine
+[@eelyafi]: https://github.com/eelyafi
+[@Ephem]: https://github.com/Ephem
+[@ephys]: https://github.com/ephys
 [@ernestostifano]: https://github.com/ernestostifano
+[@fa93hws]: https://github.com/fa93hws
+[@fengkfengk]: https://github.com/fengkfengk
+[@fernandopasik]: https://github.com/fernandopasik
+[@feychenie]: https://github.com/feychenie
+[@fisker]: https://github.com/fisker
+[@FloEdelmann]: https://github.com/FloEdelmann
+[@fooloomanzoo]: https://github.com/fooloomanzoo
+[@foray1010]: https://github.com/foray1010
 [@forivall]: https://github.com/forivall
-[@xpl]: https://github.com/xpl
-[@astorije]: https://github.com/astorije
-[@Ephem]: https://github.com/Ephem
-[@kmui2]: https://github.com/kmui2
-[@arvigeus]: https://github.com/arvigeus
-[@atos1990]: https://github.com/atos1990
+[@fsmaia]: https://github.com/fsmaia
+[@fson]: https://github.com/fson
+[@futpib]: https://github.com/futpib
+[@gajus]: https://github.com/gajus
+[@gausie]: https://github.com/gausie
+[@gavriguy]: https://github.com/gavriguy
+[@giodamelio]: https://github.com/giodamelio
+[@golopot]: https://github.com/golopot
+[@graingert]: https://github.com/graingert
+[@grit96]: https://github.com/grit96
+[@guillaumewuip]: https://github.com/guillaumewuip
+[@hayes]: https://github.com/hayes
+[@hulkish]: https://github.com/hulkish
 [@Hypnosphi]: https://github.com/Hypnosphi
-[@nickofthyme]: https://github.com/nickofthyme
-[@manuth]: https://github.com/manuth
+[@isiahmeadows]: https://github.com/isiahmeadows
+[@IvanGoncharov]: https://github.com/IvanGoncharov
+[@ivo-stefchev]: https://github.com/ivo-stefchev
+[@jakubsta]: https://github.com/jakubsta
+[@jeffshaver]: https://github.com/jeffshaver
+[@jf248]: https://github.com/jf248
+[@jfmengels]: https://github.com/jfmengels
+[@jimbolla]: https://github.com/jimbolla
+[@jkimbo]: https://github.com/jkimbo
+[@joaovieira]: https://github.com/joaovieira
+[@johndevedu]: https://github.com/johndevedu
+[@jonboiser]: https://github.com/jonboiser
+[@josh]: https://github.com/josh
+[@JounQin]: https://github.com/JounQin
+[@jquense]: https://github.com/jquense
+[@jseminck]: https://github.com/jseminck
 [@julien1619]: https://github.com/julien1619
-[@darkartur]: https://github.com/darkartur
-[@MikeyBeLike]: https://github.com/MikeyBeLike
-[@barbogast]: https://github.com/barbogast
-[@adamborowski]: https://github.com/adamborowski
-[@adjerbetian]: https://github.com/adjerbetian
-[@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
+[@justinanastos]: https://github.com/justinanastos
+[@k15a]: https://github.com/k15a
+[@kentcdodds]: https://github.com/kentcdodds
+[@kevin940726]: https://github.com/kevin940726
+[@kgregory]: https://github.com/kgregory
+[@kirill-konshin]: https://github.com/kirill-konshin
+[@kiwka]: https://github.com/kiwka
+[@klimashkin]: https://github.com/klimashkin
+[@kmui2]: https://github.com/kmui2
+[@knpwrs]: https://github.com/knpwrs
+[@laysent]: https://github.com/laysent
+[@le0nik]: https://github.com/le0nik
+[@lemonmade]: https://github.com/lemonmade
+[@lencioni]: https://github.com/lencioni
+[@leonardodino]: https://github.com/leonardodino
+[@Librazy]: https://github.com/Librazy
+[@lilling]: https://github.com/lilling
+[@ljharb]: https://github.com/ljharb
+[@ljqx]: https://github.com/ljqx
+[@lo1tuma]: https://github.com/lo1tuma
+[@loganfsmyth]: https://github.com/loganfsmyth
+[@luczsoma]: https://github.com/luczsoma
+[@lukeapage]: https://github.com/lukeapage
+[@lydell]: https://github.com/lydell
+[@Mairu]: https://github.com/Mairu
 [@malykhinvi]: https://github.com/malykhinvi
+[@manovotny]: https://github.com/manovotny
+[@manuth]: https://github.com/manuth
+[@marcusdarmstrong]: https://github.com/marcusdarmstrong
+[@mastilver]: https://github.com/mastilver
+[@mathieudutour]: https://github.com/mathieudutour
+[@MatthiasKunnen]: https://github.com/MatthiasKunnen
+[@mattijsbliek]: https://github.com/mattijsbliek
+[@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
+[@maxmalov]: https://github.com/maxmalov
+[@MikeyBeLike]: https://github.com/MikeyBeLike
+[@mplewis]: https://github.com/mplewis
+[@nickofthyme]: https://github.com/nickofthyme
 [@nicolashenry]: https://github.com/nicolashenry
-[@fernandopasik]: https://github.com/fernandopasik
-[@taye]: https://github.com/taye
-[@AndrewLeedham]: https://github.com/AndrewLeedham
-[@be5invis]: https://github.com/be5invis
 [@noelebrun]: https://github.com/noelebrun
-[@beatrizrezener]: https://github.com/beatrizrezener
-[@3nuc]: https://github.com/3nuc
-[@foray1010]: https://github.com/foray1010
-[@tomprats]: https://github.com/tomprats
+[@ntdb]: https://github.com/ntdb
+[@panrafal]: https://github.com/panrafal
+[@paztis]: https://github.com/paztis
+[@pcorpet]: https://github.com/pcorpet
+[@Pessimistress]: https://github.com/Pessimistress
+[@preco21]: https://github.com/preco21
+[@pzhine]: https://github.com/pzhine
+[@ramasilveyra]: https://github.com/ramasilveyra
+[@randallreedjr]: https://github.com/randallreedjr
+[@redbugz]: https://github.com/redbugz
+[@rfermann]: https://github.com/rfermann
+[@rhettlivingston]: https://github.com/rhettlivingston
+[@rhys-vdw]: https://github.com/rhys-vdw
+[@richardxia]: https://github.com/richardxia
+[@robertrossmann]: https://github.com/robertrossmann
+[@rosswarren]: https://github.com/rosswarren
+[@rsolomon]: https://github.com/rsolomon
+[@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w
+[@saschanaz]: https://github.com/saschanaz
+[@schmidsi]: https://github.com/schmidsi
+[@schmod]: https://github.com/schmod
+[@scottnonnenberg]: https://github.com/scottnonnenberg
+[@sergei-startsev]: https://github.com/sergei-startsev
+[@sharmilajesupaul]: https://github.com/sharmilajesupaul
+[@sheepsteak]: https://github.com/sheepsteak
+[@silviogutierrez]: https://github.com/silviogutierrez
+[@SimenB]: https://github.com/SimenB
+[@sindresorhus]: https://github.com/sindresorhus
+[@singles]: https://github.com/singles
+[@skozin]: https://github.com/skozin
+[@skyrpex]: https://github.com/skyrpex
+[@sompylasar]: https://github.com/sompylasar
+[@spalger]: https://github.com/spalger
+[@st-sloth]: https://github.com/st-sloth
+[@stekycz]: https://github.com/stekycz
 [@straub]: https://github.com/straub
-[@andreubotella]: https://github.com/andreubotella
-[@cherryblossom000]: https://github.com/cherryblossom000
-[@Blasz]: https://github.com/Blasz
-[@leonardodino]: https://github.com/leonardodino
-[@fa93hws]: https://github.com/fa93hws
-[@Librazy]: https://github.com/Librazy
+[@strawbrary]: https://github.com/strawbrary
+[@stropho]: https://github.com/stropho
+[@sveyret]: https://github.com/sveyret
 [@swernerx]: https://github.com/swernerx
-[@fsmaia]: https://github.com/fsmaia
-[@MatthiasKunnen]: https://github.com/MatthiasKunnen
-[@paztis]: https://github.com/paztis
-[@FloEdelmann]: https://github.com/FloEdelmann
-[@bicstone]: https://github.com/bicstone
-[@guillaumewuip]: https://github.com/guillaumewuip
+[@syymza]: https://github.com/syymza
+[@taion]: https://github.com/taion
+[@TakeScoop]: https://github.com/TakeScoop
 [@tapayne88]: https://github.com/tapayne88
-[@panrafal]: https://github.com/panrafal
+[@Taranys]: https://github.com/Taranys
+[@taye]: https://github.com/taye
+[@TheCrueltySage]: https://github.com/TheCrueltySage
+[@tihonove]: https://github.com/tihonove
+[@timkraut]: https://github.com/timkraut
+[@tizmagik]: https://github.com/tizmagik
+[@tomprats]: https://github.com/tomprats
+[@TrevorBurnham]: https://github.com/TrevorBurnham
 [@ttmarek]: https://github.com/ttmarek
-[@christianvuerings]: https://github.com/christianvuerings
-[@devongovett]: https://github.com/devongovett
-[@dwardu]: https://github.com/dwardu
-[@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w
-[@grit96]: https://github.com/grit96
-[@lilling]: https://github.com/lilling
-[@silviogutierrez]: https://github.com/silviogutierrez
-[@aladdin-add]: https://github.com/aladdin-add
-[@davidbonnet]: https://github.com/davidbonnet
-[@hayes]: https://github.com/hayes
-[@edemaine]: https://github.com/edemaine
+[@vikr01]: https://github.com/vikr01
+[@wKich]: https://github.com/wKich
+[@wschurman]: https://github.com/wschurman
+[@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
+[@xpl]: https://github.com/xpl
+[@yordis]: https://github.com/yordis
+[@zloirock]: https://github.com/zloirock

From 30bba6a25e6d8ba6ae37b46072be2e232140402d Mon Sep 17 00:00:00 2001
From: cherryblossom <31467609+cherryblossom000@users.noreply.github.com>
Date: Mon, 17 May 2021 19:28:04 +1000
Subject: [PATCH 300/767] [Fix] `no-cycle`: ignore imports where imported file
 only imports types of importing file

This fixes this situation:

`a.ts`:
```ts
import { foo } from './b'
```

`b.ts`:
```ts
import type { Bar } from './a'
```

Previously, `no-cycle` would have incorrectly reported a dependency cycle for the import in `a.ts`,
even though `b.ts` is only importing types from `a.ts`.
---
 CHANGELOG.md                                  |  2 ++
 src/rules/no-cycle.js                         | 26 ++++++++++++-------
 ...low-types-only-importing-multiple-types.js |  3 +++
 .../cycles/flow-types-only-importing-type.js  |  3 +++
 tests/src/rules/no-cycle.js                   |  8 ++++++
 5 files changed, 33 insertions(+), 9 deletions(-)
 create mode 100644 tests/files/cycles/flow-types-only-importing-multiple-types.js
 create mode 100644 tests/files/cycles/flow-types-only-importing-type.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7397bc727d..712bf21a24 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`no-restricted-paths`]: fix false positive matches ([#2090], thanks [@malykhinvi])
+- [`no-cycle`]: ignore imports where imported file only imports types of importing file ([#2083], thanks [@cherryblossom000])
 
 ### Changed
 - [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])
@@ -790,6 +791,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2090]: https://github.com/benmosher/eslint-plugin-import/pull/2090
+[#2083]: https://github.com/benmosher/eslint-plugin-import/pull/2083
 [#2075]: https://github.com/benmosher/eslint-plugin-import/pull/2075
 [#2071]: https://github.com/benmosher/eslint-plugin-import/pull/2071
 [#2034]: https://github.com/benmosher/eslint-plugin-import/pull/2034
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 74b77cbc3c..9d9a28cd66 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -84,18 +84,26 @@ module.exports = {
         traversed.add(m.path);
 
         for (const [path, { getter, declarations }] of m.imports) {
-          if (path === myPath) return true;
           if (traversed.has(path)) continue;
-          for (const { source, isOnlyImportingTypes } of declarations) {
-            if (ignoreModule(source.value)) continue;
+          const toTraverse = [...declarations].filter(({ source, isOnlyImportingTypes }) =>
+            !ignoreModule(source.value) &&
             // Ignore only type imports
-            if (isOnlyImportingTypes) continue;
+            !isOnlyImportingTypes
+          );
+          /*
+          Only report as a cycle if there are any import declarations that are considered by
+          the rule. For example:
 
-            if (route.length + 1 < maxDepth) {
-              untraversed.push({
-                mget: getter,
-                route: route.concat(source),
-              });
+          a.ts:
+          import { foo } from './b' // should not be reported as a cycle
+
+          b.ts:
+          import type { Bar } from './a'
+          */
+          if (path === myPath && toTraverse.length > 0) return true;
+          if (route.length + 1 < maxDepth) {
+            for (const { source } of toTraverse) {
+              untraversed.push({ mget: getter, route: route.concat(source) });
             }
           }
         }
diff --git a/tests/files/cycles/flow-types-only-importing-multiple-types.js b/tests/files/cycles/flow-types-only-importing-multiple-types.js
new file mode 100644
index 0000000000..ab61606fd3
--- /dev/null
+++ b/tests/files/cycles/flow-types-only-importing-multiple-types.js
@@ -0,0 +1,3 @@
+// @flow
+
+import { type FooType, type BarType } from './depth-zero';
diff --git a/tests/files/cycles/flow-types-only-importing-type.js b/tests/files/cycles/flow-types-only-importing-type.js
new file mode 100644
index 0000000000..b407da9870
--- /dev/null
+++ b/tests/files/cycles/flow-types-only-importing-type.js
@@ -0,0 +1,3 @@
+// @flow
+
+import type { FooType } from './depth-zero';
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 965fa36b7e..9620eac447 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -73,6 +73,14 @@ ruleTester.run('no-cycle', rule, {
       code: 'import { bar } from "./flow-types"',
       parser: require.resolve('babel-eslint'),
     }),
+    test({
+      code: 'import { bar } from "./flow-types-only-importing-type"',
+      parser: require.resolve('babel-eslint'),
+    }),
+    test({
+      code: 'import { bar } from "./flow-types-only-importing-multiple-types"',
+      parser: require.resolve('babel-eslint'),
+    }),
   ],
   invalid: [
     test({

From 72b9c3da5d30c39a4dcb677c7a46d2ddae8aca7e Mon Sep 17 00:00:00 2001
From: cherryblossom <31467609+cherryblossom000@users.noreply.github.com>
Date: Mon, 17 May 2021 19:23:39 +1000
Subject: [PATCH 301/767] [Fix] `no-cycle`: fix false negative when file
 imports a type after importing a value in Flow

This fixes this situation:

`a.js`:
```js
import { foo } from './b'
```

`b.js`:
```js
// @flow
import { bar, type Baz } from './a'
```

Previously, `no-cycle` would have not reported a dependency cycle for the import in `a.js`, even
though `b.js` is importing `bar`, which is not a type import, from `a.js`. This commit fixes that.
---
 CHANGELOG.md                                       |  1 +
 src/ExportMap.js                                   | 11 ++++++-----
 tests/files/cycles/flow-types-some-type-imports.js |  3 +++
 tests/src/rules/no-cycle.js                        |  5 +++++
 4 files changed, 15 insertions(+), 5 deletions(-)
 create mode 100644 tests/files/cycles/flow-types-some-type-imports.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 712bf21a24..03526c700d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`no-restricted-paths`]: fix false positive matches ([#2090], thanks [@malykhinvi])
 - [`no-cycle`]: ignore imports where imported file only imports types of importing file ([#2083], thanks [@cherryblossom000])
+- [`no-cycle`]: fix false negative when file imports a type after importing a value in Flow ([#2083], thanks [@cherryblossom000])
 
 ### Changed
 - [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 9cc7a089e1..76b07f9dc9 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -495,7 +495,9 @@ ExportMap.parse = function (path, content, context) {
     if (n.type === 'ImportDeclaration') {
       // import type { Foo } (TS and Flow)
       const declarationIsType = n.importKind === 'type';
-      let isOnlyImportingTypes = declarationIsType;
+      // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
+      // shouldn't be considered to be just importing types
+      let specifiersOnlyImportingTypes = n.specifiers.length;
       const importedSpecifiers = new Set();
       n.specifiers.forEach(specifier => {
         if (supportedImportTypes.has(specifier.type)) {
@@ -506,11 +508,10 @@ ExportMap.parse = function (path, content, context) {
         }
 
         // import { type Foo } (Flow)
-        if (!declarationIsType) {
-          isOnlyImportingTypes = specifier.importKind === 'type';
-        }
+        specifiersOnlyImportingTypes =
+          specifiersOnlyImportingTypes && specifier.importKind === 'type';
       });
-      captureDependency(n, isOnlyImportingTypes, importedSpecifiers);
+      captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
 
       const ns = n.specifiers.find(s => s.type === 'ImportNamespaceSpecifier');
       if (ns) {
diff --git a/tests/files/cycles/flow-types-some-type-imports.js b/tests/files/cycles/flow-types-some-type-imports.js
new file mode 100644
index 0000000000..9008ba1af8
--- /dev/null
+++ b/tests/files/cycles/flow-types-some-type-imports.js
@@ -0,0 +1,3 @@
+// @flow
+
+import { foo, type BarType } from './depth-zero'
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 9620eac447..302db8351b 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -87,6 +87,11 @@ ruleTester.run('no-cycle', rule, {
       code: 'import { foo } from "./depth-one"',
       errors: [error(`Dependency cycle detected.`)],
     }),
+    test({
+      code: 'import { bar } from "./flow-types-some-type-imports"',
+      parser: require.resolve('babel-eslint'),
+      errors: [error(`Dependency cycle detected.`)],
+    }),
     test({
       code: 'import { foo } from "cycles/external/depth-one"',
       errors: [error(`Dependency cycle detected.`)],

From b39770d98c3ba9af8f9df8c8d6357b17ab9af786 Mon Sep 17 00:00:00 2001
From: Geraint White <geraintwhite@gmail.com>
Date: Mon, 17 May 2021 22:48:43 +0100
Subject: [PATCH 302/767] [Fix] `order`: restore default behavior unless `type`
 is in groups

Fixes #2070. Fixes #2084.
---
 CHANGELOG.md             |   2 +
 src/rules/order.js       |  10 +-
 tests/src/rules/order.js | 207 ++++++++++++++++++++++++++++++++-------
 3 files changed, 182 insertions(+), 37 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 03526c700d..e5f432932e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-restricted-paths`]: fix false positive matches ([#2090], thanks [@malykhinvi])
 - [`no-cycle`]: ignore imports where imported file only imports types of importing file ([#2083], thanks [@cherryblossom000])
 - [`no-cycle`]: fix false negative when file imports a type after importing a value in Flow ([#2083], thanks [@cherryblossom000])
+- [`order`]: restore default behavior unless `type` is in groups ([#2087], thanks [@grit96])
 
 ### Changed
 - [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])
@@ -792,6 +793,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2090]: https://github.com/benmosher/eslint-plugin-import/pull/2090
+[#2087]: https://github.com/benmosher/eslint-plugin-import/pull/2087
 [#2083]: https://github.com/benmosher/eslint-plugin-import/pull/2083
 [#2075]: https://github.com/benmosher/eslint-plugin-import/pull/2075
 [#2071]: https://github.com/benmosher/eslint-plugin-import/pull/2071
diff --git a/src/rules/order.js b/src/rules/order.js
index 515c089f7f..ce34604c64 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -313,7 +313,7 @@ function computeRank(context, ranks, importEntry, excludedImportTypes) {
   let rank;
   if (importEntry.type === 'import:object') {
     impType = 'object';
-  } else if (importEntry.node.importKind === 'type') {
+  } else if (importEntry.node.importKind === 'type' && ranks.omittedTypes.indexOf('type') === -1) {
     impType = 'type';
   } else {
     impType = importType(importEntry.value, context);
@@ -382,10 +382,12 @@ function convertGroupsToRanks(groups) {
     return rankObject[type] === undefined;
   });
 
-  return omittedTypes.reduce(function(res, type) {
+  const ranks = omittedTypes.reduce(function(res, type) {
     res[type] = groups.length;
     return res;
   }, rankObject);
+
+  return { groups: ranks, omittedTypes };
 }
 
 function convertPathGroupsForRanks(pathGroups) {
@@ -590,8 +592,10 @@ module.exports = {
 
     try {
       const { pathGroups, maxPosition } = convertPathGroupsForRanks(options.pathGroups || []);
+      const { groups, omittedTypes } = convertGroupsToRanks(options.groups || defaultGroups);
       ranks = {
-        groups: convertGroupsToRanks(options.groups || defaultGroups),
+        groups,
+        omittedTypes,
         pathGroups,
         maxPosition,
       };
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index f621c811d6..75d59ef319 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2243,6 +2243,50 @@ context('TypeScript', function () {
           // #1667: typescript type import support
 
           // Option alphabetize: {order: 'asc'}
+          test(
+            {
+              code: `
+                import c from 'Bar';
+                import type { C } from 'Bar';
+                import b from 'bar';
+                import a from 'foo';
+                import type { A } from 'foo';
+
+                import index from './';
+              `,
+              parser,
+              options: [
+                {
+                  groups: ['external', 'index'],
+                  alphabetize: { order: 'asc' },
+                },
+              ],
+            },
+            parserConfig,
+          ),
+          // Option alphabetize: {order: 'desc'}
+          test(
+            {
+              code: `
+                import a from 'foo';
+                import type { A } from 'foo';
+                import b from 'bar';
+                import c from 'Bar';
+                import type { C } from 'Bar';
+
+                import index from './';
+              `,
+              parser,
+              options: [
+                {
+                  groups: ['external', 'index'],
+                  alphabetize: { order: 'desc' },
+                },
+              ],
+            },
+            parserConfig,
+          ),
+          // Option alphabetize: {order: 'asc'} with type group
           test(
             {
               code: `
@@ -2258,14 +2302,14 @@ context('TypeScript', function () {
               parser,
               options: [
                 {
-                  groups: ['external', 'index'],
+                  groups: ['external', 'index', 'type'],
                   alphabetize: { order: 'asc' },
                 },
               ],
             },
             parserConfig,
           ),
-          // Option alphabetize: {order: 'desc'}
+          // Option alphabetize: {order: 'desc'} with type group
           test(
             {
               code: `
@@ -2281,7 +2325,7 @@ context('TypeScript', function () {
               parser,
               options: [
                 {
-                  groups: ['external', 'index'],
+                  groups: ['external', 'index', 'type'],
                   alphabetize: { order: 'desc' },
                 },
               ],
@@ -2303,35 +2347,130 @@ context('TypeScript', function () {
             },
             parserConfig,
           ),
+          test(
+            {
+              code: `
+                import { serialize, parse, mapFieldErrors } from '@vtaits/form-schema';
+                import type { GetFieldSchema } from '@vtaits/form-schema';
+                import { useMemo, useCallback } from 'react';
+                import type { ReactElement, ReactNode } from 'react';
+                import { Form } from 'react-final-form';
+                import type { FormProps as FinalFormProps } from 'react-final-form';
+              `,
+              parser,
+              options: [
+                {
+                  alphabetize: { order: 'asc' },
+                },
+              ],
+            },
+            parserConfig,
+          ),
         ],
         invalid: [
           // Option alphabetize: {order: 'asc'}
           test(
             {
               code: `
-              import b from 'bar';
-              import c from 'Bar';
-              import a from 'foo';
-
-              import index from './';
+                import b from 'bar';
+                import c from 'Bar';
+                import type { C } from 'Bar';
+                import a from 'foo';
+                import type { A } from 'foo';
 
-              import type { A } from 'foo';
-              import type { C } from 'Bar';
-            `,
+                import index from './';
+              `,
               output: `
-              import c from 'Bar';
-              import b from 'bar';
-              import a from 'foo';
+                import c from 'Bar';
+                import type { C } from 'Bar';
+                import b from 'bar';
+                import a from 'foo';
+                import type { A } from 'foo';
 
-              import index from './';
+                import index from './';
+              `,
+              parser,
+              options: [
+                {
+                  groups: ['external', 'index'],
+                  alphabetize: { order: 'asc' },
+                },
+              ],
+              errors: [
+                {
+                  message: semver.satisfies(eslintPkg.version, '< 3')
+                    ? '`bar` import should occur after import of `Bar`'
+                    : /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,
+                },
+              ],
+            },
+            parserConfig,
+          ),
+          // Option alphabetize: {order: 'desc'}
+          test(
+            {
+              code: `
+                import a from 'foo';
+                import type { A } from 'foo';
+                import c from 'Bar';
+                import type { C } from 'Bar';
+                import b from 'bar';
 
-              import type { C } from 'Bar';
-              import type { A } from 'foo';
-            `,
+                import index from './';
+              `,
+              output: `
+                import a from 'foo';
+                import type { A } from 'foo';
+                import b from 'bar';
+                import c from 'Bar';
+                import type { C } from 'Bar';
+
+                import index from './';
+              `,
               parser,
               options: [
                 {
                   groups: ['external', 'index'],
+                  alphabetize: { order: 'desc' },
+                },
+              ],
+              errors: [
+                {
+                  message: semver.satisfies(eslintPkg.version, '< 3')
+                    ? '`bar` import should occur before import of `Bar`'
+                    : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
+                },
+              ],
+            },
+            parserConfig,
+          ),
+          // Option alphabetize: {order: 'asc'} with type group
+          test(
+            {
+              code: `
+                import b from 'bar';
+                import c from 'Bar';
+                import a from 'foo';
+
+                import index from './';
+
+                import type { A } from 'foo';
+                import type { C } from 'Bar';
+              `,
+              output: `
+                import c from 'Bar';
+                import b from 'bar';
+                import a from 'foo';
+
+                import index from './';
+
+                import type { C } from 'Bar';
+                import type { A } from 'foo';
+              `,
+              parser,
+              options: [
+                {
+                  groups: ['external', 'index', 'type'],
                   alphabetize: { order: 'asc' },
                 },
               ],
@@ -2345,33 +2484,33 @@ context('TypeScript', function () {
             },
             parserConfig,
           ),
-          // Option alphabetize: {order: 'desc'}
+          // Option alphabetize: {order: 'desc'} with type group
           test(
             {
               code: `
-              import a from 'foo';
-              import c from 'Bar';
-              import b from 'bar';
+                import a from 'foo';
+                import c from 'Bar';
+                import b from 'bar';
 
-              import index from './';
+                import index from './';
 
-              import type { C } from 'Bar';
-              import type { A } from 'foo';
-            `,
+                import type { C } from 'Bar';
+                import type { A } from 'foo';
+              `,
               output: `
-              import a from 'foo';
-              import b from 'bar';
-              import c from 'Bar';
+                import a from 'foo';
+                import b from 'bar';
+                import c from 'Bar';
 
-              import index from './';
+                import index from './';
 
-              import type { A } from 'foo';
-              import type { C } from 'Bar';
-            `,
+                import type { A } from 'foo';
+                import type { C } from 'Bar';
+              `,
               parser,
               options: [
                 {
-                  groups: ['external', 'index'],
+                  groups: ['external', 'index', 'type'],
                   alphabetize: { order: 'desc' },
                 },
               ],

From 0a08b6ac7d5452df576049c45b83b3076fe9e306 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 21 May 2021 12:20:54 -0700
Subject: [PATCH 303/767] [Tests] `order` add passing test to close #2081

---
 tests/src/rules/order.js | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 75d59ef319..6475e4bcea 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -720,6 +720,31 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    test({
+      code: `
+        import { UserInputError } from 'apollo-server-express';
+
+        import { new as assertNewEmail } from '~/Assertions/Email';
+      `,
+      options: [{
+        alphabetize: {
+          caseInsensitive: true,
+          order: 'asc',
+        },
+        pathGroups: [
+          { pattern: '~/*', group: 'internal' },
+        ],
+        groups: [
+          'builtin',
+          'external',
+          'internal',
+          'parent',
+          'sibling',
+          'index',
+        ],
+        'newlines-between': 'always',
+      }],
+    }),
     ...flatMap(getTSParsers, parser => [
       // Order of the `import ... = require(...)` syntax
       test({

From 20c373c509ad33e339b96fc38b0daaef8c5f6e9a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 21 May 2021 12:24:14 -0700
Subject: [PATCH 304/767] Bump to v2.23.3

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5f432932e..c155f9d380 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.23.3] - 2021-05-21
+
 ### Fixed
 - [`no-restricted-paths`]: fix false positive matches ([#2090], thanks [@malykhinvi])
 - [`no-cycle`]: ignore imports where imported file only imports types of importing file ([#2083], thanks [@cherryblossom000])
@@ -1135,7 +1137,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.2...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.3...HEAD
+[2.23.3]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.2...v2.23.3
 [2.23.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.1...v2.23.2
 [2.23.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.0...v2.23.1
 [2.23.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.1...v2.23.0
diff --git a/package.json b/package.json
index 1edec2bc38..18ee8896cf 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.23.2",
+  "version": "2.23.3",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 81b9d2459c4dcf36d6b7cad994241efec2db5b3a Mon Sep 17 00:00:00 2001
From: eps1lon <silbermann.sebastian@gmail.com>
Date: Wed, 26 May 2021 10:31:56 +0200
Subject: [PATCH 305/767] [Fix] `no-import-module-exports`: Don't crash if
 packages have no entrypoint

---
 CHANGELOG.md                                | 5 ++++-
 src/rules/no-import-module-exports.js       | 8 +++++++-
 tests/files/missing-entrypoint/package.json | 3 +++
 tests/src/rules/no-import-module-exports.js | 7 +++++++
 4 files changed, 21 insertions(+), 2 deletions(-)
 create mode 100644 tests/files/missing-entrypoint/package.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c155f9d380..74412fff47 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-cycle`]: ignore imports where imported file only imports types of importing file ([#2083], thanks [@cherryblossom000])
 - [`no-cycle`]: fix false negative when file imports a type after importing a value in Flow ([#2083], thanks [@cherryblossom000])
 - [`order`]: restore default behavior unless `type` is in groups ([#2087], thanks [@grit96])
+- [`no-import-module-exports`]: Don't crash if packages have no entrypoint ([#2099], thanks [@eps1lon])
 
 ### Changed
 - [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])
@@ -794,6 +795,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
 [#2090]: https://github.com/benmosher/eslint-plugin-import/pull/2090
 [#2087]: https://github.com/benmosher/eslint-plugin-import/pull/2087
 [#2083]: https://github.com/benmosher/eslint-plugin-import/pull/2083
@@ -1262,6 +1264,7 @@ for info on changes for earlier releases.
 [@eelyafi]: https://github.com/eelyafi
 [@Ephem]: https://github.com/Ephem
 [@ephys]: https://github.com/ephys
+[@eps1lon]: https://github.com/eps1lon
 [@ernestostifano]: https://github.com/ernestostifano
 [@fa93hws]: https://github.com/fa93hws
 [@fengkfengk]: https://github.com/fengkfengk
@@ -1402,4 +1405,4 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xpl]: https://github.com/xpl
 [@yordis]: https://github.com/yordis
-[@zloirock]: https://github.com/zloirock
+[@zloirock]: https://github.com/zloirock
\ No newline at end of file
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index 7ac56da396..8ce5f4c9ac 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -4,7 +4,13 @@ import pkgUp from 'pkg-up';
 
 function getEntryPoint(context) {
   const pkgPath = pkgUp.sync(context.getFilename());
-  return require.resolve(path.dirname(pkgPath));
+  try {
+    return require.resolve(path.dirname(pkgPath));
+  } catch (error) {
+    // Assume the package has no entrypoint (e.g. CLI packages)
+    // in which case require.resolve would throw.
+    return null;
+  }
 }
 
 module.exports = {
diff --git a/tests/files/missing-entrypoint/package.json b/tests/files/missing-entrypoint/package.json
new file mode 100644
index 0000000000..4138a88f4b
--- /dev/null
+++ b/tests/files/missing-entrypoint/package.json
@@ -0,0 +1,3 @@
+{
+  "bin": "./cli.js"
+}
diff --git a/tests/src/rules/no-import-module-exports.js b/tests/src/rules/no-import-module-exports.js
index bd18bf4777..9ffbe6b56e 100644
--- a/tests/src/rules/no-import-module-exports.js
+++ b/tests/src/rules/no-import-module-exports.js
@@ -57,6 +57,13 @@ ruleTester.run('no-import-module-exports', rule, {
       filename: path.join(process.cwd(), 'tests/files/some/other/entry-point.js'),
       options: [{ exceptions: ['**/*/other/entry-point.js'] }],
     }),
+    test({
+      code: `
+        import * as process from 'process';
+        console.log(process.env);
+      `,
+      filename: path.join(process.cwd(), 'tests/files/missing-entrypoint/cli.js'),
+    }),
   ],
   invalid: [
     test({

From da8d584fc22495a10e04206619c117baa2760898 Mon Sep 17 00:00:00 2001
From: jeromeh <jerome.henaff@amdocs.com>
Date: Tue, 25 May 2021 13:31:36 +0200
Subject: [PATCH 306/767] [Fix] `no-extraneous-dependencies`: fix package name
 algorithm

- resolve nested package.json problems (a/b/c import will check a, a/b and a/b/c)
- resolve renamed dependencies: checks the import name and the resolve package name

Fixes #2066. Fixes #2065. Fixes #2058. Fixes #2078.
---
 CHANGELOG.md                                  |  2 +
 src/rules/no-extraneous-dependencies.js       | 84 ++++++++++++++-----
 tests/files/node_modules/rxjs/index.js        |  1 +
 .../node_modules/rxjs/operators/index.js      |  1 +
 .../node_modules/rxjs/operators/package.json  |  5 ++
 tests/files/node_modules/rxjs/package.json    |  5 ++
 tests/files/package.json                      |  3 +-
 tests/src/rules/no-extraneous-dependencies.js |  6 +-
 8 files changed, 84 insertions(+), 23 deletions(-)
 create mode 100644 tests/files/node_modules/rxjs/index.js
 create mode 100644 tests/files/node_modules/rxjs/operators/index.js
 create mode 100644 tests/files/node_modules/rxjs/operators/package.json
 create mode 100644 tests/files/node_modules/rxjs/package.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 74412fff47..95f72d587d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-cycle`]: fix false negative when file imports a type after importing a value in Flow ([#2083], thanks [@cherryblossom000])
 - [`order`]: restore default behavior unless `type` is in groups ([#2087], thanks [@grit96])
 - [`no-import-module-exports`]: Don't crash if packages have no entrypoint ([#2099], thanks [@eps1lon])
+- [`no-extraneous-dependencies`]: fix package name algorithm ([#2097], thanks [@paztis])
 
 ### Changed
 - [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])
@@ -796,6 +797,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
+[#2097]: https://github.com/benmosher/eslint-plugin-import/pull/2097
 [#2090]: https://github.com/benmosher/eslint-plugin-import/pull/2090
 [#2087]: https://github.com/benmosher/eslint-plugin-import/pull/2087
 [#2083]: https://github.com/benmosher/eslint-plugin-import/pull/2083
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 5fd2674843..8a6af2f617 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -126,6 +126,36 @@ function getModuleRealName(resolved) {
   return getFilePackageName(resolved);
 }
 
+function checkDependencyDeclaration(deps, packageName) {
+  // in case of sub package.json inside a module
+  // check the dependencies on all hierarchy
+  const packageHierarchy = [];
+  const packageNameParts = packageName.split('/');
+  packageNameParts.forEach((namePart, index) => {
+    if (!namePart.startsWith('@')) {
+      const ancestor = packageNameParts.slice(0, index + 1).join('/');
+      packageHierarchy.push(ancestor);
+    }
+  });
+
+  return packageHierarchy.reduce((result, ancestorName) => {
+    return {
+      isInDeps: result.isInDeps || deps.dependencies[ancestorName] !== undefined,
+      isInDevDeps: result.isInDevDeps || deps.devDependencies[ancestorName] !== undefined,
+      isInOptDeps: result.isInOptDeps || deps.optionalDependencies[ancestorName] !== undefined,
+      isInPeerDeps: result.isInPeerDeps || deps.peerDependencies[ancestorName] !== undefined,
+      isInBundledDeps:
+        result.isInBundledDeps || deps.bundledDependencies.indexOf(ancestorName) !== -1,
+    };
+  }, {
+    isInDeps: false,
+    isInDevDeps: false,
+    isInOptDeps: false,
+    isInPeerDeps: false,
+    isInBundledDeps: false,
+  });
+}
+
 function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types
   if (node.importKind === 'type' || (node.parent && node.parent.importKind === 'type') || node.importKind === 'typeof') {
@@ -139,37 +169,49 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
   const resolved = resolve(name, context);
   if (!resolved) { return; }
 
-  // get the real name from the resolved package.json
-  // if not aliased imports (alias/react for example) will not be correctly interpreted
-  // fallback on original name in case no package.json found
-  const packageName = getModuleRealName(resolved) || getModuleOriginalName(name);
-
-  const isInDeps = deps.dependencies[packageName] !== undefined;
-  const isInDevDeps = deps.devDependencies[packageName] !== undefined;
-  const isInOptDeps = deps.optionalDependencies[packageName] !== undefined;
-  const isInPeerDeps = deps.peerDependencies[packageName] !== undefined;
-  const isInBundledDeps = deps.bundledDependencies.indexOf(packageName) !== -1;
-
-  if (isInDeps ||
-    (depsOptions.allowDevDeps && isInDevDeps) ||
-    (depsOptions.allowPeerDeps && isInPeerDeps) ||
-    (depsOptions.allowOptDeps && isInOptDeps) ||
-    (depsOptions.allowBundledDeps && isInBundledDeps)
+  const importPackageName = getModuleOriginalName(name);
+  const importPackageNameDeclaration = checkDependencyDeclaration(deps, importPackageName);
+
+  if (importPackageNameDeclaration.isInDeps ||
+    (depsOptions.allowDevDeps && importPackageNameDeclaration.isInDevDeps) ||
+    (depsOptions.allowPeerDeps && importPackageNameDeclaration.isInPeerDeps) ||
+    (depsOptions.allowOptDeps && importPackageNameDeclaration.isInOptDeps) ||
+    (depsOptions.allowBundledDeps && importPackageNameDeclaration.isInBundledDeps)
+  ) {
+    return;
+  }
+
+  // test the real name from the resolved package.json
+  // if not aliased imports (alias/react for example), importPackageName can be  misinterpreted
+  const realPackageName = getModuleRealName(resolved);
+  const realPackageNameDeclaration = checkDependencyDeclaration(deps, realPackageName);
+
+  if (realPackageNameDeclaration.isInDeps ||
+    (depsOptions.allowDevDeps && realPackageNameDeclaration.isInDevDeps) ||
+    (depsOptions.allowPeerDeps && realPackageNameDeclaration.isInPeerDeps) ||
+    (depsOptions.allowOptDeps && realPackageNameDeclaration.isInOptDeps) ||
+    (depsOptions.allowBundledDeps && realPackageNameDeclaration.isInBundledDeps)
   ) {
     return;
   }
 
-  if (isInDevDeps && !depsOptions.allowDevDeps) {
-    context.report(node, devDepErrorMessage(packageName));
+  if ((
+    importPackageNameDeclaration.isInDevDeps ||
+    realPackageNameDeclaration.isInDevDeps
+  ) && !depsOptions.allowDevDeps) {
+    context.report(node, devDepErrorMessage(realPackageName));
     return;
   }
 
-  if (isInOptDeps && !depsOptions.allowOptDeps) {
-    context.report(node, optDepErrorMessage(packageName));
+  if ((
+    importPackageNameDeclaration.isInOptDeps ||
+    realPackageNameDeclaration.isInOptDeps
+  ) && !depsOptions.allowOptDeps) {
+    context.report(node, optDepErrorMessage(realPackageName));
     return;
   }
 
-  context.report(node, missingErrorMessage(packageName));
+  context.report(node, missingErrorMessage(realPackageName));
 }
 
 function testConfig(config, filename) {
diff --git a/tests/files/node_modules/rxjs/index.js b/tests/files/node_modules/rxjs/index.js
new file mode 100644
index 0000000000..ea9b101e1c
--- /dev/null
+++ b/tests/files/node_modules/rxjs/index.js
@@ -0,0 +1 @@
+export default function () {}
diff --git a/tests/files/node_modules/rxjs/operators/index.js b/tests/files/node_modules/rxjs/operators/index.js
new file mode 100644
index 0000000000..ea9b101e1c
--- /dev/null
+++ b/tests/files/node_modules/rxjs/operators/index.js
@@ -0,0 +1 @@
+export default function () {}
diff --git a/tests/files/node_modules/rxjs/operators/package.json b/tests/files/node_modules/rxjs/operators/package.json
new file mode 100644
index 0000000000..c857f8e31d
--- /dev/null
+++ b/tests/files/node_modules/rxjs/operators/package.json
@@ -0,0 +1,5 @@
+{
+  "name": "rxjs/operators",
+  "version": "1.0.0",
+  "main": "index.js"
+}
diff --git a/tests/files/node_modules/rxjs/package.json b/tests/files/node_modules/rxjs/package.json
new file mode 100644
index 0000000000..4fb9c6fa6d
--- /dev/null
+++ b/tests/files/node_modules/rxjs/package.json
@@ -0,0 +1,5 @@
+{
+  "name": "rxjs",
+  "version": "1.0.0",
+  "main": "index.js"
+}
diff --git a/tests/files/package.json b/tests/files/package.json
index 0ca8e77737..62bd3764a3 100644
--- a/tests/files/package.json
+++ b/tests/files/package.json
@@ -11,7 +11,8 @@
     "@org/package": "^1.0.0",
     "jquery": "^3.1.0",
     "lodash.cond": "^4.3.0",
-    "pkg-up": "^1.0.0"
+    "pkg-up": "^1.0.0",
+    "rxjs": "^1.0.0"
   },
   "optionalDependencies": {
     "lodash.isarray": "^4.0.0"
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 96ce533ac3..6bb84358ae 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -88,7 +88,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
     test({
       code: `
-        // @flow                                                                                                                                                                                                   
+        // @flow
         import typeof TypeScriptModule from 'typescript';
       `,
       options: [{ packageDir: packageDirWithFlowTyped }],
@@ -150,6 +150,10 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import "@generated/bar/and/sub/path"',
       settings: { 'import/core-modules': ['@generated/bar'] },
     }),
+    // check if "rxjs" dependency declaration fix the "rxjs/operators subpackage
+    test({
+      code: 'import "rxjs/operators"',
+    }),
   ],
   invalid: [
     test({

From ec10721dec48f8f7e3cdf386f03e773edde57ca1 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 May 2021 12:49:00 -0700
Subject: [PATCH 307/767] [meta] fix changelog entries

---
 CHANGELOG.md | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95f72d587d..6e8434c087 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`no-import-module-exports`]: Don't crash if packages have no entrypoint ([#2099], thanks [@eps1lon])
+- [`no-extraneous-dependencies`]: fix package name algorithm ([#2097], thanks [@paztis])
+
 ## [2.23.3] - 2021-05-21
 
 ### Fixed
@@ -13,8 +17,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-cycle`]: ignore imports where imported file only imports types of importing file ([#2083], thanks [@cherryblossom000])
 - [`no-cycle`]: fix false negative when file imports a type after importing a value in Flow ([#2083], thanks [@cherryblossom000])
 - [`order`]: restore default behavior unless `type` is in groups ([#2087], thanks [@grit96])
-- [`no-import-module-exports`]: Don't crash if packages have no entrypoint ([#2099], thanks [@eps1lon])
-- [`no-extraneous-dependencies`]: fix package name algorithm ([#2097], thanks [@paztis])
 
 ### Changed
 - [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])

From 998c3000c70b8571aa27cfe1ec30cfff0efc9795 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 29 May 2021 13:15:36 -0700
Subject: [PATCH 308/767] Bump to v2.23.4

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e8434c087..95416f1af7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.23.4] - 2021-05-29
+
 ### Fixed
 - [`no-import-module-exports`]: Don't crash if packages have no entrypoint ([#2099], thanks [@eps1lon])
 - [`no-extraneous-dependencies`]: fix package name algorithm ([#2097], thanks [@paztis])
@@ -1143,7 +1145,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
 [#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.3...HEAD
+[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.4...HEAD
+[2.23.4]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.3...v2.23.4
 [2.23.3]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.2...v2.23.3
 [2.23.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.1...v2.23.2
 [2.23.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.0...v2.23.1
diff --git a/package.json b/package.json
index 18ee8896cf..eedf4e3504 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.23.3",
+  "version": "2.23.4",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 7aea664b8f6859aa9e8a0d808ab71cf96576f299 Mon Sep 17 00:00:00 2001
From: Mateusz Derks <mateusz.derks@toptal.com>
Date: Tue, 13 Apr 2021 09:18:30 +0200
Subject: [PATCH 309/767] [Fix] `no-duplicates`: ensure autofix avoids
 excessive newlines

Fixes #2027
---
 CHANGELOG.md                     |  7 +++++-
 src/rules/no-duplicates.js       | 15 ++++++++++++-
 tests/src/rules/no-duplicates.js | 37 +++++++++++++++++++++-----------
 3 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95416f1af7..ed5ff92e87 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
+
 ## [2.23.4] - 2021-05-29
 
 ### Fixed
@@ -808,6 +811,7 @@ for info on changes for earlier releases.
 [#2075]: https://github.com/benmosher/eslint-plugin-import/pull/2075
 [#2071]: https://github.com/benmosher/eslint-plugin-import/pull/2071
 [#2034]: https://github.com/benmosher/eslint-plugin-import/pull/2034
+[#2028]: https://github.com/benmosher/eslint-plugin-import/pull/2028
 [#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
 [#2022]: https://github.com/benmosher/eslint-plugin-import/pull/2022
 [#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021
@@ -1273,6 +1277,7 @@ for info on changes for earlier releases.
 [@ephys]: https://github.com/ephys
 [@eps1lon]: https://github.com/eps1lon
 [@ernestostifano]: https://github.com/ernestostifano
+[@ertrzyiks]: https://github.com/ertrzyiks
 [@fa93hws]: https://github.com/fa93hws
 [@fengkfengk]: https://github.com/fengkfengk
 [@fernandopasik]: https://github.com/fernandopasik
@@ -1412,4 +1417,4 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xpl]: https://github.com/xpl
 [@yordis]: https://github.com/yordis
-[@zloirock]: https://github.com/zloirock
\ No newline at end of file
+[@zloirock]: https://github.com/zloirock
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 1bf6f38245..43a29506be 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -150,7 +150,14 @@ function getFix(first, rest, sourceCode) {
 
     // Remove imports whose specifiers have been moved into the first import.
     for (const specifier of specifiers) {
-      fixes.push(fixer.remove(specifier.importNode));
+      const importNode = specifier.importNode;
+      fixes.push(fixer.remove(importNode));
+
+      const charAfterImportRange = [importNode.range[1], importNode.range[1] + 1];
+      const charAfterImport = sourceCode.text.substring(charAfterImportRange[0], charAfterImportRange[1]);
+      if (charAfterImport === '\n') {
+        fixes.push(fixer.removeRange(charAfterImportRange));
+      }
     }
 
     // Remove imports whose default import has been moved to the first import,
@@ -158,6 +165,12 @@ function getFix(first, rest, sourceCode) {
     // import.
     for (const node of unnecessaryImports) {
       fixes.push(fixer.remove(node));
+
+      const charAfterImportRange = [node.range[1], node.range[1] + 1];
+      const charAfterImport = sourceCode.text.substring(charAfterImportRange[0], charAfterImportRange[1]);
+      if (charAfterImport === '\n') {
+        fixes.push(fixer.removeRange(charAfterImportRange));
+      }
     }
 
     return fixes;
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 6b5bc739d5..d16f37b103 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -302,32 +302,30 @@ ruleTester.run('no-duplicates', rule, {
 
     test({
       code: `
-        import {x} from './foo'
-        import {y} from './foo'
-        // some-tool-disable-next-line
+import {x} from './foo'
+import {y} from './foo'
+// some-tool-disable-next-line
       `,
       // Not autofix bail.
       output: `
-        import {x,y} from './foo'
-        
-        // some-tool-disable-next-line
+import {x,y} from './foo'
+// some-tool-disable-next-line
       `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
 
     test({
       code: `
-        import {x} from './foo'
-        // comment
+import {x} from './foo'
+// comment
 
-        import {y} from './foo'
+import {y} from './foo'
       `,
       // Not autofix bail.
       output: `
-        import {x,y} from './foo'
-        // comment
+import {x,y} from './foo'
+// comment
 
-        
       `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
@@ -400,6 +398,20 @@ ruleTester.run('no-duplicates', rule, {
       `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
+
+    // #2027 long import list generate empty lines
+    test({
+      code: "import { Foo } from './foo';\nimport { Bar } from './foo';\nexport const value = {}",
+      output: "import { Foo , Bar } from './foo';\nexport const value = {}",
+      errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
+    }),
+
+    // #2027 long import list generate empty lines
+    test({
+      code: "import { Foo } from './foo';\nimport Bar from './foo';\nexport const value = {}",
+      output: "import Bar, { Foo } from './foo';\nexport const value = {}",
+      errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
+    }),
   ],
 });
 
@@ -430,4 +442,3 @@ context('TypeScript', function() {
       });
     });
 });
-

From 40794824e5d6a3c952a23c22feff43e6e4436255 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 4 Jun 2021 08:35:20 -0700
Subject: [PATCH 310/767] [Fix] `extensions`: avoid crashing on partially typed
 import/export statements

Fixes #2118.
---
 CHANGELOG.md            | 2 ++
 src/rules/extensions.js | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed5ff92e87..b918675a3f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
+- [`extensions`]: avoid crashing on partially typed import/export statements ([#2118], thanks [@ljharb])
 
 ## [2.23.4] - 2021-05-29
 
@@ -1043,6 +1044,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
 [#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
 [#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
+[#2118]: https://github.com/benmosher/eslint-plugin-import/issues/2118
 [#2067]: https://github.com/benmosher/eslint-plugin-import/issues/2067
 [#2056]: https://github.com/benmosher/eslint-plugin-import/issues/2056
 [#2063]: https://github.com/benmosher/eslint-plugin-import/issues/2063
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index bd47afa99d..921b981e0e 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -136,8 +136,8 @@ module.exports = {
     }
 
     function checkFileExtension(source) {
-      // bail if the declaration doesn't have a source, e.g. "export { foo };"
-      if (!source) return;
+      // bail if the declaration doesn't have a source, e.g. "export { foo };", or if it's only partially typed like in an editor
+      if (!source || !source.value) return;
       
       const importPathWithQueryString = source.value;
 

From b3d8c0cd5a89ce00642279f0a67e4ec1e5c5977d Mon Sep 17 00:00:00 2001
From: jeromeh <jerome.henaff@amdocs.com>
Date: Mon, 14 Jun 2021 23:30:19 +0200
Subject: [PATCH 311/767] [Fix] `no-extraneous-dependencies`: add ESM
 intermediate package.json support

Fixes #2120.
---
 CHANGELOG.md                                  |  2 +
 src/core/packagePath.js                       |  8 +-
 src/rules/no-extraneous-dependencies.js       | 80 ++++++++++---------
 .../esm-module/index.js                       |  0
 .../esm-module/package.json                   |  4 +
 .../esm-package-not-in-pkg-json/index.js      |  0
 .../esm-package-not-in-pkg-json/package.json  |  5 ++
 .../esm-package/esm-module/index.js           |  0
 .../esm-package/esm-module/package.json       |  4 +
 tests/files/node_modules/esm-package/index.js |  0
 .../node_modules/esm-package/package.json     |  5 ++
 tests/files/package.json                      |  1 +
 tests/files/webpack.config.js                 |  3 +-
 tests/src/rules/no-extraneous-dependencies.js | 16 ++++
 14 files changed, 87 insertions(+), 41 deletions(-)
 create mode 100644 tests/files/node_modules/esm-package-not-in-pkg-json/esm-module/index.js
 create mode 100644 tests/files/node_modules/esm-package-not-in-pkg-json/esm-module/package.json
 create mode 100644 tests/files/node_modules/esm-package-not-in-pkg-json/index.js
 create mode 100644 tests/files/node_modules/esm-package-not-in-pkg-json/package.json
 create mode 100644 tests/files/node_modules/esm-package/esm-module/index.js
 create mode 100644 tests/files/node_modules/esm-package/esm-module/package.json
 create mode 100644 tests/files/node_modules/esm-package/index.js
 create mode 100644 tests/files/node_modules/esm-package/package.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b918675a3f..3452dd5413 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
 - [`extensions`]: avoid crashing on partially typed import/export statements ([#2118], thanks [@ljharb])
+- [`no-extraneous-dependencies`]: add ESM intermediate package.json support] ([#2121], thanks [@paztis])
 
 ## [2.23.4] - 2021-05-29
 
@@ -804,6 +805,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
 [#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
 [#2097]: https://github.com/benmosher/eslint-plugin-import/pull/2097
 [#2090]: https://github.com/benmosher/eslint-plugin-import/pull/2090
diff --git a/src/core/packagePath.js b/src/core/packagePath.js
index e95b066668..315ec0918c 100644
--- a/src/core/packagePath.js
+++ b/src/core/packagePath.js
@@ -13,6 +13,10 @@ export function getFilePackagePath(filePath) {
 }
 
 export function getFilePackageName(filePath) {
-  const { pkg } = readPkgUp.sync({ cwd: filePath, normalize: false });
-  return pkg && pkg.name;
+  const { pkg, path } = readPkgUp.sync({ cwd: filePath, normalize: false });
+  if (pkg) {
+    // recursion in case of intermediate esm package.json without name found
+    return pkg.name || getFilePackageName(dirname(dirname(path)));
+  }
+  return null;
 }
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 8a6af2f617..7e46ac34bc 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -126,11 +126,19 @@ function getModuleRealName(resolved) {
   return getFilePackageName(resolved);
 }
 
-function checkDependencyDeclaration(deps, packageName) {
+function checkDependencyDeclaration(deps, packageName, declarationStatus) {
+  const newDeclarationStatus = declarationStatus || {
+    isInDeps: false,
+    isInDevDeps: false,
+    isInOptDeps: false,
+    isInPeerDeps: false,
+    isInBundledDeps: false,
+  };
+
   // in case of sub package.json inside a module
   // check the dependencies on all hierarchy
   const packageHierarchy = [];
-  const packageNameParts = packageName.split('/');
+  const packageNameParts = packageName ? packageName.split('/') : [];
   packageNameParts.forEach((namePart, index) => {
     if (!namePart.startsWith('@')) {
       const ancestor = packageNameParts.slice(0, index + 1).join('/');
@@ -147,18 +155,16 @@ function checkDependencyDeclaration(deps, packageName) {
       isInBundledDeps:
         result.isInBundledDeps || deps.bundledDependencies.indexOf(ancestorName) !== -1,
     };
-  }, {
-    isInDeps: false,
-    isInDevDeps: false,
-    isInOptDeps: false,
-    isInPeerDeps: false,
-    isInBundledDeps: false,
-  });
+  }, newDeclarationStatus);
 }
 
 function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types
-  if (node.importKind === 'type' || (node.parent && node.parent.importKind === 'type') || node.importKind === 'typeof') {
+  if (
+    node.importKind === 'type' ||
+    (node.parent && node.parent.importKind === 'type') ||
+    node.importKind === 'typeof'
+  ) {
     return;
   }
 
@@ -170,48 +176,46 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
   if (!resolved) { return; }
 
   const importPackageName = getModuleOriginalName(name);
-  const importPackageNameDeclaration = checkDependencyDeclaration(deps, importPackageName);
-
-  if (importPackageNameDeclaration.isInDeps ||
-    (depsOptions.allowDevDeps && importPackageNameDeclaration.isInDevDeps) ||
-    (depsOptions.allowPeerDeps && importPackageNameDeclaration.isInPeerDeps) ||
-    (depsOptions.allowOptDeps && importPackageNameDeclaration.isInOptDeps) ||
-    (depsOptions.allowBundledDeps && importPackageNameDeclaration.isInBundledDeps)
+  let declarationStatus = checkDependencyDeclaration(deps, importPackageName);
+
+  if (
+    declarationStatus.isInDeps ||
+    (depsOptions.allowDevDeps && declarationStatus.isInDevDeps) ||
+    (depsOptions.allowPeerDeps && declarationStatus.isInPeerDeps) ||
+    (depsOptions.allowOptDeps && declarationStatus.isInOptDeps) ||
+    (depsOptions.allowBundledDeps && declarationStatus.isInBundledDeps)
   ) {
     return;
   }
 
   // test the real name from the resolved package.json
-  // if not aliased imports (alias/react for example), importPackageName can be  misinterpreted
+  // if not aliased imports (alias/react for example), importPackageName can be misinterpreted
   const realPackageName = getModuleRealName(resolved);
-  const realPackageNameDeclaration = checkDependencyDeclaration(deps, realPackageName);
-
-  if (realPackageNameDeclaration.isInDeps ||
-    (depsOptions.allowDevDeps && realPackageNameDeclaration.isInDevDeps) ||
-    (depsOptions.allowPeerDeps && realPackageNameDeclaration.isInPeerDeps) ||
-    (depsOptions.allowOptDeps && realPackageNameDeclaration.isInOptDeps) ||
-    (depsOptions.allowBundledDeps && realPackageNameDeclaration.isInBundledDeps)
-  ) {
-    return;
+  if (realPackageName && realPackageName !== importPackageName) {
+    declarationStatus = checkDependencyDeclaration(deps, realPackageName, declarationStatus);
+
+    if (
+      declarationStatus.isInDeps ||
+      (depsOptions.allowDevDeps && declarationStatus.isInDevDeps) ||
+      (depsOptions.allowPeerDeps && declarationStatus.isInPeerDeps) ||
+      (depsOptions.allowOptDeps && declarationStatus.isInOptDeps) ||
+      (depsOptions.allowBundledDeps && declarationStatus.isInBundledDeps)
+    ) {
+      return;
+    }
   }
 
-  if ((
-    importPackageNameDeclaration.isInDevDeps ||
-    realPackageNameDeclaration.isInDevDeps
-  ) && !depsOptions.allowDevDeps) {
-    context.report(node, devDepErrorMessage(realPackageName));
+  if (declarationStatus.isInDevDeps && !depsOptions.allowDevDeps) {
+    context.report(node, devDepErrorMessage(realPackageName || importPackageName));
     return;
   }
 
-  if ((
-    importPackageNameDeclaration.isInOptDeps ||
-    realPackageNameDeclaration.isInOptDeps
-  ) && !depsOptions.allowOptDeps) {
-    context.report(node, optDepErrorMessage(realPackageName));
+  if (declarationStatus.isInOptDeps && !depsOptions.allowOptDeps) {
+    context.report(node, optDepErrorMessage(realPackageName || importPackageName));
     return;
   }
 
-  context.report(node, missingErrorMessage(realPackageName));
+  context.report(node, missingErrorMessage(realPackageName || importPackageName));
 }
 
 function testConfig(config, filename) {
diff --git a/tests/files/node_modules/esm-package-not-in-pkg-json/esm-module/index.js b/tests/files/node_modules/esm-package-not-in-pkg-json/esm-module/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/node_modules/esm-package-not-in-pkg-json/esm-module/package.json b/tests/files/node_modules/esm-package-not-in-pkg-json/esm-module/package.json
new file mode 100644
index 0000000000..0c58fec1b0
--- /dev/null
+++ b/tests/files/node_modules/esm-package-not-in-pkg-json/esm-module/package.json
@@ -0,0 +1,4 @@
+{
+  "sideEffects": false,
+  "module": "./index.js"
+}
diff --git a/tests/files/node_modules/esm-package-not-in-pkg-json/index.js b/tests/files/node_modules/esm-package-not-in-pkg-json/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/node_modules/esm-package-not-in-pkg-json/package.json b/tests/files/node_modules/esm-package-not-in-pkg-json/package.json
new file mode 100644
index 0000000000..fa7f3c0438
--- /dev/null
+++ b/tests/files/node_modules/esm-package-not-in-pkg-json/package.json
@@ -0,0 +1,5 @@
+{
+  "name": "esm-package-not-in-pkg-json",
+  "main": "index.js",
+  "version": "1.0.0"
+}
diff --git a/tests/files/node_modules/esm-package/esm-module/index.js b/tests/files/node_modules/esm-package/esm-module/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/node_modules/esm-package/esm-module/package.json b/tests/files/node_modules/esm-package/esm-module/package.json
new file mode 100644
index 0000000000..0c58fec1b0
--- /dev/null
+++ b/tests/files/node_modules/esm-package/esm-module/package.json
@@ -0,0 +1,4 @@
+{
+  "sideEffects": false,
+  "module": "./index.js"
+}
diff --git a/tests/files/node_modules/esm-package/index.js b/tests/files/node_modules/esm-package/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/node_modules/esm-package/package.json b/tests/files/node_modules/esm-package/package.json
new file mode 100644
index 0000000000..ddad1a531e
--- /dev/null
+++ b/tests/files/node_modules/esm-package/package.json
@@ -0,0 +1,5 @@
+{
+  "name": "esm-package",
+  "main": "index.js",
+  "version": "1.0.0"
+}
diff --git a/tests/files/package.json b/tests/files/package.json
index 62bd3764a3..de1d802753 100644
--- a/tests/files/package.json
+++ b/tests/files/package.json
@@ -9,6 +9,7 @@
   },
   "dependencies": {
     "@org/package": "^1.0.0",
+    "esm-package": "^1.0.0",
     "jquery": "^3.1.0",
     "lodash.cond": "^4.3.0",
     "pkg-up": "^1.0.0",
diff --git a/tests/files/webpack.config.js b/tests/files/webpack.config.js
index 6a5dc0b88c..bbe81b359e 100644
--- a/tests/files/webpack.config.js
+++ b/tests/files/webpack.config.js
@@ -3,7 +3,8 @@ module.exports = {
     extensions: ['', '.js', '.jsx'],
     root: __dirname,
     alias: {
-      'alias/chai$': 'chai' // alias for no-extraneous-dependencies tests
+      'alias/chai$': 'chai', // alias for no-extraneous-dependencies tests
+      'alias/esm-package': 'esm-package' // alias for no-extraneous-dependencies tests
     }
   },
 }
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 6bb84358ae..7a11074684 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -154,6 +154,15 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'import "rxjs/operators"',
     }),
+
+    test({
+      code: 'import "esm-package/esm-module";',
+    }),
+
+    test({
+      code: 'import "alias/esm-package/esm-module";',
+      settings: { 'import/resolver': 'webpack' },
+    }),
   ],
   invalid: [
     test({
@@ -358,6 +367,13 @@ ruleTester.run('no-extraneous-dependencies', rule, {
         message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
       }],
     }),
+
+    test({
+      code: 'import "esm-package-not-in-pkg-json/esm-module";',
+      errors: [{
+        message: `'esm-package-not-in-pkg-json' should be listed in the project's dependencies. Run 'npm i -S esm-package-not-in-pkg-json' to add it`,
+      }],
+    }),
   ],
 });
 

From 1012eb951767279ce3b540a4ec4f29236104bb5b Mon Sep 17 00:00:00 2001
From: Wenfang Du <duwenfangcn@163.com>
Date: Fri, 25 Jun 2021 20:17:31 +0800
Subject: [PATCH 312/767] [Docs] `extensions`: removed incorrect cases

---
 CHANGELOG.md             | 7 ++++++-
 docs/rules/extensions.md | 4 ----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3452dd5413..07f595d8ec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extensions`]: avoid crashing on partially typed import/export statements ([#2118], thanks [@ljharb])
 - [`no-extraneous-dependencies`]: add ESM intermediate package.json support] ([#2121], thanks [@paztis])
 
+### Changed
+- [Docs] `extensions`: removed incorrect cases ([#2138], thanks [@wenfangdu])
+
 ## [2.23.4] - 2021-05-29
 
 ### Fixed
@@ -805,6 +808,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2138]: https://github.com/benmosher/eslint-plugin-import/pull/2138
 [#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
 [#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
 [#2097]: https://github.com/benmosher/eslint-plugin-import/pull/2097
@@ -1416,9 +1420,10 @@ for info on changes for earlier releases.
 [@TrevorBurnham]: https://github.com/TrevorBurnham
 [@ttmarek]: https://github.com/ttmarek
 [@vikr01]: https://github.com/vikr01
+[@wenfangdu]: https://github.com/wenfangdu
 [@wKich]: https://github.com/wKich
 [@wschurman]: https://github.com/wschurman
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xpl]: https://github.com/xpl
 [@yordis]: https://github.com/yordis
-[@zloirock]: https://github.com/zloirock
+[@zloirock]: https://github.com/zloirock
\ No newline at end of file
diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md
index 2f6d4a9c7a..bf29dbe5fb 100644
--- a/docs/rules/extensions.md
+++ b/docs/rules/extensions.md
@@ -109,8 +109,6 @@ import foo from './foo';
 import bar from './bar';
 
 import Component from './Component';
-
-import express from 'express';
 ```
 
 The following patterns are not considered problems when configuration set to "always":
@@ -122,8 +120,6 @@ import bar from './bar.json';
 
 import Component from './Component.jsx';
 
-import express from 'express/index.js';
-
 import * as path from 'path';
 ```
 

From 95e60112bcb116c14f18005c42adf3d3e4501b32 Mon Sep 17 00:00:00 2001
From: "BZ (Brian Zhang)" <bz@stripe.com>
Date: Sun, 18 Jul 2021 23:22:07 -0700
Subject: [PATCH 313/767] [Tests] `order`: add tests for
 `pathGroupsExcludedImportTypes: ['type']`

Closes #2159
---
 CHANGELOG.md             |  3 ++
 tests/src/rules/order.js | 95 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 07f595d8ec..294529304a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Changed
 - [Docs] `extensions`: removed incorrect cases ([#2138], thanks [@wenfangdu])
+- [Tests] `order`: add tests for `pathGroupsExcludedImportTypes: ['type']` ([#2158], thanks [@atav32])
 
 ## [2.23.4] - 2021-05-29
 
@@ -808,6 +809,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2158]: https://github.com/benmosher/eslint-plugin-import/pull/2158
 [#2138]: https://github.com/benmosher/eslint-plugin-import/pull/2138
 [#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
 [#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
@@ -1250,6 +1252,7 @@ for info on changes for earlier releases.
 [@arvigeus]: https://github.com/arvigeus
 [@asapach]: https://github.com/asapach
 [@astorije]: https://github.com/astorije
+[@atav32]: https://github.com/atav32
 [@atikenny]: https://github.com/atikenny
 [@atos1990]: https://github.com/atos1990
 [@barbogast]: https://github.com/barbogast
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 6475e4bcea..7798a24cee 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -745,6 +745,36 @@ ruleTester.run('order', rule, {
         'newlines-between': 'always',
       }],
     }),
+    test({
+      code: `
+        import { ReactElement, ReactNode } from 'react';
+
+        import { util } from 'Internal/lib';
+
+        import { parent } from '../parent';
+
+        import { sibling } from './sibling';
+      `,
+      options: [{
+        alphabetize: {
+          caseInsensitive: true,
+          order: 'asc',
+        },
+        pathGroups: [
+          { pattern: 'Internal/**/*', group: 'internal' },
+        ],
+        groups: [
+          'builtin',
+          'external',
+          'internal',
+          'parent',
+          'sibling',
+          'index',
+        ],
+        'newlines-between': 'always',
+        pathGroupsExcludedImportTypes: [],
+      }],
+    }),
     ...flatMap(getTSParsers, parser => [
       // Order of the `import ... = require(...)` syntax
       test({
@@ -2334,6 +2364,71 @@ context('TypeScript', function () {
             },
             parserConfig,
           ),
+          // Option alphabetize: {order: 'asc'} with type group & path group
+          test(
+            {
+              // only: true,
+              code: `
+                import c from 'Bar';
+                import a from 'foo';
+
+                import b from 'dirA/bar';
+
+                import index from './';
+
+                import type { C } from 'dirA/Bar';
+                import type { A } from 'foo';
+              `,
+              parser,
+              options: [
+                {
+                  alphabetize: { order: 'asc' },
+                  groups: ['external', 'internal', 'index', 'type'],
+                  pathGroups: [
+                    {
+                      pattern: 'dirA/**',
+                      group: 'internal',
+                    },
+                  ],
+                  'newlines-between': 'always',
+                  pathGroupsExcludedImportTypes: ['type'],
+                },
+              ],
+            },
+            parserConfig,
+          ),
+          // Option alphabetize: {order: 'asc'} with path group
+          test(
+            {
+              // only: true,
+              code: `
+                import c from 'Bar';
+                import type { A } from 'foo';
+                import a from 'foo';
+
+                import type { C } from 'dirA/Bar';
+                import b from 'dirA/bar';
+
+                import index from './';
+              `,
+              parser,
+              options: [
+                {
+                  alphabetize: { order: 'asc' },
+                  groups: ['external', 'internal', 'index'],
+                  pathGroups: [
+                    {
+                      pattern: 'dirA/**',
+                      group: 'internal',
+                    },
+                  ],
+                  'newlines-between': 'always',
+                  pathGroupsExcludedImportTypes: [],
+                },
+              ],
+            },
+            parserConfig,
+          ),
           // Option alphabetize: {order: 'desc'} with type group
           test(
             {

From 95212841ac6095f35049a32dace893a1aa15d3b6 Mon Sep 17 00:00:00 2001
From: Mustafa Haddara <mhaddara@pagerduty.com>
Date: Mon, 26 Jul 2021 15:41:33 -0400
Subject: [PATCH 314/767] [Docs] `named`: update docs with `module` info and
 deprecation notice for `jsnext:main`

---
 docs/rules/named.md | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/docs/rules/named.md b/docs/rules/named.md
index 01ccb14ae7..0f697cc254 100644
--- a/docs/rules/named.md
+++ b/docs/rules/named.md
@@ -5,7 +5,7 @@ Verifies that all named imports are part of the set of named exports in the refe
 For `export`, verifies that all named exports exist in the referenced module.
 
 Note: for packages, the plugin will find exported names
-from [`jsnext:main`], if present in `package.json`.
+from [`jsnext:main`] (deprecated) or `module`, if present in `package.json`.
 Redux's npm module includes this key, and thereby is lintable, for example.
 
 A module path that is [ignored] or not [unambiguously an ES module] will not be reported when imported. Note that type imports and exports, as used by [Flow], are always ignored.
@@ -91,8 +91,10 @@ runtime, you will likely see false positives with this rule.
 ## Further Reading
 
 - [`import/ignore`] setting
-- [`jsnext:main`] (Rollup)
+- [`jsnext:main`] deprecation
+- [`pkg.module`] (Rollup)
 
 
-[`jsnext:main`]: https://github.com/rollup/rollup/wiki/jsnext:main
+[`jsnext:main`]: https://github.com/jsforum/jsforum/issues/5
+[`pkg.module`]: https://github.com/rollup/rollup/wiki/pkg.module
 [`import/ignore`]: ../../README.md#importignore

From 96e4332eb93fc6fa179d873dc705ced984eb7618 Mon Sep 17 00:00:00 2001
From: Mustafa Haddara <mhaddara@pagerduty.com>
Date: Mon, 26 Jul 2021 15:42:03 -0400
Subject: [PATCH 315/767] [resolvers/node] [New] use "module" in the same spot
 as "jsnext:main"

---
 resolvers/node/CHANGELOG.md | 5 +++++
 resolvers/node/index.js     | 6 ++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index 8fa31bed7d..86554a4231 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Added
+- use "module" in the same spot as "jsnext:main" ([#2166], thanks [@MustafaHaddara])
+
 ## v0.3.4 - 2020-06-16
 ### Added
 - add `.node` extension ([#1663])
@@ -48,6 +51,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - find files with `.json` extensions (#333, thanks for noticing @jfmengels)
 
+[#2166]: https://github.com/benmosher/eslint-plugin-import/pull/2166
 [#438]: https://github.com/benmosher/eslint-plugin-import/pull/438
 
 [#1663]: https://github.com/benmosher/eslint-plugin-import/issues/1663
@@ -61,3 +65,4 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@SkeLLLa]: https://github.com/SkeLLLa
 [@ljharb]: https://github.com/ljharb
 [@opichals]: https://github.com/opichals
+[@MustafaHaddara]: https://github.com/MustafaHaddara
\ No newline at end of file
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index 85550ddf7a..84fc5076b6 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -42,8 +42,10 @@ function opts(file, config) {
 }
 
 function packageFilter(pkg) {
-  if (pkg['jsnext:main']) {
-    pkg['main'] = pkg['jsnext:main'];
+  if (pkg.module) {
+    pkg.main = pkg.module;
+  } else if (pkg['jsnext:main']) {
+    pkg.main = pkg['jsnext:main'];
   }
   return pkg;
 }

From 5478a40035a1a780026317b80bd210e28728a40b Mon Sep 17 00:00:00 2001
From: Mustafa Haddara <mhaddara@pagerduty.com>
Date: Tue, 27 Jul 2021 09:38:02 -0400
Subject: [PATCH 316/767] [Tests] update webpack resolver unit tests to check
 `module` resolution

---
 .../test/package-mains/module-and-jsnext/package.json        | 5 +++++
 .../test/package-mains/module-and-jsnext/src/index.js        | 0
 resolvers/webpack/test/packageMains.js                       | 5 +++++
 3 files changed, 10 insertions(+)
 create mode 100644 resolvers/webpack/test/package-mains/module-and-jsnext/package.json
 create mode 100644 resolvers/webpack/test/package-mains/module-and-jsnext/src/index.js

diff --git a/resolvers/webpack/test/package-mains/module-and-jsnext/package.json b/resolvers/webpack/test/package-mains/module-and-jsnext/package.json
new file mode 100644
index 0000000000..4b1355aaed
--- /dev/null
+++ b/resolvers/webpack/test/package-mains/module-and-jsnext/package.json
@@ -0,0 +1,5 @@
+{
+  "main": "lib/index.js",
+  "module": "src/index.js",
+  "jsnext:main": "lib/index.js"
+}
diff --git a/resolvers/webpack/test/package-mains/module-and-jsnext/src/index.js b/resolvers/webpack/test/package-mains/module-and-jsnext/src/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/resolvers/webpack/test/packageMains.js b/resolvers/webpack/test/packageMains.js
index ed9c79a398..96becbc8ce 100644
--- a/resolvers/webpack/test/packageMains.js
+++ b/resolvers/webpack/test/packageMains.js
@@ -21,6 +21,11 @@ describe('packageMains', function () {
       .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
   });
 
+  it('captures module instead of jsnext', function () {
+    expect(webpack.resolve('./module-and-jsnext', file)).property('path')
+      .to.equal(path.join(__dirname, 'package-mains', 'module-and-jsnext', 'src', 'index.js'));
+  });
+
   it('captures webpack', function () {
     expect(webpack.resolve('./webpack', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'webpack.js'));

From 8dd13e8b3df79b00f89aa21207790d0caa7e3c77 Mon Sep 17 00:00:00 2001
From: Mustafa Haddara <mhaddara@pagerduty.com>
Date: Tue, 27 Jul 2021 09:38:29 -0400
Subject: [PATCH 317/767] [Tests] add unit tests for node resolver `module` and
 `jsnext:main` resolution

---
 .../test/package-mains/jsnext/package.json    |  4 +++
 .../test/package-mains/jsnext/src/index.js    |  0
 .../module-and-jsnext/package.json            |  5 ++++
 .../module-and-jsnext/src/index.js            |  0
 .../test/package-mains/module/package.json    |  4 +++
 .../test/package-mains/module/src/index.js    |  0
 .../node/test/package-mains/package.json      |  1 +
 resolvers/node/test/packageMains.js           | 27 +++++++++++++++++++
 8 files changed, 41 insertions(+)
 create mode 100644 resolvers/node/test/package-mains/jsnext/package.json
 create mode 100644 resolvers/node/test/package-mains/jsnext/src/index.js
 create mode 100644 resolvers/node/test/package-mains/module-and-jsnext/package.json
 create mode 100644 resolvers/node/test/package-mains/module-and-jsnext/src/index.js
 create mode 100644 resolvers/node/test/package-mains/module/package.json
 create mode 100644 resolvers/node/test/package-mains/module/src/index.js
 create mode 100644 resolvers/node/test/package-mains/package.json
 create mode 100644 resolvers/node/test/packageMains.js

diff --git a/resolvers/node/test/package-mains/jsnext/package.json b/resolvers/node/test/package-mains/jsnext/package.json
new file mode 100644
index 0000000000..d336fedaf4
--- /dev/null
+++ b/resolvers/node/test/package-mains/jsnext/package.json
@@ -0,0 +1,4 @@
+{
+  "main": "lib/index.js",
+  "jsnext:main": "src/index.js"
+}
diff --git a/resolvers/node/test/package-mains/jsnext/src/index.js b/resolvers/node/test/package-mains/jsnext/src/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/resolvers/node/test/package-mains/module-and-jsnext/package.json b/resolvers/node/test/package-mains/module-and-jsnext/package.json
new file mode 100644
index 0000000000..4b1355aaed
--- /dev/null
+++ b/resolvers/node/test/package-mains/module-and-jsnext/package.json
@@ -0,0 +1,5 @@
+{
+  "main": "lib/index.js",
+  "module": "src/index.js",
+  "jsnext:main": "lib/index.js"
+}
diff --git a/resolvers/node/test/package-mains/module-and-jsnext/src/index.js b/resolvers/node/test/package-mains/module-and-jsnext/src/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/resolvers/node/test/package-mains/module/package.json b/resolvers/node/test/package-mains/module/package.json
new file mode 100644
index 0000000000..3a80819f88
--- /dev/null
+++ b/resolvers/node/test/package-mains/module/package.json
@@ -0,0 +1,4 @@
+{
+  "main": "lib/index.js",
+  "module": "src/index.js"
+}
diff --git a/resolvers/node/test/package-mains/module/src/index.js b/resolvers/node/test/package-mains/module/src/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/resolvers/node/test/package-mains/package.json b/resolvers/node/test/package-mains/package.json
new file mode 100644
index 0000000000..0a5fb6e237
--- /dev/null
+++ b/resolvers/node/test/package-mains/package.json
@@ -0,0 +1 @@
+{ "dummy": true }
\ No newline at end of file
diff --git a/resolvers/node/test/packageMains.js b/resolvers/node/test/packageMains.js
new file mode 100644
index 0000000000..0a7d9463c7
--- /dev/null
+++ b/resolvers/node/test/packageMains.js
@@ -0,0 +1,27 @@
+'use strict';
+
+const chai = require('chai');
+const expect = chai.expect;
+const path = require('path');
+
+const webpack = require('../');
+
+const file = path.join(__dirname, 'package-mains', 'dummy.js');
+
+
+describe('packageMains', function () {
+  it('captures module', function () {
+    expect(webpack.resolve('./module', file)).property('path')
+      .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'));
+  });
+
+  it('captures jsnext', function () {
+    expect(webpack.resolve('./jsnext', file)).property('path')
+      .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
+  });
+
+  it('captures module instead of jsnext', function () {
+    expect(webpack.resolve('./module-and-jsnext', file)).property('path')
+      .to.equal(path.join(__dirname, 'package-mains', 'module-and-jsnext', 'src', 'index.js'));
+  });
+});

From e20db4e02c6dced96aff2d7039187205d15e1085 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 1 Aug 2021 16:51:07 -0700
Subject: [PATCH 318/767] [Tests] eslint v7.32 added a new `fatalErrorCount`
 property to `cli.executeOnFiles` result

---
 tests/src/cli.js | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tests/src/cli.js b/tests/src/cli.js
index 033513ad62..91d3dfc158 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -62,12 +62,18 @@ describe('CLI regression tests', function () {
               },
             ],
             errorCount: 1,
+            ...(semver.satisfies(eslintPkg.version, '>= 7.32') && {
+              fatalErrorCount: 0,
+            }),
             warningCount: 0,
             fixableErrorCount: 0,
             fixableWarningCount: 0,
             source: results.results[0].source, // NewLine-characters might differ depending on git-settings
           },
         ],
+        ...(semver.satisfies(eslintPkg.version, '>= 7.32') && {
+          fatalErrorCount: 0,
+        }),
         errorCount: 1,
         warningCount: 0,
         fixableErrorCount: 0,

From c8876b115cb7af2850a4ee9a529b8a3d822f4648 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 2 Aug 2021 20:19:26 -0700
Subject: [PATCH 319/767] [Dev Deps] update babel to use airbnb preset

---
 .babelrc     | 6 +++---
 package.json | 1 +
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/.babelrc b/.babelrc
index 604f307fee..883c03b79b 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,17 +1,17 @@
 {
-  "presets": [ "es2015-argon" ],
+  "presets": ["airbnb"],
   "sourceMaps": "inline",
   "retainLines": true,
   "env": {
     "test": {
       "plugins": [
         "istanbul",
-        [ "module-resolver", { "root": [ "./src/" ] } ]
+        ["module-resolver", { "root": ["./src/"] }],
       ]
     },
     "testCompiled": {
       "plugins": [
-        [ "module-resolver", { "root": [ "./lib/" ] } ]
+        ["module-resolver", { "root": ["./lib/"] }],
       ]
     }
   }
diff --git a/package.json b/package.json
index eedf4e3504..0bc4237988 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,7 @@
     "babel-eslint": "=8.0.3 || ^8.2.6",
     "babel-plugin-istanbul": "^4.1.6",
     "babel-plugin-module-resolver": "^2.7.1",
+    "babel-preset-airbnb": "^2.6.0",
     "babel-preset-es2015-argon": "latest",
     "babel-preset-flow": "^6.23.0",
     "babel-register": "^6.26.0",

From 376143529b02c7ac3db13b867e61cc80914ad683 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 2 Aug 2021 20:34:16 -0700
Subject: [PATCH 320/767] [eslint] fix eslint failures

---
 .eslintrc                  | 2 +-
 resolvers/webpack/index.js | 8 ++++----
 tests/.eslintrc            | 9 +++++++++
 tests/.eslintrc.yml        | 8 --------
 utils/.eslintrc            | 5 +++++
 utils/parse.js             | 6 +-----
 utils/resolve.js           | 5 +----
 7 files changed, 21 insertions(+), 22 deletions(-)
 create mode 100644 tests/.eslintrc
 delete mode 100644 tests/.eslintrc.yml
 create mode 100644 utils/.eslintrc

diff --git a/.eslintrc b/.eslintrc
index 356666af5d..146ac91d7a 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -15,7 +15,7 @@
     },
     "parserOptions": {
         "sourceType": "module",
-        "ecmaVersion": 6,
+        "ecmaVersion": 2020,
     },
     "rules": {
         "comma-dangle": [2, "always-multiline"],
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index fb03fc4d19..50832f8f31 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -271,18 +271,18 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
     makeRootPlugin(ModulesInRootPlugin, 'module', resolveConfig.root),
     new ModulesInDirectoriesPlugin(
       'module',
-      resolveConfig.modulesDirectories || resolveConfig.modules || ['web_modules', 'node_modules']
+      resolveConfig.modulesDirectories || resolveConfig.modules || ['web_modules', 'node_modules'],
     ),
     makeRootPlugin(ModulesInRootPlugin, 'module', resolveConfig.fallback),
     new ModuleAsFilePlugin('module'),
     new ModuleAsDirectoryPlugin('module'),
     new DirectoryDescriptionFilePlugin(
       'package.json',
-      ['module', 'jsnext:main'].concat(resolveConfig.packageMains || webpack1DefaultMains)
+      ['module', 'jsnext:main'].concat(resolveConfig.packageMains || webpack1DefaultMains),
     ),
     new DirectoryDefaultFilePlugin(['index']),
     new FileAppendPlugin(resolveConfig.extensions || ['', '.webpack.js', '.web.js', '.js']),
-    new ResultSymlinkPlugin()
+    new ResultSymlinkPlugin(),
   );
 
 
@@ -422,7 +422,7 @@ function findConfigPath(configPath, packageDir) {
       }
 
       const maybePath = path.resolve(
-        path.join(packageDir, 'webpack.config' + maybeExtension)
+        path.join(packageDir, 'webpack.config' + maybeExtension),
       );
       if (fs.existsSync(maybePath)) {
         configPath = maybePath;
diff --git a/tests/.eslintrc b/tests/.eslintrc
new file mode 100644
index 0000000000..5720f3fcac
--- /dev/null
+++ b/tests/.eslintrc
@@ -0,0 +1,9 @@
+{
+  "env": {
+    "mocha": true,
+  },
+  "rules": {
+    "max-len": 0,
+    "import/default": 0,
+  },
+}
diff --git a/tests/.eslintrc.yml b/tests/.eslintrc.yml
deleted file mode 100644
index 92b917ed62..0000000000
--- a/tests/.eslintrc.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-parserOptions:
-  ecmaVersion: 8
-env:
-  mocha: true
-rules:
-  max-len: 0
-  import/default: 0
diff --git a/utils/.eslintrc b/utils/.eslintrc
new file mode 100644
index 0000000000..3fd3f5e647
--- /dev/null
+++ b/utils/.eslintrc
@@ -0,0 +1,5 @@
+{
+  "parserOptions": {
+    "ecmaVersion": 6,
+  },
+}
diff --git a/utils/parse.js b/utils/parse.js
index 9cc2380b3a..468a2acdae 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -52,11 +52,7 @@ exports.default = function parse(path, content, context) {
       console.warn('Line ' + e.lineNumber + ', column ' + e.column + ': ' + e.message);
     }
     if (!ast || typeof ast !== 'object') {
-      console.warn(
-        '`parseForESLint` from parser `' +
-          parserPath +
-          '` is invalid and will just be ignored'
-      );
+      console.warn('`parseForESLint` from parser `' + parserPath + '` is invalid and will just be ignored');
     } else {
       return ast;
     }
diff --git a/utils/resolve.js b/utils/resolve.js
index ea5bf5a150..ab9f13d5e8 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -217,10 +217,7 @@ const erroredContexts = new Set();
  */
 function resolve(p, context) {
   try {
-    return relative( p
-      , context.getFilename()
-      , context.settings
-    );
+    return relative(p, context.getFilename(), context.settings);
   } catch (err) {
     if (!erroredContexts.has(context)) {
       // The `err.stack` string starts with `err.name` followed by colon and `err.message`.

From bfab4cc50821ff621c65e0061f02c5e1a14e424a Mon Sep 17 00:00:00 2001
From: Patrick McElhaney <pmcelhaney@gmail.com>
Date: Wed, 21 Jul 2021 09:38:44 -0400
Subject: [PATCH 321/767] [Fix] Use `context.getPhysicalFilename()` when
 available (ESLint 7.28+)

---
 CHANGELOG.md                            |   3 +
 src/core/packagePath.js                 |   2 +-
 src/rules/named.js                      |   2 +-
 src/rules/newline-after-import.js       |   6 +-
 src/rules/no-cycle.js                   |   2 +-
 src/rules/no-extraneous-dependencies.js |   4 +-
 src/rules/no-import-module-exports.js   |   4 +-
 src/rules/no-relative-packages.js       |   2 +-
 src/rules/no-relative-parent-imports.js |   2 +-
 src/rules/no-restricted-paths.js        |   2 +-
 src/rules/no-self-import.js             |   2 +-
 src/rules/no-unassigned-import.js       |   2 +-
 src/rules/no-unused-modules.js          |   2 +-
 src/rules/no-useless-path-segments.js   |   2 +-
 tests/src/core/getExports.js            |  17 ++-
 tests/src/core/resolve.js               | 154 ++++++++++++++++++++++++
 utils/resolve.js                        |   2 +-
 17 files changed, 187 insertions(+), 23 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 294529304a..e8173955f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
 - [`extensions`]: avoid crashing on partially typed import/export statements ([#2118], thanks [@ljharb])
 - [`no-extraneous-dependencies`]: add ESM intermediate package.json support] ([#2121], thanks [@paztis])
+ - Use `context.getPhysicalFilename()` when available (ESLint 7.28+) ([#2160], thanks [@pmcelhaney])
 
 ### Changed
 - [Docs] `extensions`: removed incorrect cases ([#2138], thanks [@wenfangdu])
@@ -809,6 +810,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2160]: https://github.com/benmosher/eslint-plugin-import/pull/2160
 [#2158]: https://github.com/benmosher/eslint-plugin-import/pull/2158
 [#2138]: https://github.com/benmosher/eslint-plugin-import/pull/2138
 [#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
@@ -1374,6 +1376,7 @@ for info on changes for earlier releases.
 [@paztis]: https://github.com/paztis
 [@pcorpet]: https://github.com/pcorpet
 [@Pessimistress]: https://github.com/Pessimistress
+[@pmcelhaney]: https://github.com/pmcelhaney
 [@preco21]: https://github.com/preco21
 [@pzhine]: https://github.com/pzhine
 [@ramasilveyra]: https://github.com/ramasilveyra
diff --git a/src/core/packagePath.js b/src/core/packagePath.js
index 315ec0918c..a8c3c67632 100644
--- a/src/core/packagePath.js
+++ b/src/core/packagePath.js
@@ -4,7 +4,7 @@ import readPkgUp from 'read-pkg-up';
 
 
 export function getContextPackagePath(context) {
-  return getFilePackagePath(context.getFilename());
+  return getFilePackagePath(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
 }
 
 export function getFilePackagePath(filePath) {
diff --git a/src/rules/named.js b/src/rules/named.js
index c4ce5ea915..7dee06ce10 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -43,7 +43,7 @@ module.exports = {
         if (!deepLookup.found) {
           if (deepLookup.path.length > 1) {
             const deepPath = deepLookup.path
-              .map(i => path.relative(path.dirname(context.getFilename()), i.path))
+              .map(i => path.relative(path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename()), i.path))
               .join(' -> ');
 
             context.report(im[key],
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index f9a817846b..cf5dce831e 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -48,7 +48,7 @@ function isExportDefaultClass(node) {
 }
 
 function isExportNameClass(node) {
-  
+
   return node.type === 'ExportNamedDeclaration' && node.declaration && node.declaration.type === 'ClassDeclaration';
 }
 
@@ -124,7 +124,7 @@ after ${type} statement not followed by another ${type}.`,
       const { parent } = node;
       const nodePosition = parent.body.indexOf(node);
       const nextNode = parent.body[nodePosition + 1];
-        
+
       // skip "export import"s
       if (node.type === 'TSImportEqualsDeclaration' && node.isExport) {
         return;
@@ -144,7 +144,7 @@ after ${type} statement not followed by another ${type}.`,
         }
       },
       'Program:exit': function () {
-        log('exit processing for', context.getFilename());
+        log('exit processing for', context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
         const scopeBody = getScopeBody(context.getScope());
         log('got scope:', scopeBody);
 
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 9d9a28cd66..ec4cfeae9a 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -37,7 +37,7 @@ module.exports = {
   },
 
   create: function (context) {
-    const myPath = context.getFilename();
+    const myPath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
     if (myPath === '<text>') return {}; // can't cycle-check a non-file
 
     const options = context.options[0] || {};
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 7e46ac34bc..9403931f53 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -69,7 +69,7 @@ function getDependencies(context, packageDir) {
       Object.assign(
         packageContent,
         extractDepFields(
-          readPkgUp.sync({ cwd: context.getFilename(), normalize: false }).pkg
+          readPkgUp.sync({ cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), normalize: false }).pkg
         )
       );
     }
@@ -254,7 +254,7 @@ module.exports = {
 
   create: function (context) {
     const options = context.options[0] || {};
-    const filename = context.getFilename();
+    const filename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
     const deps = getDependencies(context, options.packageDir) || extractDepFields({});
 
     const depsOptions = {
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index 8ce5f4c9ac..50ba212c87 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -3,7 +3,7 @@ import path from 'path';
 import pkgUp from 'pkg-up';
 
 function getEntryPoint(context) {
-  const pkgPath = pkgUp.sync(context.getFilename());
+  const pkgPath = pkgUp.sync(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
   try {
     return require.resolve(path.dirname(pkgPath));
   } catch (error) {
@@ -39,7 +39,7 @@ module.exports = {
     let alreadyReported = false;
 
     function report(node) {
-      const fileName = context.getFilename();
+      const fileName = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
       const isEntryPoint = entryPoint === fileName;
       const isIdentifier = node.object.type === 'Identifier';
       const hasKeywords = (/^(module|exports)$/).test(node.object.name);
diff --git a/src/rules/no-relative-packages.js b/src/rules/no-relative-packages.js
index a654c08393..90c1ecc701 100644
--- a/src/rules/no-relative-packages.js
+++ b/src/rules/no-relative-packages.js
@@ -21,7 +21,7 @@ function checkImportForRelativePackage(context, importPath, node) {
   }
 
   const resolvedImport = resolve(importPath, context);
-  const resolvedContext = context.getFilename();
+  const resolvedContext = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
 
   if (!resolvedImport || !resolvedContext) {
     return;
diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js
index 9826da826b..8e3696275b 100644
--- a/src/rules/no-relative-parent-imports.js
+++ b/src/rules/no-relative-parent-imports.js
@@ -15,7 +15,7 @@ module.exports = {
   },
 
   create: function noRelativePackages(context) {
-    const myPath = context.getFilename();
+    const myPath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
     if (myPath === '<text>') return {}; // can't check a non-file
 
     function checkSourceValue(sourceNode) {
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 6409ff57ac..058aa43ea8 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -52,7 +52,7 @@ module.exports = {
     const options = context.options[0] || {};
     const restrictedPaths = options.zones || [];
     const basePath = options.basePath || process.cwd();
-    const currentFilename = context.getFilename();
+    const currentFilename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
     const matchingZones = restrictedPaths.filter((zone) => {
       const targetPath = path.resolve(basePath, zone.target);
 
diff --git a/src/rules/no-self-import.js b/src/rules/no-self-import.js
index a10be56786..58c393b662 100644
--- a/src/rules/no-self-import.js
+++ b/src/rules/no-self-import.js
@@ -8,7 +8,7 @@ import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 function isImportingSelf(context, node, requireName) {
-  const filePath = context.getFilename();
+  const filePath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
 
   // If the input is from stdin, this test can't fail
   if (filePath !== '<text>' && filePath === resolve(requireName, context)) {
diff --git a/src/rules/no-unassigned-import.js b/src/rules/no-unassigned-import.js
index ed292e9128..37be903e0b 100644
--- a/src/rules/no-unassigned-import.js
+++ b/src/rules/no-unassigned-import.js
@@ -32,7 +32,7 @@ function testIsAllow(globs, filename, source) {
 
 function create(context) {
   const options = context.options[0] || {};
-  const filename = context.getFilename();
+  const filename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
   const isAllow = source => testIsAllow(options.allow, filename, source);
 
   return {
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 99b564edab..205259eef9 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -463,7 +463,7 @@ module.exports = {
       doPreparation(src, ignoreExports, context);
     }
 
-    const file = context.getFilename();
+    const file = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
 
     const checkExportPresence = node => {
       if (!missingExports) {
diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index b22aa94788..a058608028 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -58,7 +58,7 @@ module.exports = {
   },
 
   create(context) {
-    const currentDir = path.dirname(context.getFilename());
+    const currentDir = path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
     const options = context.options[0];
 
     function checkSourceValue(source) {
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 5a9bdadb15..74c8d9ee93 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -11,11 +11,18 @@ import { getFilename } from '../utils';
 import * as unambiguous from 'eslint-module-utils/unambiguous';
 
 describe('ExportMap', function () {
-  const fakeContext = {
-    getFilename: getFilename,
-    settings: {},
-    parserPath: 'babel-eslint',
-  };
+  const fakeContext = Object.assign(
+    semver.satisfies(eslintPkg.version, '>= 7.28') ? {
+      getFilename: function () { throw new Error('Should call getPhysicalFilename() instead of getFilename()'); },
+      getPhysicalFilename: getFilename,
+    } : {
+      getFilename,
+    },
+    {
+      settings: {},
+      parserPath: 'babel-eslint',
+    },
+  );
 
   it('handles ExportAllDeclaration', function () {
     let imports;
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index b8deaa6d25..ccfe5f6c27 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -1,4 +1,6 @@
 import { expect } from 'chai';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
 import resolve, { CASE_SENSITIVE_FS, fileExistsWithCaseSync } from 'eslint-module-utils/resolve';
 import ModuleCache from 'eslint-module-utils/ModuleCache';
@@ -162,6 +164,158 @@ describe('resolve', function () {
     expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
   });
 
+  // context.getPhysicalFilename() is available in ESLint 7.28+
+  (semver.satisfies(eslintPkg.version, '>= 7.28') ? describe : describe.skip)('getPhysicalFilename()', () => {
+    function unexpectedCallToGetFilename() {
+      throw new Error('Expected to call to getPhysicalFilename() instead of getFilename()');
+    }
+
+    it('resolves via a custom resolver with interface version 1', function () {
+      const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' });
+
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(utils.testFilePath('./bar.jsx'));
+
+      expect(resolve( '../files/exception'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('exception.js'); } }),
+      )).to.equal(undefined);
+
+      expect(resolve( '../files/not-found'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('not-found.js'); } }),
+      )).to.equal(undefined);
+    });
+
+    it('resolves via a custom resolver with interface version 1 assumed if not specified', function () {
+      const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' });
+
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(utils.testFilePath('./bar.jsx'));
+
+      expect(resolve( '../files/exception'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('exception.js'); } }),
+      )).to.equal(undefined);
+
+      expect(resolve( '../files/not-found'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('not-found.js'); } }),
+      )).to.equal(undefined);
+    });
+
+    it('resolves via a custom resolver with interface version 2', function () {
+      const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v2' });
+      const testContextReports = [];
+      testContext.report = function (reportInfo) {
+        testContextReports.push(reportInfo);
+      };
+
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(utils.testFilePath('./bar.jsx'));
+
+      testContextReports.length = 0;
+      expect(resolve( '../files/exception'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('exception.js'); } }),
+      )).to.equal(undefined);
+      expect(testContextReports[0]).to.be.an('object');
+      expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>');
+      expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
+
+      testContextReports.length = 0;
+      expect(resolve( '../files/not-found'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('not-found.js'); } }),
+      )).to.equal(undefined);
+      expect(testContextReports.length).to.equal(0);
+    });
+
+    it('respects import/resolver as array of strings', function () {
+      const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
+
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(utils.testFilePath('./bar.jsx'));
+    });
+
+    it('respects import/resolver as object', function () {
+      const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } });
+
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(utils.testFilePath('./bar.jsx'));
+    });
+
+    it('respects import/resolver as array of objects', function () {
+      const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
+
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(utils.testFilePath('./bar.jsx'));
+    });
+
+    it('finds resolvers from the source files rather than eslint-module-utils', function () {
+      const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } });
+
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(utils.testFilePath('./bar.jsx'));
+    });
+
+    it('reports invalid import/resolver config', function () {
+      const testContext = utils.testContext({ 'import/resolver': 123.456 });
+      const testContextReports = [];
+      testContext.report = function (reportInfo) {
+        testContextReports.push(reportInfo);
+      };
+
+      testContextReports.length = 0;
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(undefined);
+      expect(testContextReports[0]).to.be.an('object');
+      expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config');
+      expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
+    });
+
+    it('reports loaded resolver with invalid interface', function () {
+      const resolverName = './foo-bar-resolver-invalid';
+      const testContext = utils.testContext({ 'import/resolver': resolverName });
+      const testContextReports = [];
+      testContext.report = function (reportInfo) {
+        testContextReports.push(reportInfo);
+      };
+      testContextReports.length = 0;
+      expect(resolve( '../files/foo'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+      )).to.equal(undefined);
+      expect(testContextReports[0]).to.be.an('object');
+      expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`);
+      expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
+    });
+
+    it('respects import/resolve extensions', function () {
+      const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] } });
+
+      expect(resolve( './jsx/MyCoolComponent'
+        , testContext,
+      )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx'));
+    });
+
+    it('reports load exception in a user resolver', function () {
+      const testContext = utils.testContext({ 'import/resolver': './load-error-resolver' });
+      const testContextReports = [];
+      testContext.report = function (reportInfo) {
+        testContextReports.push(reportInfo);
+      };
+
+      expect(resolve( '../files/exception'
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('exception.js'); } }),
+      )).to.equal(undefined);
+      expect(testContextReports[0]).to.be.an('object');
+      expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>');
+      expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
+    });
+  });
+
   const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip);
   caseDescribe('case sensitivity', function () {
     let file;
diff --git a/utils/resolve.js b/utils/resolve.js
index ab9f13d5e8..f488ea798f 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -217,7 +217,7 @@ const erroredContexts = new Set();
  */
 function resolve(p, context) {
   try {
-    return relative(p, context.getFilename(), context.settings);
+    return relative(p, context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), context.settings);
   } catch (err) {
     if (!erroredContexts.has(context)) {
       // The `err.stack` string starts with `err.name` followed by colon and `err.message`.

From b236748e39d97dae4be873e06b77c411e178b654 Mon Sep 17 00:00:00 2001
From: Bryan Lee <doslby@gmail.com>
Date: Thu, 22 Jul 2021 14:39:55 +0800
Subject: [PATCH 322/767] [Docs] `order`:  improve the documentation for the
 `pathGroupsExcludedImportTypes` option

---
 CHANGELOG.md        |  3 +++
 docs/rules/order.md | 21 +++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e8173955f6..a6ddbb8030 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - [Docs] `extensions`: removed incorrect cases ([#2138], thanks [@wenfangdu])
 - [Tests] `order`: add tests for `pathGroupsExcludedImportTypes: ['type']` ([#2158], thanks [@atav32])
+- [Docs] `order`:  improve the documentation for the `pathGroupsExcludedImportTypes` option ([#2156], thanks [@liby])
 
 ## [2.23.4] - 2021-05-29
 
@@ -812,6 +813,7 @@ for info on changes for earlier releases.
 
 [#2160]: https://github.com/benmosher/eslint-plugin-import/pull/2160
 [#2158]: https://github.com/benmosher/eslint-plugin-import/pull/2158
+[#2156]: https://github.com/benmosher/eslint-plugin-import/pull/2156
 [#2138]: https://github.com/benmosher/eslint-plugin-import/pull/2138
 [#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
 [#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
@@ -1347,6 +1349,7 @@ for info on changes for earlier releases.
 [@lencioni]: https://github.com/lencioni
 [@leonardodino]: https://github.com/leonardodino
 [@Librazy]: https://github.com/Librazy
+[@liby]: https://github.com/liby
 [@lilling]: https://github.com/lilling
 [@ljharb]: https://github.com/ljharb
 [@ljqx]: https://github.com/ljqx
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 848c91ddef..e320ee0c87 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -148,6 +148,27 @@ Example:
   }]
 }
 ```
+
+You can also use `patterns`(e.g., `react`, `react-router-dom`, etc).
+
+Example:
+```json
+{
+  "import/order": [
+    "error",
+    {
+      "pathGroups": [
+        {
+          "pattern": "react",
+          "group": "builtin",
+          "position": "before"
+        }
+      ],
+      "pathGroupsExcludedImportTypes": ["react"]
+    }
+  ]
+}
+```
 The default value is `["builtin", "external"]`.
 
 ### `newlines-between: [ignore|always|always-and-inside-groups|never]`:

From 00d7bc8e512622c1ecabf0b56f36b504d29b926d Mon Sep 17 00:00:00 2001
From: Rafael Perello <rafael.perello@omniaccess.com>
Date: Tue, 6 Jul 2021 14:26:20 +0200
Subject: [PATCH 323/767] [Fix] `extensions`/`importType`: fix isScoped
 treating @/abc as scoped module

Fixes #2145
---
 CHANGELOG.md                  |  5 ++++-
 src/core/importType.js        |  2 +-
 tests/src/core/importType.js  | 11 ++++++++++-
 tests/src/rules/extensions.js | 10 ++++++++++
 4 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6ddbb8030..53cc782407 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
 - [`extensions`]: avoid crashing on partially typed import/export statements ([#2118], thanks [@ljharb])
 - [`no-extraneous-dependencies`]: add ESM intermediate package.json support] ([#2121], thanks [@paztis])
- - Use `context.getPhysicalFilename()` when available (ESLint 7.28+) ([#2160], thanks [@pmcelhaney])
+- Use `context.getPhysicalFilename()` when available (ESLint 7.28+) ([#2160], thanks [@pmcelhaney])
+- [`extensions`]/`importType`: fix isScoped treating @/abc as scoped module ([#2146], thanks [@rperello])
 
 ### Changed
 - [Docs] `extensions`: removed incorrect cases ([#2138], thanks [@wenfangdu])
@@ -814,6 +815,7 @@ for info on changes for earlier releases.
 [#2160]: https://github.com/benmosher/eslint-plugin-import/pull/2160
 [#2158]: https://github.com/benmosher/eslint-plugin-import/pull/2158
 [#2156]: https://github.com/benmosher/eslint-plugin-import/pull/2156
+[#2146]: https://github.com/benmosher/eslint-plugin-import/pull/2146
 [#2138]: https://github.com/benmosher/eslint-plugin-import/pull/2138
 [#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
 [#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
@@ -1391,6 +1393,7 @@ for info on changes for earlier releases.
 [@richardxia]: https://github.com/richardxia
 [@robertrossmann]: https://github.com/robertrossmann
 [@rosswarren]: https://github.com/rosswarren
+[@rperello]: https://github.com/rperello
 [@rsolomon]: https://github.com/rsolomon
 [@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w
 [@saschanaz]: https://github.com/saschanaz
diff --git a/src/core/importType.js b/src/core/importType.js
index ecea976f4a..8457c78535 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -64,7 +64,7 @@ function isModuleMain(name) {
   return name && moduleMainRegExp.test(name);
 }
 
-const scopedRegExp = /^@[^/]*\/?[^/]+/;
+const scopedRegExp = /^@[^/]+\/?[^/]+/;
 export function isScoped(name) {
   return name && scopedRegExp.test(name);
 }
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 371a3d7397..3a50002125 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -1,7 +1,7 @@
 import { expect } from 'chai';
 import * as path from 'path';
 
-import importType, { isExternalModule, isScopedModule } from 'core/importType';
+import importType, { isExternalModule, isScopedModule, isScoped } from 'core/importType';
 
 import { testContext, testFilePath } from '../utils';
 
@@ -241,6 +241,15 @@ describe('importType(name)', function () {
 
   it('correctly identifies scoped modules with `isScopedModule`', () => {
     expect(isScopedModule('@/abc')).to.equal(false);
+    expect(isScopedModule('@/abc/def')).to.equal(false);
     expect(isScopedModule('@a/abc')).to.equal(true);
+    expect(isScopedModule('@a/abc/def')).to.equal(true);
+  });
+
+  it('correctly identifies scoped modules with `isScoped`', () => {
+    expect(isScoped('@/abc')).to.equal(false);
+    expect(isScoped('@/abc/def')).to.equal(false);
+    expect(isScoped('@a/abc')).to.equal(true);
+    expect(isScoped('@a/abc/def')).to.equal(true);
   });
 });
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 4070c6a6bc..0134334558 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -349,6 +349,11 @@ ruleTester.run('extensions', rule, {
           line: 4,
           column: 31,
         },
+        {
+          message: 'Missing file extension for "@/configs/chart"',
+          line: 7,
+          column: 27,
+        },
       ],
     }),
 
@@ -369,6 +374,11 @@ ruleTester.run('extensions', rule, {
           line: 4,
           column: 31,
         },
+        {
+          message: 'Missing file extension for "@/configs/chart"',
+          line: 7,
+          column: 27,
+        },
       ],
     }),
 

From 7163824ddefc01e8dcb3f02cbf482ea946deb6b6 Mon Sep 17 00:00:00 2001
From: vikr01 <vik120@icloud.com>
Date: Thu, 25 Oct 2018 20:42:32 -0700
Subject: [PATCH 324/767] [New] `no-dynamic-require`: add option `esmodule`

See #700.
---
 CHANGELOG.md                          |  4 ++
 src/rules/no-dynamic-require.js       | 33 ++++++++++-
 tests/src/rules/no-dynamic-require.js | 84 +++++++++++++++++++++++++++
 3 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53cc782407..41799fb6d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Added
+- [`no-dynamic-require`]: add option `esmodule` ([#1223], thanks [@vikr01])
+
 ### Fixed
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
 - [`extensions`]: avoid crashing on partially typed import/export statements ([#2118], thanks [@ljharb])
@@ -888,6 +891,7 @@ for info on changes for earlier releases.
 [#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
 [#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
 [#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
+[#1223]: https://github.com/benmosher/eslint-plugin-import/pull/1223
 [#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
 [#1572]: https://github.com/benmosher/eslint-plugin-import/pull/1572
diff --git a/src/rules/no-dynamic-require.js b/src/rules/no-dynamic-require.js
index 0c14df0893..f8900088df 100644
--- a/src/rules/no-dynamic-require.js
+++ b/src/rules/no-dynamic-require.js
@@ -8,6 +8,12 @@ function isRequire(node) {
     node.arguments.length >= 1;
 }
 
+function isDynamicImport(node) {
+  return node &&
+    node.callee &&
+    node.callee.type === 'Import';
+}
+
 function isStaticValue(arg) {
   return arg.type === 'Literal' ||
     (arg.type === 'TemplateLiteral' && arg.expressions.length === 0);
@@ -19,18 +25,39 @@ module.exports = {
     docs: {
       url: docsUrl('no-dynamic-require'),
     },
-    schema: [],
+    schema: [
+      {
+        type: 'object',
+        properties: {
+          esmodule: {
+            type: 'boolean',
+          },
+        },
+        additionalProperties: false,
+      },
+    ],
   },
 
   create: function (context) {
+    const options = context.options[0] || {};
+
     return {
       CallExpression(node) {
-        if (isRequire(node) && !isStaticValue(node.arguments[0])) {
-          context.report({
+        if (!node.arguments[0] || isStaticValue(node.arguments[0])) {
+          return;
+        }
+        if (isRequire(node)) {
+          return context.report({
             node,
             message: 'Calls to require() should use string literals',
           });
         }
+        if (options.esmodule && isDynamicImport(node)) {
+          return context.report({
+            node,
+            message: 'Calls to import() should use string literals',
+          });
+        }
       },
     };
   },
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index 7dba242313..4a70e7bc2b 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -9,6 +9,10 @@ const error = {
   message: 'Calls to require() should use string literals',
 };
 
+const dynamicImportError = {
+  message: 'Calls to import() should use string literals',
+};
+
 ruleTester.run('no-dynamic-require', rule, {
   valid: [
     test({ code: 'import _ from "lodash"' }),
@@ -22,6 +26,59 @@ ruleTester.run('no-dynamic-require', rule, {
     test({ code: 'var foo = require(`foo`)' }),
     test({ code: 'var foo = require("./foo")' }),
     test({ code: 'var foo = require("@scope/foo")' }),
+
+    //dynamic import
+    test({
+      code: 'import("foo")',
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'import(`foo`)',
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'import("./foo")',
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'import("@scope/foo")',
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'var foo = import("foo")',
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'var foo = import(`foo`)',
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'var foo = import("./foo")',
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'var foo = import("@scope/foo")',
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'import("../" + name)',
+      errors: [dynamicImportError],
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: false }],
+    }),
+    test({
+      code: 'import(`../${name}`)',
+      errors: [dynamicImportError],
+      parser: require.resolve('babel-eslint'),
+    }),
   ],
   invalid: [
     test({
@@ -43,6 +100,33 @@ ruleTester.run('no-dynamic-require', rule, {
     test({
       code: 'require(name + "foo", "bar")',
       errors: [error],
+      options: [{ esmodule: true }],
+    }),
+
+    // dynamic import
+    test({
+      code: 'import("../" + name)',
+      errors: [dynamicImportError],
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'import(`../${name}`)',
+      errors: [dynamicImportError],
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'import(name)',
+      errors: [dynamicImportError],
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
+    }),
+    test({
+      code: 'import(name())',
+      errors: [dynamicImportError],
+      parser: require.resolve('babel-eslint'),
+      options: [{ esmodule: true }],
     }),
     test({
       code: 'require(`foo${x}`)',

From 7626a148510cccedd1e4583111b92cd14bfcb630 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 4 Aug 2021 20:53:55 -0700
Subject: [PATCH 325/767] [Refactor] `named`: clean up formatting

---
 src/rules/named.js | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/src/rules/named.js b/src/rules/named.js
index 7dee06ce10..bcf143bebc 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -14,18 +14,23 @@ module.exports = {
   create: function (context) {
     function checkSpecifiers(key, type, node) {
       // ignore local exports and type imports/exports
-      if (node.source == null || node.importKind === 'type' ||
-          node.importKind === 'typeof'  || node.exportKind === 'type') {
+      if (
+        node.source == null
+        || node.importKind === 'type'
+        || node.importKind === 'typeof'
+        || node.exportKind === 'type'
+      ) {
         return;
       }
 
-      if (!node.specifiers
-        .some(function (im) { return im.type === type; })) {
+      if (!node.specifiers.some((im) => im.type === type)) {
         return; // no named imports/exports
       }
 
       const imports = Exports.get(node.source.value, context);
-      if (imports == null) return;
+      if (imports == null) {
+        return;
+      }
 
       if (imports.errors.length) {
         imports.reportErrors(context, node);
@@ -33,10 +38,14 @@ module.exports = {
       }
 
       node.specifiers.forEach(function (im) {
-        if (im.type !== type) return;
+        if (im.type !== type) {
+          return;
+        }
 
         // ignore type imports
-        if (im.importKind === 'type' || im.importKind === 'typeof') return;
+        if (im.importKind === 'type' || im.importKind === 'typeof') {
+          return;
+        }
 
         const deepLookup = imports.hasDeep(im[key].name);
 
@@ -46,27 +55,18 @@ module.exports = {
               .map(i => path.relative(path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename()), i.path))
               .join(' -> ');
 
-            context.report(im[key],
-              `${im[key].name} not found via ${deepPath}`);
+            context.report(im[key], `${im[key].name} not found via ${deepPath}`);
           } else {
-            context.report(im[key],
-              im[key].name + ' not found in \'' + node.source.value + '\'');
+            context.report(im[key], im[key].name + ' not found in \'' + node.source.value + '\'');
           }
         }
       });
     }
 
     return {
-      'ImportDeclaration': checkSpecifiers.bind( null
-        , 'imported'
-        , 'ImportSpecifier'
-      ),
+      ImportDeclaration: checkSpecifiers.bind(null, 'imported', 'ImportSpecifier'),
 
-      'ExportNamedDeclaration': checkSpecifiers.bind( null
-        , 'local'
-        , 'ExportSpecifier'
-      ),
+      ExportNamedDeclaration: checkSpecifiers.bind(null, 'local', 'ExportSpecifier'),
     };
-
   },
 };

From 54d86c8a64dc21c14088fcdd8fc3935206e8347a Mon Sep 17 00:00:00 2001
From: vikr01 <vik120@icloud.com>
Date: Thu, 25 Oct 2018 01:44:45 -0700
Subject: [PATCH 326/767] [New] `named`: add `commonjs` option

---
 CHANGELOG.md             |  4 +-
 src/rules/named.js       | 80 ++++++++++++++++++++++++++++++++++++----
 tests/src/rules/named.js | 59 +++++++++++++++++++++++++++++
 3 files changed, 135 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 41799fb6d9..493c709407 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Added
 - [`no-dynamic-require`]: add option `esmodule` ([#1223], thanks [@vikr01])
+- [`named`]: add `commonjs` option ([#1222], thanks [@vikr01])
 
 ### Fixed
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
@@ -891,7 +892,6 @@ for info on changes for earlier releases.
 [#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
 [#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
 [#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
-[#1223]: https://github.com/benmosher/eslint-plugin-import/pull/1223
 [#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
 [#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
 [#1572]: https://github.com/benmosher/eslint-plugin-import/pull/1572
@@ -963,6 +963,8 @@ for info on changes for earlier releases.
 [#1235]: https://github.com/benmosher/eslint-plugin-import/pull/1235
 [#1234]: https://github.com/benmosher/eslint-plugin-import/pull/1234
 [#1232]: https://github.com/benmosher/eslint-plugin-import/pull/1232
+[#1223]: https://github.com/benmosher/eslint-plugin-import/pull/1223
+[#1222]: https://github.com/benmosher/eslint-plugin-import/pull/1222
 [#1218]: https://github.com/benmosher/eslint-plugin-import/pull/1218
 [#1176]: https://github.com/benmosher/eslint-plugin-import/pull/1176
 [#1163]: https://github.com/benmosher/eslint-plugin-import/pull/1163
diff --git a/src/rules/named.js b/src/rules/named.js
index bcf143bebc..2770d51fa2 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -8,10 +8,22 @@ module.exports = {
     docs: {
       url: docsUrl('named'),
     },
-    schema: [],
+    schema: [
+      {
+        type: 'object',
+        properties: {
+          commonjs: {
+            type: 'boolean',
+          },
+        },
+        additionalProperties: false,
+      },
+    ],
   },
 
   create: function (context) {
+    const options = context.options[0] || {};
+
     function checkSpecifiers(key, type, node) {
       // ignore local exports and type imports/exports
       if (
@@ -38,12 +50,11 @@ module.exports = {
       }
 
       node.specifiers.forEach(function (im) {
-        if (im.type !== type) {
-          return;
-        }
-
-        // ignore type imports
-        if (im.importKind === 'type' || im.importKind === 'typeof') {
+        if (
+          im.type !== type
+          // ignore type imports
+          || im.importKind === 'type' || im.importKind === 'typeof'
+        ) {
           return;
         }
 
@@ -63,10 +74,65 @@ module.exports = {
       });
     }
 
+    function checkRequire(node) {
+      if (
+        !options.commonjs
+        || node.type !== 'VariableDeclarator'
+        // return if it's not an object destructure or it's an empty object destructure
+        || !node.id || node.id.type !== 'ObjectPattern' || node.id.properties.length === 0
+        // return if there is no call expression on the right side
+        || !node.init || node.init.type !== 'CallExpression'
+      ) {
+        return;
+      }
+
+      const call = node.init;
+      const [source] = call.arguments;
+      const variableImports = node.id.properties;
+      const variableExports = Exports.get(source.value, context);
+
+      if (
+        // return if it's not a commonjs require statement
+        call.callee.type !== 'Identifier' || call.callee.name !== 'require' || call.arguments.length !== 1
+        // return if it's not a string source
+        || source.type !== 'Literal'
+        || variableExports == null
+      ) {
+        return;
+      }
+
+      if (variableExports.errors.length) {
+        variableExports.reportErrors(context, node);
+        return;
+      }
+
+      variableImports.forEach(function (im) {
+        if (im.type !== 'Property' || !im.key || im.key.type !== 'Identifier') {
+          return;
+        }
+
+        const deepLookup = variableExports.hasDeep(im.key.name);
+
+        if (!deepLookup.found) {
+          if (deepLookup.path.length > 1) {
+            const deepPath = deepLookup.path
+              .map(i => path.relative(path.dirname(context.getFilename()), i.path))
+              .join(' -> ');
+
+            context.report(im.key, `${im.key.name} not found via ${deepPath}`);
+          } else {
+            context.report(im.key, im.key.name + ' not found in \'' + source.value + '\'');
+          }
+        }
+      });
+    }
+
     return {
       ImportDeclaration: checkSpecifiers.bind(null, 'imported', 'ImportSpecifier'),
 
       ExportNamedDeclaration: checkSpecifiers.bind(null, 'local', 'ExportSpecifier'),
+
+      VariableDeclarator: checkRequire,
     };
   },
 };
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index f09ee20595..57e40c91ac 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -146,6 +146,41 @@ ruleTester.run('named', rule, {
       code: 'import { common } from "./re-export-default"',
     }),
 
+    // destructured requires with commonjs option
+    test({
+      code: 'const { destructuredProp } = require("./named-exports")',
+      options: [{ commonjs: true }],
+    }),
+    test({
+      code: 'let { arrayKeyProp } = require("./named-exports")',
+      options: [{ commonjs: true }],
+    }),
+    test({
+      code: 'const { deepProp } = require("./named-exports")',
+      options: [{ commonjs: true }],
+    }),
+
+    test({
+      code: 'const { foo, bar } = require("./re-export-names")',
+      options: [{ commonjs: true }],
+    }),
+
+    test({
+      code: 'const { baz } = require("./bar")',
+      errors: [error('baz', './bar')],
+    }),
+
+    test({
+      code: 'const { baz } = require("./bar")',
+      errors: [error('baz', './bar')],
+      options: [{ commonjs: false }],
+    }),
+
+    test({
+      code: 'const { default: defExport } = require("./bar")',
+      options: [{ commonjs: true }],
+    }),
+
     ...SYNTAX_CASES,
   ],
 
@@ -201,6 +236,30 @@ ruleTester.run('named', rule, {
       errors: ['baz not found via broken-trampoline.js -> named-exports.js'],
     }),
 
+    test({
+      code: 'const { baz } = require("./bar")',
+      errors: [error('baz', './bar')],
+      options: [{ commonjs: true }],
+    }),
+
+    test({
+      code: 'let { baz } = require("./bar")',
+      errors: [error('baz', './bar')],
+      options: [{ commonjs: true }],
+    }),
+
+    test({
+      code: 'const { baz: bar, bop } = require("./bar"), { a } = require("./re-export-names")',
+      errors: [error('baz', './bar'), error('bop', './bar'), error('a', './re-export-names')],
+      options: [{ commonjs: true }],
+    }),
+
+    test({
+      code: 'const { default: defExport } = require("./named-exports")',
+      errors: [error('default', './named-exports')],
+      options: [{ commonjs: true }],
+    }),
+
     // parse errors
     // test({
     //   code: "import { a } from './test.coffee';",

From bba59c4848cdd31461a9f45ebe79865d28cd3f5f Mon Sep 17 00:00:00 2001
From: Arkadii Berezkin <arkberezkin@yandex-team.ru>
Date: Wed, 2 Jun 2021 16:19:05 +0300
Subject: [PATCH 327/767] [New] `no-namespace`: Add `ignore` option

Closes #1916.
Closes #1903.
---
 CHANGELOG.md                    |  3 +++
 docs/rules/no-namespace.md      | 11 +++++++++++
 src/rules/no-namespace.js       | 31 ++++++++++++++++++++++++-------
 tests/src/rules/no-namespace.js |  1 +
 4 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 493c709407..45aacceb79 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Added
 - [`no-dynamic-require`]: add option `esmodule` ([#1223], thanks [@vikr01])
 - [`named`]: add `commonjs` option ([#1222], thanks [@vikr01])
+- [`no-namespace`]: Add `ignore` option ([#2112], thanks [@aberezkin])
 
 ### Fixed
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
@@ -822,6 +823,7 @@ for info on changes for earlier releases.
 [#2146]: https://github.com/benmosher/eslint-plugin-import/pull/2146
 [#2138]: https://github.com/benmosher/eslint-plugin-import/pull/2138
 [#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
+[#2112]: https://github.com/benmosher/eslint-plugin-import/pull/2112
 [#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
 [#2097]: https://github.com/benmosher/eslint-plugin-import/pull/2097
 [#2090]: https://github.com/benmosher/eslint-plugin-import/pull/2090
@@ -1252,6 +1254,7 @@ for info on changes for earlier releases.
 [@1pete]: https://github.com/1pete
 [@3nuc]: https://github.com/3nuc
 [@aamulumi]: https://github.com/aamulumi
+[@aberezkin]: https://github.com/aberezkin
 [@adamborowski]: https://github.com/adamborowski
 [@adjerbetian]: https://github.com/adjerbetian
 [@ai]: https://github.com/ai
diff --git a/docs/rules/no-namespace.md b/docs/rules/no-namespace.md
index e0b0f0b967..e987260513 100644
--- a/docs/rules/no-namespace.md
+++ b/docs/rules/no-namespace.md
@@ -5,6 +5,12 @@ Enforce a convention of not using namespace (a.k.a. "wildcard" `*`) imports.
 +(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule, provided that the namespace object is only used for direct member access, e.g. `namespace.a`.
 The `--fix` functionality for this rule requires ESLint 5 or newer.
 
+### Options
+
+This rule supports the following options:
+
+- `ignore`: array of glob strings for modules that should be ignored by the rule.
+
 ## Rule Details
 
 Valid:
@@ -15,6 +21,11 @@ import { a, b }  from './bar'
 import defaultExport, { a, b }  from './foobar'
 ```
 
+```js
+/* eslint import/no-namespace: ["error", {ignore: ['*.ext']] */
+import * as bar from './ignored-module.ext';
+```
+
 Invalid:
 
 ```js
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index ca51823a0b..472b93dd09 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -3,6 +3,7 @@
  * @author Radek Benkel
  */
 
+import minimatch from 'minimatch';
 import docsUrl from '../docsUrl';
 
 //------------------------------------------------------------------------------
@@ -17,16 +18,32 @@ module.exports = {
       url: docsUrl('no-namespace'),
     },
     fixable: 'code',
-    schema: [],
+    schema: [{
+      type: 'object',
+      properties: {
+        ignore: {
+          type: 'array',
+          items: {
+            type: 'string',
+          },
+          uniqueItems: true,
+        },
+      },
+    }],
   },
 
   create: function (context) {
+    const firstOption = context.options[0] || {};
+    const ignoreGlobs = firstOption.ignore;
+
     return {
-      'ImportNamespaceSpecifier': function (node) {
+      ImportNamespaceSpecifier(node) {
+        if (ignoreGlobs && ignoreGlobs.find(glob => minimatch(node.parent.source.value, glob, { matchBase: true }))) {
+          return;
+        }
+
         const scopeVariables = context.getScope().variables;
-        const namespaceVariable = scopeVariables.find((variable) =>
-          variable.defs[0].node === node
-        );
+        const namespaceVariable = scopeVariables.find((variable) => variable.defs[0].node === node);
         const namespaceReferences = namespaceVariable.references;
         const namespaceIdentifiers = namespaceReferences.map(reference => reference.identifier);
         const canFix = namespaceIdentifiers.length > 0 && !usesNamespaceAsObject(namespaceIdentifiers);
@@ -63,11 +80,11 @@ module.exports = {
             );
 
             // Replace the ImportNamespaceSpecifier with a list of ImportSpecifiers
-            const namedImportSpecifiers = importNames.map((importName) =>
+            const namedImportSpecifiers = importNames.map((importName) => (
               importName === importLocalNames[importName]
                 ? importName
                 : `${importName} as ${importLocalNames[importName]}`
-            );
+            ));
             fixes.push(fixer.replaceText(node, `{ ${namedImportSpecifiers.join(', ')} }`));
 
             // Pass 2: Replace references to the namespace with references to the named imports
diff --git a/tests/src/rules/no-namespace.js b/tests/src/rules/no-namespace.js
index d7c4c9cf8f..d75928c1d8 100644
--- a/tests/src/rules/no-namespace.js
+++ b/tests/src/rules/no-namespace.js
@@ -78,6 +78,7 @@ ruleTester.run('no-namespace', require('rules/no-namespace'), {
     { code: 'import { a, b } from \'./foo\';', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
     { code: 'import bar from \'bar\';', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
     { code: 'import bar from \'./bar\';', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
+    { code: 'import * as bar from \'./ignored-module.ext\';', parserOptions: { ecmaVersion: 2015, sourceType: 'module' }, options: [{ ignore: ['*.ext'] }] },
   ],
 
   invalid: [

From b743a650e9d474fcd5a4252b01c522adcc11b65c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Fermann?= <rene.fermann@gmx.de>
Date: Mon, 6 Jul 2020 10:02:53 +0200
Subject: [PATCH 328/767] [New] `max-dependencies`: add option
 `ignoreTypeImports`

---
 CHANGELOG.md                        |  2 +
 src/rules/max-dependencies.js       | 18 ++++++---
 tests/src/rules/max-dependencies.js | 57 ++++++++++++++++++++++++++++-
 3 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 45aacceb79..d4163b8fce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-dynamic-require`]: add option `esmodule` ([#1223], thanks [@vikr01])
 - [`named`]: add `commonjs` option ([#1222], thanks [@vikr01])
 - [`no-namespace`]: Add `ignore` option ([#2112], thanks [@aberezkin])
+- [`max-dependencies`]: add option `ignoreTypeImports` ([#1847], thanks [@rfermann])
 
 ### Fixed
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
@@ -853,6 +854,7 @@ for info on changes for earlier releases.
 [#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
 [#1860]: https://github.com/benmosher/eslint-plugin-import/pull/1860
 [#1848]: https://github.com/benmosher/eslint-plugin-import/pull/1848
+[#1847]: https://github.com/benmosher/eslint-plugin-import/pull/1847
 [#1846]: https://github.com/benmosher/eslint-plugin-import/pull/1846
 [#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
 [#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
diff --git a/src/rules/max-dependencies.js b/src/rules/max-dependencies.js
index c8e1b3ab13..f9bdd12e51 100644
--- a/src/rules/max-dependencies.js
+++ b/src/rules/max-dependencies.js
@@ -2,15 +2,14 @@ import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 const DEFAULT_MAX = 10;
+const DEFAULT_IGNORE_TYPE_IMPORTS = false;
+const TYPE_IMPORT = 'type';
 
 const countDependencies = (dependencies, lastNode, context) => {
   const { max } = context.options[0] || { max: DEFAULT_MAX };
 
   if (dependencies.size > max) {
-    context.report(
-      lastNode,
-      `Maximum number of dependencies (${max}) exceeded.`
-    );
+    context.report(lastNode, `Maximum number of dependencies (${max}) exceeded.`);
   }
 };
 
@@ -26,6 +25,7 @@ module.exports = {
         'type': 'object',
         'properties': {
           'max': { 'type': 'number' },
+          'ignoreTypeImports': { 'type': 'boolean' },
         },
         'additionalProperties': false,
       },
@@ -33,6 +33,10 @@ module.exports = {
   },
 
   create: context => {
+    const {
+      ignoreTypeImports = DEFAULT_IGNORE_TYPE_IMPORTS,
+    } = context.options[0] || {};
+
     const dependencies = new Set(); // keep track of dependencies
     let lastNode; // keep track of the last node to report on
 
@@ -40,8 +44,10 @@ module.exports = {
       'Program:exit': function () {
         countDependencies(dependencies, lastNode, context);
       },
-    }, moduleVisitor((source) => {
-      dependencies.add(source.value);
+    }, moduleVisitor((source, { importKind }) => {
+      if (importKind !== TYPE_IMPORT || !ignoreTypeImports) {
+        dependencies.add(source.value);
+      }
       lastNode = source;
     }, { commonjs: true }));
   },
diff --git a/tests/src/rules/max-dependencies.js b/tests/src/rules/max-dependencies.js
index f4e5f9a976..1251af97e8 100644
--- a/tests/src/rules/max-dependencies.js
+++ b/tests/src/rules/max-dependencies.js
@@ -1,6 +1,8 @@
-import { test } from '../utils';
+import { test, getTSParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
+import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/max-dependencies');
@@ -74,5 +76,58 @@ ruleTester.run('max-dependencies', rule, {
         'Maximum number of dependencies (1) exceeded.',
       ],
     }),
+
+    test({
+      code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'; import type { z } from \'./baz\'',
+      parser: require.resolve('babel-eslint'),
+      options: [{
+        max: 2,
+        ignoreTypeImports: false,
+      }],
+      errors: [
+        'Maximum number of dependencies (2) exceeded.',
+      ],
+    }),
   ],
 });
+
+context('TypeScript', { skip: semver.satisfies(eslintPkg.version, '>5.0.0') }, () => {
+  getTSParsers().forEach((parser) => {
+    ruleTester.run(`max-dependencies (${parser.replace(process.cwd(), '.')})`, rule, {
+      valid: [    
+        test({
+          code: 'import type { x } from \'./foo\'; import { y } from \'./bar\';',
+          parser: parser,
+          options: [{
+            max: 1,
+            ignoreTypeImports: true,
+          }],
+        }),
+      ],
+      invalid: [    
+        test({
+          code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'',
+          parser: parser,
+          options: [{
+            max: 1,
+          }],
+          errors: [
+            'Maximum number of dependencies (1) exceeded.',
+          ],
+        }),
+    
+        test({
+          code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'; import type { z } from \'./baz\'',
+          parser: parser,
+          options: [{
+            max: 2,
+            ignoreTypeImports: false,
+          }],
+          errors: [
+            'Maximum number of dependencies (2) exceeded.',
+          ],
+        }),
+      ],
+    });
+  });
+});

From 429f3f60238356d1d6c1019be988bccad7def0e0 Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Thu, 24 Oct 2019 23:11:59 +0300
Subject: [PATCH 329/767] [Tests] `no-cycle`: Restructure test files

---
 CHANGELOG.md                                  |   9 +-
 tests/files/cycles/depth-one.js               |   2 -
 tests/files/cycles/es6/depth-one.js           |   2 +
 .../cycles/{ => es6}/depth-three-indirect.js  |   0
 .../cycles/{ => es6}/depth-three-star.js      |   0
 tests/files/cycles/{ => es6}/depth-two.js     |   0
 tests/files/cycles/flow-types-depth-two.js    |   2 +-
 tests/src/rules/no-cycle.js                   | 216 +++++++++---------
 8 files changed, 122 insertions(+), 109 deletions(-)
 delete mode 100644 tests/files/cycles/depth-one.js
 create mode 100644 tests/files/cycles/es6/depth-one.js
 rename tests/files/cycles/{ => es6}/depth-three-indirect.js (100%)
 rename tests/files/cycles/{ => es6}/depth-three-star.js (100%)
 rename tests/files/cycles/{ => es6}/depth-two.js (100%)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4163b8fce..266b4ee12d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,9 +20,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extensions`]/`importType`: fix isScoped treating @/abc as scoped module ([#2146], thanks [@rperello])
 
 ### Changed
-- [Docs] `extensions`: removed incorrect cases ([#2138], thanks [@wenfangdu])
-- [Tests] `order`: add tests for `pathGroupsExcludedImportTypes: ['type']` ([#2158], thanks [@atav32])
-- [Docs] `order`:  improve the documentation for the `pathGroupsExcludedImportTypes` option ([#2156], thanks [@liby])
+- [Docs] [`extensions`]: removed incorrect cases ([#2138], thanks [@wenfangdu])
+- [Tests] [`order`]: add tests for `pathGroupsExcludedImportTypes: ['type']` ([#2158], thanks [@atav32])
+- [Docs] [`order`]:  improve the documentation for the `pathGroupsExcludedImportTypes` option ([#2156], thanks [@liby])
+- [Tests] [`no-cycle`]: Restructure test files ([#1517], thanks [@soryy708])
 
 ## [2.23.4] - 2021-05-29
 
@@ -909,6 +910,7 @@ for info on changes for earlier releases.
 [#1526]: https://github.com/benmosher/eslint-plugin-import/pull/1526
 [#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
 [#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
+[#1517]: https://github.com/benmosher/eslint-plugin-import/pull/1517
 [#1507]: https://github.com/benmosher/eslint-plugin-import/pull/1507
 [#1506]: https://github.com/benmosher/eslint-plugin-import/pull/1506
 [#1496]: https://github.com/benmosher/eslint-plugin-import/pull/1496
@@ -1421,6 +1423,7 @@ for info on changes for earlier releases.
 [@skozin]: https://github.com/skozin
 [@skyrpex]: https://github.com/skyrpex
 [@sompylasar]: https://github.com/sompylasar
+[@soryy708]: https://github.com/soryy708
 [@spalger]: https://github.com/spalger
 [@st-sloth]: https://github.com/st-sloth
 [@stekycz]: https://github.com/stekycz
diff --git a/tests/files/cycles/depth-one.js b/tests/files/cycles/depth-one.js
deleted file mode 100644
index 748f65f844..0000000000
--- a/tests/files/cycles/depth-one.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import foo from "./depth-zero"
-export { foo }
diff --git a/tests/files/cycles/es6/depth-one.js b/tests/files/cycles/es6/depth-one.js
new file mode 100644
index 0000000000..9caa762505
--- /dev/null
+++ b/tests/files/cycles/es6/depth-one.js
@@ -0,0 +1,2 @@
+import foo from "../depth-zero"
+export { foo }
diff --git a/tests/files/cycles/depth-three-indirect.js b/tests/files/cycles/es6/depth-three-indirect.js
similarity index 100%
rename from tests/files/cycles/depth-three-indirect.js
rename to tests/files/cycles/es6/depth-three-indirect.js
diff --git a/tests/files/cycles/depth-three-star.js b/tests/files/cycles/es6/depth-three-star.js
similarity index 100%
rename from tests/files/cycles/depth-three-star.js
rename to tests/files/cycles/es6/depth-three-star.js
diff --git a/tests/files/cycles/depth-two.js b/tests/files/cycles/es6/depth-two.js
similarity index 100%
rename from tests/files/cycles/depth-two.js
rename to tests/files/cycles/es6/depth-two.js
diff --git a/tests/files/cycles/flow-types-depth-two.js b/tests/files/cycles/flow-types-depth-two.js
index 9058840ac6..64a0a83591 100644
--- a/tests/files/cycles/flow-types-depth-two.js
+++ b/tests/files/cycles/flow-types-depth-two.js
@@ -1 +1 @@
-import { foo } from './depth-one'
+import { foo } from './es6/depth-one'
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 302db8351b..11fc515f0b 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -1,6 +1,7 @@
 import { test as _test, testFilePath } from '../utils';
 
 import { RuleTester } from 'eslint';
+import flatMap from 'array.prototype.flatmap';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-cycle');
@@ -11,9 +12,10 @@ const test = def => _test(Object.assign(def, {
   filename: testFilePath('./cycles/depth-zero.js'),
 }));
 
-// describe.only("no-cycle", () => {
+const testDialects = ['es6'];
+
 ruleTester.run('no-cycle', rule, {
-  valid: [
+  valid: [].concat(
     // this rule doesn't care if the cycle length is 0
     test({ code: 'import foo from "./foo.js"' }),
 
@@ -32,14 +34,6 @@ ruleTester.run('no-cycle', rule, {
       code: 'var bar = require("./bar")',
       filename: '<text>',
     }),
-    test({
-      code: 'import { foo } from "./depth-two"',
-      options: [{ maxDepth: 1 }],
-    }),
-    test({
-      code: 'import { foo, bar } from "./depth-two"',
-      options: [{ maxDepth: 1 }],
-    }),
     test({
       code: 'import { foo } from "cycles/external/depth-one"',
       options: [{ ignoreExternal: true }],
@@ -56,19 +50,31 @@ ruleTester.run('no-cycle', rule, {
         'import/external-module-folders': ['cycles/external'],
       },
     }),
-    test({
-      code: 'import("./depth-two").then(function({ foo }){})',
-      options: [{ maxDepth: 1 }],
-      parser: require.resolve('babel-eslint'),
-    }),
-    test({
-      code: 'import type { FooType } from "./depth-one"',
-      parser: require.resolve('babel-eslint'),
-    }),
-    test({
-      code: 'import type { FooType, BarType } from "./depth-one"',
-      parser: require.resolve('babel-eslint'),
-    }),
+
+    flatMap(testDialects, (testDialect) => [
+      test({
+        code: `import { foo } from "./${testDialect}/depth-two"`,
+        options: [{ maxDepth: 1 }],
+      }),
+      test({
+        code: `import { foo, bar } from "./${testDialect}/depth-two"`,
+        options: [{ maxDepth: 1 }],
+      }),
+      test({
+        code: `import("./${testDialect}/depth-two").then(function({ foo }){})`,
+        options: [{ maxDepth: 1 }],
+        parser: require.resolve('babel-eslint'),
+      }),
+      test({
+        code: `import type { FooType } from "./${testDialect}/depth-one"`,
+        parser: require.resolve('babel-eslint'),
+      }),
+      test({
+        code: `import type { FooType, BarType } from "./${testDialect}/depth-one"`,
+        parser: require.resolve('babel-eslint'),
+      }),
+    ]),
+
     test({
       code: 'import { bar } from "./flow-types"',
       parser: require.resolve('babel-eslint'),
@@ -81,12 +87,9 @@ ruleTester.run('no-cycle', rule, {
       code: 'import { bar } from "./flow-types-only-importing-multiple-types"',
       parser: require.resolve('babel-eslint'),
     }),
-  ],
-  invalid: [
-    test({
-      code: 'import { foo } from "./depth-one"',
-      errors: [error(`Dependency cycle detected.`)],
-    }),
+  ),
+
+  invalid: [].concat(
     test({
       code: 'import { bar } from "./flow-types-some-type-imports"',
       parser: require.resolve('babel-eslint'),
@@ -108,82 +111,89 @@ ruleTester.run('no-cycle', rule, {
         'import/external-module-folders': ['cycles/external'],
       },
     }),
-    test({
-      code: 'import { foo } from "./depth-one"',
-      options: [{ maxDepth: 1 }],
-      errors: [error(`Dependency cycle detected.`)],
-    }),
-    test({
-      code: 'const { foo } = require("./depth-one")',
-      errors: [error(`Dependency cycle detected.`)],
-      options: [{ commonjs: true }],
-    }),
-    test({
-      code: 'require(["./depth-one"], d1 => {})',
-      errors: [error(`Dependency cycle detected.`)],
-      options: [{ amd: true }],
-    }),
-    test({
-      code: 'define(["./depth-one"], d1 => {})',
-      errors: [error(`Dependency cycle detected.`)],
-      options: [{ amd: true }],
-    }),
-    test({
-      code: 'import { foo } from "./depth-two"',
-      errors: [error(`Dependency cycle via ./depth-one:1`)],
-    }),
-    test({
-      code: 'import { foo } from "./depth-two"',
-      options: [{ maxDepth: 2 }],
-      errors: [error(`Dependency cycle via ./depth-one:1`)],
-    }),
-    test({
-      code: 'const { foo } = require("./depth-two")',
-      errors: [error(`Dependency cycle via ./depth-one:1`)],
-      options: [{ commonjs: true }],
-    }),
-    test({
-      code: 'import { two } from "./depth-three-star"',
-      errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-    }),
-    test({
-      code: 'import one, { two, three } from "./depth-three-star"',
-      errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-    }),
-    test({
-      code: 'import { bar } from "./depth-three-indirect"',
-      errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-    }),
-    test({
-      code: 'import { bar } from "./depth-three-indirect"',
-      errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-      parser: require.resolve('babel-eslint'),
-    }),
-    test({
-      code: 'import("./depth-three-star")',
-      errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-      parser: require.resolve('babel-eslint'),
-    }),
-    test({
-      code: 'import("./depth-three-indirect")',
-      errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-      parser: require.resolve('babel-eslint'),
-    }),
+
+    flatMap(testDialects, (testDialect) => [
+      test({
+        code: `import { foo } from "./${testDialect}/depth-one"`,
+        errors: [error(`Dependency cycle detected.`)],
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-one"`,
+        options: [{ maxDepth: 1 }],
+        errors: [error(`Dependency cycle detected.`)],
+      }),
+      test({
+        code: `const { foo } = require("./${testDialect}/depth-one")`,
+        errors: [error(`Dependency cycle detected.`)],
+        options: [{ commonjs: true }],
+      }),
+      test({
+        code: `require(["./${testDialect}/depth-one"], d1 => {})`,
+        errors: [error(`Dependency cycle detected.`)],
+        options: [{ amd: true }],
+      }),
+      test({
+        code: `define(["./${testDialect}/depth-one"], d1 => {})`,
+        errors: [error(`Dependency cycle detected.`)],
+        options: [{ amd: true }],
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-two"`,
+        errors: [error(`Dependency cycle via ./depth-one:1`)],
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-two"`,
+        options: [{ maxDepth: 2 }],
+        errors: [error(`Dependency cycle via ./depth-one:1`)],
+      }),
+      test({
+        code: `const { foo } = require("./${testDialect}/depth-two")`,
+        errors: [error(`Dependency cycle via ./depth-one:1`)],
+        options: [{ commonjs: true }],
+      }),
+      test({
+        code: `import { two } from "./${testDialect}/depth-three-star"`,
+        errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
+      }),
+      test({
+        code: `import one, { two, three } from "./${testDialect}/depth-three-star"`,
+        errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
+      }),
+      test({
+        code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
+        errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
+      }),
+      test({
+        code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
+        errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
+        parser: require.resolve('babel-eslint'),
+      }),
+      test({
+        code: `import("./${testDialect}/depth-three-star")`,
+        errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
+        parser: require.resolve('babel-eslint'),
+      }),
+      test({
+        code: `import("./${testDialect}/depth-three-indirect")`,
+        errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
+        parser: require.resolve('babel-eslint'),
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-two"`,
+        options: [{ maxDepth: Infinity }],
+        errors: [error(`Dependency cycle via ./depth-one:1`)],
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-two"`,
+        options: [{ maxDepth: '∞' }],
+        errors: [error(`Dependency cycle via ./depth-one:1`)],
+      }),
+    ]),
+
     test({
       code: 'import { bar } from "./flow-types-depth-one"',
       parser: require.resolve('babel-eslint'),
-      errors: [error(`Dependency cycle via ./flow-types-depth-two:4=>./depth-one:1`)],
-    }),
-    test({
-      code: 'import { foo } from "./depth-two"',
-      options: [{ maxDepth: Infinity }],
-      errors: [error(`Dependency cycle via ./depth-one:1`)],
-    }),
-    test({
-      code: 'import { foo } from "./depth-two"',
-      options: [{ maxDepth: '∞' }],
-      errors: [error(`Dependency cycle via ./depth-one:1`)],
+      errors: [error(`Dependency cycle via ./flow-types-depth-two:4=>./es6/depth-one:1`)],
     }),
-  ],
+  ),
 });
-// })

From 794e869757d047deafab35b38c9552bb42f9e835 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 8 Aug 2021 12:31:48 -0700
Subject: [PATCH 330/767] [meta] update repo URLs

---
 .github/workflows/node-4+.yml          |   2 +-
 .github/workflows/packages.yml         |   2 +-
 CHANGELOG.md                           | 872 ++++++++++++-------------
 README.md                              |   8 +-
 RELEASE.md                             |  10 +-
 docs/rules/first.md                    |   2 +-
 docs/rules/imports-first.md            |   2 +-
 docs/rules/no-cycle.md                 |   2 +-
 docs/rules/no-duplicates.md            |   2 +-
 docs/rules/no-unused-modules.md        |   2 +-
 docs/rules/no-useless-path-segments.md |   2 +-
 memo-parser/package.json               |   6 +-
 package.json                           |   6 +-
 resolvers/node/CHANGELOG.md            |  16 +-
 resolvers/node/package.json            |   6 +-
 resolvers/webpack/CHANGELOG.md         |  70 +-
 resolvers/webpack/package.json         |   6 +-
 src/docsUrl.js                         |   2 +-
 tests/src/config/typescript.js         |   2 +-
 tests/src/core/docsUrl.js              |   4 +-
 tests/src/rules/no-unresolved.js       |   2 +-
 tests/src/rules/order.js               |   2 +-
 utils/CHANGELOG.md                     |  32 +-
 utils/package.json                     |   6 +-
 utils/parse.js                         |   2 +-
 25 files changed, 534 insertions(+), 534 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 02c11a0708..6456762fce 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -14,7 +14,7 @@ jobs:
         with:
           versionsAsRoot: true
           type: majors
-          preset: '>= 6' # preset: '>=4' # see https://github.com/benmosher/eslint-plugin-import/issues/2053
+          preset: '>= 6' # preset: '>=4' # see https://github.com/import-js/eslint-plugin-import/issues/2053
 
   latest:
     needs: [matrix]
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index 2add24b49c..79bd1ce464 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -13,7 +13,7 @@ jobs:
         id: set-matrix
         with:
           type: 'majors'
-          preset: '>= 6' # preset: '>=4' # see https://github.com/benmosher/eslint-plugin-import/issues/2053
+          preset: '>= 6' # preset: '>=4' # see https://github.com/import-js/eslint-plugin-import/issues/2053
           versionsAsRoot: true
 
   tests:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 266b4ee12d..b4c027241f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -761,7 +761,7 @@ Unpublished from npm and re-released as 0.13.0. See [#170].
 - Resolver plugins. Now the linter can read Webpack config, properly follow aliases and ignore externals, dismisses inline loaders, etc. etc.!
 
 ## Earlier releases (0.10.1 and younger)
-See [GitHub release notes](https://github.com/benmosher/eslint-plugin-import/releases?after=v0.11.0)
+See [GitHub release notes](https://github.com/import-js/eslint-plugin-import/releases?after=v0.11.0)
 for info on changes for earlier releases.
 
 
@@ -819,441 +819,441 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
-[#2160]: https://github.com/benmosher/eslint-plugin-import/pull/2160
-[#2158]: https://github.com/benmosher/eslint-plugin-import/pull/2158
-[#2156]: https://github.com/benmosher/eslint-plugin-import/pull/2156
-[#2146]: https://github.com/benmosher/eslint-plugin-import/pull/2146
-[#2138]: https://github.com/benmosher/eslint-plugin-import/pull/2138
-[#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
-[#2112]: https://github.com/benmosher/eslint-plugin-import/pull/2112
-[#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
-[#2097]: https://github.com/benmosher/eslint-plugin-import/pull/2097
-[#2090]: https://github.com/benmosher/eslint-plugin-import/pull/2090
-[#2087]: https://github.com/benmosher/eslint-plugin-import/pull/2087
-[#2083]: https://github.com/benmosher/eslint-plugin-import/pull/2083
-[#2075]: https://github.com/benmosher/eslint-plugin-import/pull/2075
-[#2071]: https://github.com/benmosher/eslint-plugin-import/pull/2071
-[#2034]: https://github.com/benmosher/eslint-plugin-import/pull/2034
-[#2028]: https://github.com/benmosher/eslint-plugin-import/pull/2028
-[#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
-[#2022]: https://github.com/benmosher/eslint-plugin-import/pull/2022
-[#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021
-[#2012]: https://github.com/benmosher/eslint-plugin-import/pull/2012
-[#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997
-[#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993
-[#1990]: https://github.com/benmosher/eslint-plugin-import/pull/1990
-[#1985]: https://github.com/benmosher/eslint-plugin-import/pull/1985
-[#1983]: https://github.com/benmosher/eslint-plugin-import/pull/1983
-[#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974
-[#1958]: https://github.com/benmosher/eslint-plugin-import/pull/1958
-[#1948]: https://github.com/benmosher/eslint-plugin-import/pull/1948
-[#1947]: https://github.com/benmosher/eslint-plugin-import/pull/1947
-[#1944]: https://github.com/benmosher/eslint-plugin-import/pull/1944
-[#1940]: https://github.com/benmosher/eslint-plugin-import/pull/1940
-[#1897]: https://github.com/benmosher/eslint-plugin-import/pull/1897
-[#1889]: https://github.com/benmosher/eslint-plugin-import/pull/1889
-[#1878]: https://github.com/benmosher/eslint-plugin-import/pull/1878
-[#1860]: https://github.com/benmosher/eslint-plugin-import/pull/1860
-[#1848]: https://github.com/benmosher/eslint-plugin-import/pull/1848
-[#1847]: https://github.com/benmosher/eslint-plugin-import/pull/1847
-[#1846]: https://github.com/benmosher/eslint-plugin-import/pull/1846
-[#1836]: https://github.com/benmosher/eslint-plugin-import/pull/1836
-[#1835]: https://github.com/benmosher/eslint-plugin-import/pull/1835
-[#1833]: https://github.com/benmosher/eslint-plugin-import/pull/1833
-[#1831]: https://github.com/benmosher/eslint-plugin-import/pull/1831
-[#1830]: https://github.com/benmosher/eslint-plugin-import/pull/1830
-[#1824]: https://github.com/benmosher/eslint-plugin-import/pull/1824
-[#1823]: https://github.com/benmosher/eslint-plugin-import/pull/1823
-[#1822]: https://github.com/benmosher/eslint-plugin-import/pull/1822
-[#1820]: https://github.com/benmosher/eslint-plugin-import/pull/1820
-[#1819]: https://github.com/benmosher/eslint-plugin-import/pull/1819
-[#1802]: https://github.com/benmosher/eslint-plugin-import/pull/1802
-[#1788]: https://github.com/benmosher/eslint-plugin-import/pull/1788
-[#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
-[#1785]: https://github.com/benmosher/eslint-plugin-import/pull/1785
-[#1776]: https://github.com/benmosher/eslint-plugin-import/pull/1776
-[#1770]: https://github.com/benmosher/eslint-plugin-import/pull/1770
-[#1764]: https://github.com/benmosher/eslint-plugin-import/pull/1764
-[#1763]: https://github.com/benmosher/eslint-plugin-import/pull/1763
-[#1751]: https://github.com/benmosher/eslint-plugin-import/pull/1751
-[#1744]: https://github.com/benmosher/eslint-plugin-import/pull/1744
-[#1736]: https://github.com/benmosher/eslint-plugin-import/pull/1736
-[#1735]: https://github.com/benmosher/eslint-plugin-import/pull/1735
-[#1726]: https://github.com/benmosher/eslint-plugin-import/pull/1726
-[#1724]: https://github.com/benmosher/eslint-plugin-import/pull/1724
-[#1719]: https://github.com/benmosher/eslint-plugin-import/pull/1719
-[#1696]: https://github.com/benmosher/eslint-plugin-import/pull/1696
-[#1691]: https://github.com/benmosher/eslint-plugin-import/pull/1691
-[#1690]: https://github.com/benmosher/eslint-plugin-import/pull/1690
-[#1689]: https://github.com/benmosher/eslint-plugin-import/pull/1689
-[#1681]: https://github.com/benmosher/eslint-plugin-import/pull/1681
-[#1676]: https://github.com/benmosher/eslint-plugin-import/pull/1676
-[#1666]: https://github.com/benmosher/eslint-plugin-import/pull/1666
-[#1664]: https://github.com/benmosher/eslint-plugin-import/pull/1664
-[#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
-[#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
-[#1626]: https://github.com/benmosher/eslint-plugin-import/pull/1626
-[#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
-[#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
-[#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
-[#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
-[#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
-[#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
-[#1572]: https://github.com/benmosher/eslint-plugin-import/pull/1572
-[#1569]: https://github.com/benmosher/eslint-plugin-import/pull/1569
-[#1563]: https://github.com/benmosher/eslint-plugin-import/pull/1563
-[#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560
-[#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
-[#1542]: https://github.com/benmosher/eslint-plugin-import/pull/1542
-[#1534]: https://github.com/benmosher/eslint-plugin-import/pull/1534
-[#1528]: https://github.com/benmosher/eslint-plugin-import/pull/1528
-[#1526]: https://github.com/benmosher/eslint-plugin-import/pull/1526
-[#1521]: https://github.com/benmosher/eslint-plugin-import/pull/1521
-[#1519]: https://github.com/benmosher/eslint-plugin-import/pull/1519
-[#1517]: https://github.com/benmosher/eslint-plugin-import/pull/1517
-[#1507]: https://github.com/benmosher/eslint-plugin-import/pull/1507
-[#1506]: https://github.com/benmosher/eslint-plugin-import/pull/1506
-[#1496]: https://github.com/benmosher/eslint-plugin-import/pull/1496
-[#1495]: https://github.com/benmosher/eslint-plugin-import/pull/1495
-[#1494]: https://github.com/benmosher/eslint-plugin-import/pull/1494
-[#1493]: https://github.com/benmosher/eslint-plugin-import/pull/1493
-[#1491]: https://github.com/benmosher/eslint-plugin-import/pull/1491
-[#1472]: https://github.com/benmosher/eslint-plugin-import/pull/1472
-[#1470]: https://github.com/benmosher/eslint-plugin-import/pull/1470
-[#1447]: https://github.com/benmosher/eslint-plugin-import/pull/1447
-[#1439]: https://github.com/benmosher/eslint-plugin-import/pull/1439
-[#1436]: https://github.com/benmosher/eslint-plugin-import/pull/1436
-[#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
-[#1425]: https://github.com/benmosher/eslint-plugin-import/pull/1425
-[#1419]: https://github.com/benmosher/eslint-plugin-import/pull/1419
-[#1412]: https://github.com/benmosher/eslint-plugin-import/pull/1412
-[#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
-[#1404]: https://github.com/benmosher/eslint-plugin-import/pull/1404
-[#1401]: https://github.com/benmosher/eslint-plugin-import/pull/1401
-[#1393]: https://github.com/benmosher/eslint-plugin-import/pull/1393
-[#1389]: https://github.com/benmosher/eslint-plugin-import/pull/1389
-[#1386]: https://github.com/benmosher/eslint-plugin-import/pull/1386
-[#1377]: https://github.com/benmosher/eslint-plugin-import/pull/1377
-[#1375]: https://github.com/benmosher/eslint-plugin-import/pull/1375
-[#1372]: https://github.com/benmosher/eslint-plugin-import/pull/1372
-[#1371]: https://github.com/benmosher/eslint-plugin-import/pull/1371
-[#1370]: https://github.com/benmosher/eslint-plugin-import/pull/1370
-[#1363]: https://github.com/benmosher/eslint-plugin-import/pull/1363
-[#1360]: https://github.com/benmosher/eslint-plugin-import/pull/1360
-[#1358]: https://github.com/benmosher/eslint-plugin-import/pull/1358
-[#1356]: https://github.com/benmosher/eslint-plugin-import/pull/1356
-[#1354]: https://github.com/benmosher/eslint-plugin-import/pull/1354
-[#1352]: https://github.com/benmosher/eslint-plugin-import/pull/1352
-[#1347]: https://github.com/benmosher/eslint-plugin-import/pull/1347
-[#1345]: https://github.com/benmosher/eslint-plugin-import/pull/1345
-[#1342]: https://github.com/benmosher/eslint-plugin-import/pull/1342
-[#1340]: https://github.com/benmosher/eslint-plugin-import/pull/1340
-[#1333]: https://github.com/benmosher/eslint-plugin-import/pull/1333
-[#1331]: https://github.com/benmosher/eslint-plugin-import/pull/1331
-[#1330]: https://github.com/benmosher/eslint-plugin-import/pull/1330
-[#1320]: https://github.com/benmosher/eslint-plugin-import/pull/1320
-[#1319]: https://github.com/benmosher/eslint-plugin-import/pull/1319
-[#1312]: https://github.com/benmosher/eslint-plugin-import/pull/1312
-[#1308]: https://github.com/benmosher/eslint-plugin-import/pull/1308
-[#1304]: https://github.com/benmosher/eslint-plugin-import/pull/1304
-[#1297]: https://github.com/benmosher/eslint-plugin-import/pull/1297
-[#1295]: https://github.com/benmosher/eslint-plugin-import/pull/1295
-[#1294]: https://github.com/benmosher/eslint-plugin-import/pull/1294
-[#1290]: https://github.com/benmosher/eslint-plugin-import/pull/1290
-[#1277]: https://github.com/benmosher/eslint-plugin-import/pull/1277
-[#1257]: https://github.com/benmosher/eslint-plugin-import/pull/1257
-[#1253]: https://github.com/benmosher/eslint-plugin-import/pull/1253
-[#1248]: https://github.com/benmosher/eslint-plugin-import/pull/1248
-[#1238]: https://github.com/benmosher/eslint-plugin-import/pull/1238
-[#1237]: https://github.com/benmosher/eslint-plugin-import/pull/1237
-[#1235]: https://github.com/benmosher/eslint-plugin-import/pull/1235
-[#1234]: https://github.com/benmosher/eslint-plugin-import/pull/1234
-[#1232]: https://github.com/benmosher/eslint-plugin-import/pull/1232
-[#1223]: https://github.com/benmosher/eslint-plugin-import/pull/1223
-[#1222]: https://github.com/benmosher/eslint-plugin-import/pull/1222
-[#1218]: https://github.com/benmosher/eslint-plugin-import/pull/1218
-[#1176]: https://github.com/benmosher/eslint-plugin-import/pull/1176
-[#1163]: https://github.com/benmosher/eslint-plugin-import/pull/1163
-[#1157]: https://github.com/benmosher/eslint-plugin-import/pull/1157
-[#1151]: https://github.com/benmosher/eslint-plugin-import/pull/1151
-[#1142]: https://github.com/benmosher/eslint-plugin-import/pull/1142
-[#1139]: https://github.com/benmosher/eslint-plugin-import/pull/1139
-[#1137]: https://github.com/benmosher/eslint-plugin-import/pull/1137
-[#1135]: https://github.com/benmosher/eslint-plugin-import/pull/1135
-[#1128]: https://github.com/benmosher/eslint-plugin-import/pull/1128
-[#1126]: https://github.com/benmosher/eslint-plugin-import/pull/1126
-[#1122]: https://github.com/benmosher/eslint-plugin-import/pull/1122
-[#1112]: https://github.com/benmosher/eslint-plugin-import/pull/1112
-[#1107]: https://github.com/benmosher/eslint-plugin-import/pull/1107
-[#1106]: https://github.com/benmosher/eslint-plugin-import/pull/1106
-[#1105]: https://github.com/benmosher/eslint-plugin-import/pull/1105
-[#1093]: https://github.com/benmosher/eslint-plugin-import/pull/1093
-[#1085]: https://github.com/benmosher/eslint-plugin-import/pull/1085
-[#1068]: https://github.com/benmosher/eslint-plugin-import/pull/1068
-[#1049]: https://github.com/benmosher/eslint-plugin-import/pull/1049
-[#1046]: https://github.com/benmosher/eslint-plugin-import/pull/1046
-[#966]: https://github.com/benmosher/eslint-plugin-import/pull/966
-[#944]: https://github.com/benmosher/eslint-plugin-import/pull/944
-[#912]: https://github.com/benmosher/eslint-plugin-import/pull/912
-[#908]: https://github.com/benmosher/eslint-plugin-import/pull/908
-[#891]: https://github.com/benmosher/eslint-plugin-import/pull/891
-[#889]: https://github.com/benmosher/eslint-plugin-import/pull/889
-[#880]: https://github.com/benmosher/eslint-plugin-import/pull/880
-[#871]: https://github.com/benmosher/eslint-plugin-import/pull/871
-[#858]: https://github.com/benmosher/eslint-plugin-import/pull/858
-[#843]: https://github.com/benmosher/eslint-plugin-import/pull/843
-[#804]: https://github.com/benmosher/eslint-plugin-import/pull/804
-[#797]: https://github.com/benmosher/eslint-plugin-import/pull/797
-[#794]: https://github.com/benmosher/eslint-plugin-import/pull/794
-[#744]: https://github.com/benmosher/eslint-plugin-import/pull/744
-[#742]: https://github.com/benmosher/eslint-plugin-import/pull/742
-[#737]: https://github.com/benmosher/eslint-plugin-import/pull/737
-[#727]: https://github.com/benmosher/eslint-plugin-import/pull/727
-[#721]: https://github.com/benmosher/eslint-plugin-import/pull/721
-[#712]: https://github.com/benmosher/eslint-plugin-import/pull/712
-[#696]: https://github.com/benmosher/eslint-plugin-import/pull/696
-[#685]: https://github.com/benmosher/eslint-plugin-import/pull/685
-[#680]: https://github.com/benmosher/eslint-plugin-import/pull/680
-[#654]: https://github.com/benmosher/eslint-plugin-import/pull/654
-[#639]: https://github.com/benmosher/eslint-plugin-import/pull/639
-[#632]: https://github.com/benmosher/eslint-plugin-import/pull/632
-[#630]: https://github.com/benmosher/eslint-plugin-import/pull/630
-[#629]: https://github.com/benmosher/eslint-plugin-import/pull/629
-[#628]: https://github.com/benmosher/eslint-plugin-import/pull/628
-[#596]: https://github.com/benmosher/eslint-plugin-import/pull/596
-[#586]: https://github.com/benmosher/eslint-plugin-import/pull/586
-[#578]: https://github.com/benmosher/eslint-plugin-import/pull/578
-[#568]: https://github.com/benmosher/eslint-plugin-import/pull/568
-[#555]: https://github.com/benmosher/eslint-plugin-import/pull/555
-[#538]: https://github.com/benmosher/eslint-plugin-import/pull/538
-[#527]: https://github.com/benmosher/eslint-plugin-import/pull/527
-[#518]: https://github.com/benmosher/eslint-plugin-import/pull/518
-[#509]: https://github.com/benmosher/eslint-plugin-import/pull/509
-[#508]: https://github.com/benmosher/eslint-plugin-import/pull/508
-[#503]: https://github.com/benmosher/eslint-plugin-import/pull/503
-[#499]: https://github.com/benmosher/eslint-plugin-import/pull/499
-[#489]: https://github.com/benmosher/eslint-plugin-import/pull/489
-[#485]: https://github.com/benmosher/eslint-plugin-import/pull/485
-[#461]: https://github.com/benmosher/eslint-plugin-import/pull/461
-[#449]: https://github.com/benmosher/eslint-plugin-import/pull/449
-[#444]: https://github.com/benmosher/eslint-plugin-import/pull/444
-[#428]: https://github.com/benmosher/eslint-plugin-import/pull/428
-[#395]: https://github.com/benmosher/eslint-plugin-import/pull/395
-[#371]: https://github.com/benmosher/eslint-plugin-import/pull/371
-[#365]: https://github.com/benmosher/eslint-plugin-import/pull/365
-[#359]: https://github.com/benmosher/eslint-plugin-import/pull/359
-[#343]: https://github.com/benmosher/eslint-plugin-import/pull/343
-[#332]: https://github.com/benmosher/eslint-plugin-import/pull/332
-[#322]: https://github.com/benmosher/eslint-plugin-import/pull/322
-[#321]: https://github.com/benmosher/eslint-plugin-import/pull/321
-[#316]: https://github.com/benmosher/eslint-plugin-import/pull/316
-[#314]: https://github.com/benmosher/eslint-plugin-import/pull/314
-[#308]: https://github.com/benmosher/eslint-plugin-import/pull/308
-[#298]: https://github.com/benmosher/eslint-plugin-import/pull/298
-[#297]: https://github.com/benmosher/eslint-plugin-import/pull/297
-[#296]: https://github.com/benmosher/eslint-plugin-import/pull/296
-[#290]: https://github.com/benmosher/eslint-plugin-import/pull/290
-[#289]: https://github.com/benmosher/eslint-plugin-import/pull/289
-[#288]: https://github.com/benmosher/eslint-plugin-import/pull/288
-[#287]: https://github.com/benmosher/eslint-plugin-import/pull/287
-[#278]: https://github.com/benmosher/eslint-plugin-import/pull/278
-[#261]: https://github.com/benmosher/eslint-plugin-import/pull/261
-[#256]: https://github.com/benmosher/eslint-plugin-import/pull/256
-[#254]: https://github.com/benmosher/eslint-plugin-import/pull/254
-[#250]: https://github.com/benmosher/eslint-plugin-import/pull/250
-[#247]: https://github.com/benmosher/eslint-plugin-import/pull/247
-[#245]: https://github.com/benmosher/eslint-plugin-import/pull/245
-[#243]: https://github.com/benmosher/eslint-plugin-import/pull/243
-[#241]: https://github.com/benmosher/eslint-plugin-import/pull/241
-[#239]: https://github.com/benmosher/eslint-plugin-import/pull/239
-[#228]: https://github.com/benmosher/eslint-plugin-import/pull/228
-[#211]: https://github.com/benmosher/eslint-plugin-import/pull/211
-[#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
-[#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
-[#2118]: https://github.com/benmosher/eslint-plugin-import/issues/2118
-[#2067]: https://github.com/benmosher/eslint-plugin-import/issues/2067
-[#2056]: https://github.com/benmosher/eslint-plugin-import/issues/2056
-[#2063]: https://github.com/benmosher/eslint-plugin-import/issues/2063
-[#1965]: https://github.com/benmosher/eslint-plugin-import/issues/1965
-[#1924]: https://github.com/benmosher/eslint-plugin-import/issues/1924
-[#1854]: https://github.com/benmosher/eslint-plugin-import/issues/1854
-[#1841]: https://github.com/benmosher/eslint-plugin-import/issues/1841
-[#1834]: https://github.com/benmosher/eslint-plugin-import/issues/1834
-[#1814]: https://github.com/benmosher/eslint-plugin-import/issues/1814
-[#1811]: https://github.com/benmosher/eslint-plugin-import/issues/1811
-[#1808]: https://github.com/benmosher/eslint-plugin-import/issues/1808
-[#1805]: https://github.com/benmosher/eslint-plugin-import/issues/1805
-[#1801]: https://github.com/benmosher/eslint-plugin-import/issues/1801
-[#1722]: https://github.com/benmosher/eslint-plugin-import/issues/1722
-[#1704]: https://github.com/benmosher/eslint-plugin-import/issues/1704
-[#1702]: https://github.com/benmosher/eslint-plugin-import/issues/1702
-[#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
-[#1631]: https://github.com/benmosher/eslint-plugin-import/issues/1631
-[#1616]: https://github.com/benmosher/eslint-plugin-import/issues/1616
-[#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
-[#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
-[#1565]: https://github.com/benmosher/eslint-plugin-import/issues/1565
-[#1366]: https://github.com/benmosher/eslint-plugin-import/issues/1366
-[#1334]: https://github.com/benmosher/eslint-plugin-import/issues/1334
-[#1323]: https://github.com/benmosher/eslint-plugin-import/issues/1323
-[#1322]: https://github.com/benmosher/eslint-plugin-import/issues/1322
-[#1300]: https://github.com/benmosher/eslint-plugin-import/issues/1300
-[#1293]: https://github.com/benmosher/eslint-plugin-import/issues/1293
-[#1266]: https://github.com/benmosher/eslint-plugin-import/issues/1266
-[#1256]: https://github.com/benmosher/eslint-plugin-import/issues/1256
-[#1233]: https://github.com/benmosher/eslint-plugin-import/issues/1233
-[#1175]: https://github.com/benmosher/eslint-plugin-import/issues/1175
-[#1166]: https://github.com/benmosher/eslint-plugin-import/issues/1166
-[#1144]: https://github.com/benmosher/eslint-plugin-import/issues/1144
-[#1058]: https://github.com/benmosher/eslint-plugin-import/issues/1058
-[#1035]: https://github.com/benmosher/eslint-plugin-import/issues/1035
-[#931]: https://github.com/benmosher/eslint-plugin-import/issues/931
-[#886]: https://github.com/benmosher/eslint-plugin-import/issues/886
-[#863]: https://github.com/benmosher/eslint-plugin-import/issues/863
-[#842]: https://github.com/benmosher/eslint-plugin-import/issues/842
-[#839]: https://github.com/benmosher/eslint-plugin-import/issues/839
-[#795]: https://github.com/benmosher/eslint-plugin-import/issues/795
-[#793]: https://github.com/benmosher/eslint-plugin-import/issues/793
-[#720]: https://github.com/benmosher/eslint-plugin-import/issues/720
-[#717]: https://github.com/benmosher/eslint-plugin-import/issues/717
-[#686]: https://github.com/benmosher/eslint-plugin-import/issues/686
-[#671]: https://github.com/benmosher/eslint-plugin-import/issues/671
-[#660]: https://github.com/benmosher/eslint-plugin-import/issues/660
-[#653]: https://github.com/benmosher/eslint-plugin-import/issues/653
-[#627]: https://github.com/benmosher/eslint-plugin-import/issues/627
-[#620]: https://github.com/benmosher/eslint-plugin-import/issues/620
-[#609]: https://github.com/benmosher/eslint-plugin-import/issues/609
-[#604]: https://github.com/benmosher/eslint-plugin-import/issues/604
-[#602]: https://github.com/benmosher/eslint-plugin-import/issues/602
-[#601]: https://github.com/benmosher/eslint-plugin-import/issues/601
-[#592]: https://github.com/benmosher/eslint-plugin-import/issues/592
-[#577]: https://github.com/benmosher/eslint-plugin-import/issues/577
-[#570]: https://github.com/benmosher/eslint-plugin-import/issues/570
-[#567]: https://github.com/benmosher/eslint-plugin-import/issues/567
-[#566]: https://github.com/benmosher/eslint-plugin-import/issues/566
-[#545]: https://github.com/benmosher/eslint-plugin-import/issues/545
-[#530]: https://github.com/benmosher/eslint-plugin-import/issues/530
-[#529]: https://github.com/benmosher/eslint-plugin-import/issues/529
-[#519]: https://github.com/benmosher/eslint-plugin-import/issues/519
-[#507]: https://github.com/benmosher/eslint-plugin-import/issues/507
-[#484]: https://github.com/benmosher/eslint-plugin-import/issues/484
-[#478]: https://github.com/benmosher/eslint-plugin-import/issues/478
-[#456]: https://github.com/benmosher/eslint-plugin-import/issues/456
-[#453]: https://github.com/benmosher/eslint-plugin-import/issues/453
-[#452]: https://github.com/benmosher/eslint-plugin-import/issues/452
-[#447]: https://github.com/benmosher/eslint-plugin-import/issues/447
-[#441]: https://github.com/benmosher/eslint-plugin-import/issues/441
-[#423]: https://github.com/benmosher/eslint-plugin-import/issues/423
-[#416]: https://github.com/benmosher/eslint-plugin-import/issues/416
-[#415]: https://github.com/benmosher/eslint-plugin-import/issues/415
-[#402]: https://github.com/benmosher/eslint-plugin-import/issues/402
-[#386]: https://github.com/benmosher/eslint-plugin-import/issues/386
-[#373]: https://github.com/benmosher/eslint-plugin-import/issues/373
-[#370]: https://github.com/benmosher/eslint-plugin-import/issues/370
-[#348]: https://github.com/benmosher/eslint-plugin-import/issues/348
-[#342]: https://github.com/benmosher/eslint-plugin-import/issues/342
-[#328]: https://github.com/benmosher/eslint-plugin-import/issues/328
-[#317]: https://github.com/benmosher/eslint-plugin-import/issues/317
-[#313]: https://github.com/benmosher/eslint-plugin-import/issues/313
-[#311]: https://github.com/benmosher/eslint-plugin-import/issues/311
-[#306]: https://github.com/benmosher/eslint-plugin-import/issues/306
-[#286]: https://github.com/benmosher/eslint-plugin-import/issues/286
-[#283]: https://github.com/benmosher/eslint-plugin-import/issues/283
-[#281]: https://github.com/benmosher/eslint-plugin-import/issues/281
-[#275]: https://github.com/benmosher/eslint-plugin-import/issues/275
-[#272]: https://github.com/benmosher/eslint-plugin-import/issues/272
-[#270]: https://github.com/benmosher/eslint-plugin-import/issues/270
-[#267]: https://github.com/benmosher/eslint-plugin-import/issues/267
-[#266]: https://github.com/benmosher/eslint-plugin-import/issues/266
-[#216]: https://github.com/benmosher/eslint-plugin-import/issues/216
-[#214]: https://github.com/benmosher/eslint-plugin-import/issues/214
-[#210]: https://github.com/benmosher/eslint-plugin-import/issues/210
-[#200]: https://github.com/benmosher/eslint-plugin-import/issues/200
-[#192]: https://github.com/benmosher/eslint-plugin-import/issues/192
-[#191]: https://github.com/benmosher/eslint-plugin-import/issues/191
-[#189]: https://github.com/benmosher/eslint-plugin-import/issues/189
-[#170]: https://github.com/benmosher/eslint-plugin-import/issues/170
-[#155]: https://github.com/benmosher/eslint-plugin-import/issues/155
-[#119]: https://github.com/benmosher/eslint-plugin-import/issues/119
-[#89]: https://github.com/benmosher/eslint-plugin-import/issues/89
-
-[Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.4...HEAD
-[2.23.4]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.3...v2.23.4
-[2.23.3]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.2...v2.23.3
-[2.23.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.1...v2.23.2
-[2.23.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.23.0...v2.23.1
-[2.23.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.1...v2.23.0
-[2.22.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.22.0...v2.22.1
-[2.22.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.22.0
-[2.21.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.1...v2.21.2
-[2.21.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.21.0...v2.21.1
-[2.21.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.2...v2.21.0
-[2.20.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.1...v2.20.2
-[2.20.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.20.0...v2.20.1
-[2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.1...v2.20.0
-[2.19.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.19.0...v2.19.1
-[2.19.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.2...v2.19.0
-[2.18.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.1...v2.18.2
-[2.18.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.18.0...v2.18.1
-[2.18.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.17.3...v2.18.0
-[2.17.3]: https://github.com/benmosher/eslint-plugin-import/compare/v2.17.2...v2.17.3
-[2.17.2]: https://github.com/benmosher/eslint-plugin-import/compare/v2.17.1...v2.17.2
-[2.17.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.17.0...v2.17.1
-[2.17.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.16.0...v2.17.0
-[2.16.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.15.0...v2.16.0
-[2.15.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.14.0...v2.15.0
-[2.14.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.13.0...v2.14.0
-[2.13.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.12.0...v2.13.0
-[2.12.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.11.0...v2.12.0
-[2.11.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.10.0...v2.11.0
-[2.10.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.9.0...v2.10.0
-[2.9.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.8.0...v2.9.0
-[2.8.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.7.0...v2.8.0
-[2.7.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.6.1...v2.7.0
-[2.6.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.6.0...v2.6.1
-[2.6.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.5.0...v2.6.0
-[2.5.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.4.0...v2.5.0
-[2.4.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.3.0...v2.4.0
-[2.3.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.2.0...v2.3.0
-[2.2.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.1.0...v2.2.0
-[2.1.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.0.1...v2.1.0
-[2.0.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.0.0...v2.0.1
-[2.0.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.16.0...v2.0.0
-[1.16.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.15.0...v1.16.0
-[1.15.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.14.0...v1.15.0
-[1.14.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.13.0...v1.14.0
-[1.13.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.12.0...v1.13.0
-[1.12.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.11.1...v1.12.0
-[1.11.1]: https://github.com/benmosher/eslint-plugin-import/compare/v1.11.0...v1.11.1
-[1.11.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.3...v1.11.0
-[1.10.3]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.2...v1.10.3
-[1.10.2]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.1...v1.10.2
-[1.10.1]: https://github.com/benmosher/eslint-plugin-import/compare/v1.10.0...v1.10.1
-[1.10.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.9.2...v1.10.0
-[1.9.2]: https://github.com/benmosher/eslint-plugin-import/compare/v1.9.1...v1.9.2
-[1.9.1]: https://github.com/benmosher/eslint-plugin-import/compare/v1.9.0...v1.9.1
-[1.9.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.8.1...v1.9.0
-[1.8.1]: https://github.com/benmosher/eslint-plugin-import/compare/v1.8.0...v1.8.1
-[1.8.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.7.0...v1.8.0
-[1.7.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.6.1...v1.7.0
-[1.6.1]: https://github.com/benmosher/eslint-plugin-import/compare/v1.6.0...v1.6.1
-[1.6.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.5.0...1.6.0
-[1.5.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.4.0...v1.5.0
-[1.4.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.3.0...v1.4.0
-[1.3.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.2.0...v1.3.0
-[1.2.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.1.0...v1.2.0
-[1.1.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.0.4...v1.1.0
-[1.0.4]: https://github.com/benmosher/eslint-plugin-import/compare/v1.0.3...v1.0.4
-[1.0.3]: https://github.com/benmosher/eslint-plugin-import/compare/v1.0.2...v1.0.3
-[1.0.2]: https://github.com/benmosher/eslint-plugin-import/compare/v1.0.1...v1.0.2
-[1.0.1]: https://github.com/benmosher/eslint-plugin-import/compare/v1.0.0...v1.0.1
-[1.0.0]: https://github.com/benmosher/eslint-plugin-import/compare/v1.0.0-beta.0...v1.0.0
-[1.0.0-beta.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.13.0...v1.0.0-beta.0
-[0.13.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.12.1...v0.13.0
-[0.12.2]: https://github.com/benmosher/eslint-plugin-import/compare/v0.12.1...v0.12.2
-[0.12.1]: https://github.com/benmosher/eslint-plugin-import/compare/v0.12.0...v0.12.1
-[0.12.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.11.0...v0.12.0
-[0.11.0]: https://github.com/benmosher/eslint-plugin-import/compare/v0.10.1...v0.11.0
+[#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
+[#2158]: https://github.com/import-js/eslint-plugin-import/pull/2158
+[#2156]: https://github.com/import-js/eslint-plugin-import/pull/2156
+[#2146]: https://github.com/import-js/eslint-plugin-import/pull/2146
+[#2138]: https://github.com/import-js/eslint-plugin-import/pull/2138
+[#2121]: https://github.com/import-js/eslint-plugin-import/pull/2121
+[#2112]: https://github.com/import-js/eslint-plugin-import/pull/2112
+[#2099]: https://github.com/import-js/eslint-plugin-import/pull/2099
+[#2097]: https://github.com/import-js/eslint-plugin-import/pull/2097
+[#2090]: https://github.com/import-js/eslint-plugin-import/pull/2090
+[#2087]: https://github.com/import-js/eslint-plugin-import/pull/2087
+[#2083]: https://github.com/import-js/eslint-plugin-import/pull/2083
+[#2075]: https://github.com/import-js/eslint-plugin-import/pull/2075
+[#2071]: https://github.com/import-js/eslint-plugin-import/pull/2071
+[#2034]: https://github.com/import-js/eslint-plugin-import/pull/2034
+[#2028]: https://github.com/import-js/eslint-plugin-import/pull/2028
+[#2026]: https://github.com/import-js/eslint-plugin-import/pull/2026
+[#2022]: https://github.com/import-js/eslint-plugin-import/pull/2022
+[#2021]: https://github.com/import-js/eslint-plugin-import/pull/2021
+[#2012]: https://github.com/import-js/eslint-plugin-import/pull/2012
+[#1997]: https://github.com/import-js/eslint-plugin-import/pull/1997
+[#1993]: https://github.com/import-js/eslint-plugin-import/pull/1993
+[#1990]: https://github.com/import-js/eslint-plugin-import/pull/1990
+[#1985]: https://github.com/import-js/eslint-plugin-import/pull/1985
+[#1983]: https://github.com/import-js/eslint-plugin-import/pull/1983
+[#1974]: https://github.com/import-js/eslint-plugin-import/pull/1974
+[#1958]: https://github.com/import-js/eslint-plugin-import/pull/1958
+[#1948]: https://github.com/import-js/eslint-plugin-import/pull/1948
+[#1947]: https://github.com/import-js/eslint-plugin-import/pull/1947
+[#1944]: https://github.com/import-js/eslint-plugin-import/pull/1944
+[#1940]: https://github.com/import-js/eslint-plugin-import/pull/1940
+[#1897]: https://github.com/import-js/eslint-plugin-import/pull/1897
+[#1889]: https://github.com/import-js/eslint-plugin-import/pull/1889
+[#1878]: https://github.com/import-js/eslint-plugin-import/pull/1878
+[#1860]: https://github.com/import-js/eslint-plugin-import/pull/1860
+[#1848]: https://github.com/import-js/eslint-plugin-import/pull/1848
+[#1847]: https://github.com/import-js/eslint-plugin-import/pull/1847
+[#1846]: https://github.com/import-js/eslint-plugin-import/pull/1846
+[#1836]: https://github.com/import-js/eslint-plugin-import/pull/1836
+[#1835]: https://github.com/import-js/eslint-plugin-import/pull/1835
+[#1833]: https://github.com/import-js/eslint-plugin-import/pull/1833
+[#1831]: https://github.com/import-js/eslint-plugin-import/pull/1831
+[#1830]: https://github.com/import-js/eslint-plugin-import/pull/1830
+[#1824]: https://github.com/import-js/eslint-plugin-import/pull/1824
+[#1823]: https://github.com/import-js/eslint-plugin-import/pull/1823
+[#1822]: https://github.com/import-js/eslint-plugin-import/pull/1822
+[#1820]: https://github.com/import-js/eslint-plugin-import/pull/1820
+[#1819]: https://github.com/import-js/eslint-plugin-import/pull/1819
+[#1802]: https://github.com/import-js/eslint-plugin-import/pull/1802
+[#1788]: https://github.com/import-js/eslint-plugin-import/pull/1788
+[#1786]: https://github.com/import-js/eslint-plugin-import/pull/1786
+[#1785]: https://github.com/import-js/eslint-plugin-import/pull/1785
+[#1776]: https://github.com/import-js/eslint-plugin-import/pull/1776
+[#1770]: https://github.com/import-js/eslint-plugin-import/pull/1770
+[#1764]: https://github.com/import-js/eslint-plugin-import/pull/1764
+[#1763]: https://github.com/import-js/eslint-plugin-import/pull/1763
+[#1751]: https://github.com/import-js/eslint-plugin-import/pull/1751
+[#1744]: https://github.com/import-js/eslint-plugin-import/pull/1744
+[#1736]: https://github.com/import-js/eslint-plugin-import/pull/1736
+[#1735]: https://github.com/import-js/eslint-plugin-import/pull/1735
+[#1726]: https://github.com/import-js/eslint-plugin-import/pull/1726
+[#1724]: https://github.com/import-js/eslint-plugin-import/pull/1724
+[#1719]: https://github.com/import-js/eslint-plugin-import/pull/1719
+[#1696]: https://github.com/import-js/eslint-plugin-import/pull/1696
+[#1691]: https://github.com/import-js/eslint-plugin-import/pull/1691
+[#1690]: https://github.com/import-js/eslint-plugin-import/pull/1690
+[#1689]: https://github.com/import-js/eslint-plugin-import/pull/1689
+[#1681]: https://github.com/import-js/eslint-plugin-import/pull/1681
+[#1676]: https://github.com/import-js/eslint-plugin-import/pull/1676
+[#1666]: https://github.com/import-js/eslint-plugin-import/pull/1666
+[#1664]: https://github.com/import-js/eslint-plugin-import/pull/1664
+[#1658]: https://github.com/import-js/eslint-plugin-import/pull/1658
+[#1651]: https://github.com/import-js/eslint-plugin-import/pull/1651
+[#1626]: https://github.com/import-js/eslint-plugin-import/pull/1626
+[#1620]: https://github.com/import-js/eslint-plugin-import/pull/1620
+[#1619]: https://github.com/import-js/eslint-plugin-import/pull/1619
+[#1612]: https://github.com/import-js/eslint-plugin-import/pull/1612
+[#1611]: https://github.com/import-js/eslint-plugin-import/pull/1611
+[#1605]: https://github.com/import-js/eslint-plugin-import/pull/1605
+[#1586]: https://github.com/import-js/eslint-plugin-import/pull/1586
+[#1572]: https://github.com/import-js/eslint-plugin-import/pull/1572
+[#1569]: https://github.com/import-js/eslint-plugin-import/pull/1569
+[#1563]: https://github.com/import-js/eslint-plugin-import/pull/1563
+[#1560]: https://github.com/import-js/eslint-plugin-import/pull/1560
+[#1551]: https://github.com/import-js/eslint-plugin-import/pull/1551
+[#1542]: https://github.com/import-js/eslint-plugin-import/pull/1542
+[#1534]: https://github.com/import-js/eslint-plugin-import/pull/1534
+[#1528]: https://github.com/import-js/eslint-plugin-import/pull/1528
+[#1526]: https://github.com/import-js/eslint-plugin-import/pull/1526
+[#1521]: https://github.com/import-js/eslint-plugin-import/pull/1521
+[#1519]: https://github.com/import-js/eslint-plugin-import/pull/1519
+[#1517]: https://github.com/import-js/eslint-plugin-import/pull/1517
+[#1507]: https://github.com/import-js/eslint-plugin-import/pull/1507
+[#1506]: https://github.com/import-js/eslint-plugin-import/pull/1506
+[#1496]: https://github.com/import-js/eslint-plugin-import/pull/1496
+[#1495]: https://github.com/import-js/eslint-plugin-import/pull/1495
+[#1494]: https://github.com/import-js/eslint-plugin-import/pull/1494
+[#1493]: https://github.com/import-js/eslint-plugin-import/pull/1493
+[#1491]: https://github.com/import-js/eslint-plugin-import/pull/1491
+[#1472]: https://github.com/import-js/eslint-plugin-import/pull/1472
+[#1470]: https://github.com/import-js/eslint-plugin-import/pull/1470
+[#1447]: https://github.com/import-js/eslint-plugin-import/pull/1447
+[#1439]: https://github.com/import-js/eslint-plugin-import/pull/1439
+[#1436]: https://github.com/import-js/eslint-plugin-import/pull/1436
+[#1435]: https://github.com/import-js/eslint-plugin-import/pull/1435
+[#1425]: https://github.com/import-js/eslint-plugin-import/pull/1425
+[#1419]: https://github.com/import-js/eslint-plugin-import/pull/1419
+[#1412]: https://github.com/import-js/eslint-plugin-import/pull/1412
+[#1409]: https://github.com/import-js/eslint-plugin-import/pull/1409
+[#1404]: https://github.com/import-js/eslint-plugin-import/pull/1404
+[#1401]: https://github.com/import-js/eslint-plugin-import/pull/1401
+[#1393]: https://github.com/import-js/eslint-plugin-import/pull/1393
+[#1389]: https://github.com/import-js/eslint-plugin-import/pull/1389
+[#1386]: https://github.com/import-js/eslint-plugin-import/pull/1386
+[#1377]: https://github.com/import-js/eslint-plugin-import/pull/1377
+[#1375]: https://github.com/import-js/eslint-plugin-import/pull/1375
+[#1372]: https://github.com/import-js/eslint-plugin-import/pull/1372
+[#1371]: https://github.com/import-js/eslint-plugin-import/pull/1371
+[#1370]: https://github.com/import-js/eslint-plugin-import/pull/1370
+[#1363]: https://github.com/import-js/eslint-plugin-import/pull/1363
+[#1360]: https://github.com/import-js/eslint-plugin-import/pull/1360
+[#1358]: https://github.com/import-js/eslint-plugin-import/pull/1358
+[#1356]: https://github.com/import-js/eslint-plugin-import/pull/1356
+[#1354]: https://github.com/import-js/eslint-plugin-import/pull/1354
+[#1352]: https://github.com/import-js/eslint-plugin-import/pull/1352
+[#1347]: https://github.com/import-js/eslint-plugin-import/pull/1347
+[#1345]: https://github.com/import-js/eslint-plugin-import/pull/1345
+[#1342]: https://github.com/import-js/eslint-plugin-import/pull/1342
+[#1340]: https://github.com/import-js/eslint-plugin-import/pull/1340
+[#1333]: https://github.com/import-js/eslint-plugin-import/pull/1333
+[#1331]: https://github.com/import-js/eslint-plugin-import/pull/1331
+[#1330]: https://github.com/import-js/eslint-plugin-import/pull/1330
+[#1320]: https://github.com/import-js/eslint-plugin-import/pull/1320
+[#1319]: https://github.com/import-js/eslint-plugin-import/pull/1319
+[#1312]: https://github.com/import-js/eslint-plugin-import/pull/1312
+[#1308]: https://github.com/import-js/eslint-plugin-import/pull/1308
+[#1304]: https://github.com/import-js/eslint-plugin-import/pull/1304
+[#1297]: https://github.com/import-js/eslint-plugin-import/pull/1297
+[#1295]: https://github.com/import-js/eslint-plugin-import/pull/1295
+[#1294]: https://github.com/import-js/eslint-plugin-import/pull/1294
+[#1290]: https://github.com/import-js/eslint-plugin-import/pull/1290
+[#1277]: https://github.com/import-js/eslint-plugin-import/pull/1277
+[#1257]: https://github.com/import-js/eslint-plugin-import/pull/1257
+[#1253]: https://github.com/import-js/eslint-plugin-import/pull/1253
+[#1248]: https://github.com/import-js/eslint-plugin-import/pull/1248
+[#1238]: https://github.com/import-js/eslint-plugin-import/pull/1238
+[#1237]: https://github.com/import-js/eslint-plugin-import/pull/1237
+[#1235]: https://github.com/import-js/eslint-plugin-import/pull/1235
+[#1234]: https://github.com/import-js/eslint-plugin-import/pull/1234
+[#1232]: https://github.com/import-js/eslint-plugin-import/pull/1232
+[#1223]: https://github.com/import-js/eslint-plugin-import/pull/1223
+[#1222]: https://github.com/import-js/eslint-plugin-import/pull/1222
+[#1218]: https://github.com/import-js/eslint-plugin-import/pull/1218
+[#1176]: https://github.com/import-js/eslint-plugin-import/pull/1176
+[#1163]: https://github.com/import-js/eslint-plugin-import/pull/1163
+[#1157]: https://github.com/import-js/eslint-plugin-import/pull/1157
+[#1151]: https://github.com/import-js/eslint-plugin-import/pull/1151
+[#1142]: https://github.com/import-js/eslint-plugin-import/pull/1142
+[#1139]: https://github.com/import-js/eslint-plugin-import/pull/1139
+[#1137]: https://github.com/import-js/eslint-plugin-import/pull/1137
+[#1135]: https://github.com/import-js/eslint-plugin-import/pull/1135
+[#1128]: https://github.com/import-js/eslint-plugin-import/pull/1128
+[#1126]: https://github.com/import-js/eslint-plugin-import/pull/1126
+[#1122]: https://github.com/import-js/eslint-plugin-import/pull/1122
+[#1112]: https://github.com/import-js/eslint-plugin-import/pull/1112
+[#1107]: https://github.com/import-js/eslint-plugin-import/pull/1107
+[#1106]: https://github.com/import-js/eslint-plugin-import/pull/1106
+[#1105]: https://github.com/import-js/eslint-plugin-import/pull/1105
+[#1093]: https://github.com/import-js/eslint-plugin-import/pull/1093
+[#1085]: https://github.com/import-js/eslint-plugin-import/pull/1085
+[#1068]: https://github.com/import-js/eslint-plugin-import/pull/1068
+[#1049]: https://github.com/import-js/eslint-plugin-import/pull/1049
+[#1046]: https://github.com/import-js/eslint-plugin-import/pull/1046
+[#966]: https://github.com/import-js/eslint-plugin-import/pull/966
+[#944]: https://github.com/import-js/eslint-plugin-import/pull/944
+[#912]: https://github.com/import-js/eslint-plugin-import/pull/912
+[#908]: https://github.com/import-js/eslint-plugin-import/pull/908
+[#891]: https://github.com/import-js/eslint-plugin-import/pull/891
+[#889]: https://github.com/import-js/eslint-plugin-import/pull/889
+[#880]: https://github.com/import-js/eslint-plugin-import/pull/880
+[#871]: https://github.com/import-js/eslint-plugin-import/pull/871
+[#858]: https://github.com/import-js/eslint-plugin-import/pull/858
+[#843]: https://github.com/import-js/eslint-plugin-import/pull/843
+[#804]: https://github.com/import-js/eslint-plugin-import/pull/804
+[#797]: https://github.com/import-js/eslint-plugin-import/pull/797
+[#794]: https://github.com/import-js/eslint-plugin-import/pull/794
+[#744]: https://github.com/import-js/eslint-plugin-import/pull/744
+[#742]: https://github.com/import-js/eslint-plugin-import/pull/742
+[#737]: https://github.com/import-js/eslint-plugin-import/pull/737
+[#727]: https://github.com/import-js/eslint-plugin-import/pull/727
+[#721]: https://github.com/import-js/eslint-plugin-import/pull/721
+[#712]: https://github.com/import-js/eslint-plugin-import/pull/712
+[#696]: https://github.com/import-js/eslint-plugin-import/pull/696
+[#685]: https://github.com/import-js/eslint-plugin-import/pull/685
+[#680]: https://github.com/import-js/eslint-plugin-import/pull/680
+[#654]: https://github.com/import-js/eslint-plugin-import/pull/654
+[#639]: https://github.com/import-js/eslint-plugin-import/pull/639
+[#632]: https://github.com/import-js/eslint-plugin-import/pull/632
+[#630]: https://github.com/import-js/eslint-plugin-import/pull/630
+[#629]: https://github.com/import-js/eslint-plugin-import/pull/629
+[#628]: https://github.com/import-js/eslint-plugin-import/pull/628
+[#596]: https://github.com/import-js/eslint-plugin-import/pull/596
+[#586]: https://github.com/import-js/eslint-plugin-import/pull/586
+[#578]: https://github.com/import-js/eslint-plugin-import/pull/578
+[#568]: https://github.com/import-js/eslint-plugin-import/pull/568
+[#555]: https://github.com/import-js/eslint-plugin-import/pull/555
+[#538]: https://github.com/import-js/eslint-plugin-import/pull/538
+[#527]: https://github.com/import-js/eslint-plugin-import/pull/527
+[#518]: https://github.com/import-js/eslint-plugin-import/pull/518
+[#509]: https://github.com/import-js/eslint-plugin-import/pull/509
+[#508]: https://github.com/import-js/eslint-plugin-import/pull/508
+[#503]: https://github.com/import-js/eslint-plugin-import/pull/503
+[#499]: https://github.com/import-js/eslint-plugin-import/pull/499
+[#489]: https://github.com/import-js/eslint-plugin-import/pull/489
+[#485]: https://github.com/import-js/eslint-plugin-import/pull/485
+[#461]: https://github.com/import-js/eslint-plugin-import/pull/461
+[#449]: https://github.com/import-js/eslint-plugin-import/pull/449
+[#444]: https://github.com/import-js/eslint-plugin-import/pull/444
+[#428]: https://github.com/import-js/eslint-plugin-import/pull/428
+[#395]: https://github.com/import-js/eslint-plugin-import/pull/395
+[#371]: https://github.com/import-js/eslint-plugin-import/pull/371
+[#365]: https://github.com/import-js/eslint-plugin-import/pull/365
+[#359]: https://github.com/import-js/eslint-plugin-import/pull/359
+[#343]: https://github.com/import-js/eslint-plugin-import/pull/343
+[#332]: https://github.com/import-js/eslint-plugin-import/pull/332
+[#322]: https://github.com/import-js/eslint-plugin-import/pull/322
+[#321]: https://github.com/import-js/eslint-plugin-import/pull/321
+[#316]: https://github.com/import-js/eslint-plugin-import/pull/316
+[#314]: https://github.com/import-js/eslint-plugin-import/pull/314
+[#308]: https://github.com/import-js/eslint-plugin-import/pull/308
+[#298]: https://github.com/import-js/eslint-plugin-import/pull/298
+[#297]: https://github.com/import-js/eslint-plugin-import/pull/297
+[#296]: https://github.com/import-js/eslint-plugin-import/pull/296
+[#290]: https://github.com/import-js/eslint-plugin-import/pull/290
+[#289]: https://github.com/import-js/eslint-plugin-import/pull/289
+[#288]: https://github.com/import-js/eslint-plugin-import/pull/288
+[#287]: https://github.com/import-js/eslint-plugin-import/pull/287
+[#278]: https://github.com/import-js/eslint-plugin-import/pull/278
+[#261]: https://github.com/import-js/eslint-plugin-import/pull/261
+[#256]: https://github.com/import-js/eslint-plugin-import/pull/256
+[#254]: https://github.com/import-js/eslint-plugin-import/pull/254
+[#250]: https://github.com/import-js/eslint-plugin-import/pull/250
+[#247]: https://github.com/import-js/eslint-plugin-import/pull/247
+[#245]: https://github.com/import-js/eslint-plugin-import/pull/245
+[#243]: https://github.com/import-js/eslint-plugin-import/pull/243
+[#241]: https://github.com/import-js/eslint-plugin-import/pull/241
+[#239]: https://github.com/import-js/eslint-plugin-import/pull/239
+[#228]: https://github.com/import-js/eslint-plugin-import/pull/228
+[#211]: https://github.com/import-js/eslint-plugin-import/pull/211
+[#164]: https://github.com/import-js/eslint-plugin-import/pull/164
+[#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2118]: https://github.com/import-js/eslint-plugin-import/issues/2118
+[#2067]: https://github.com/import-js/eslint-plugin-import/issues/2067
+[#2056]: https://github.com/import-js/eslint-plugin-import/issues/2056
+[#2063]: https://github.com/import-js/eslint-plugin-import/issues/2063
+[#1965]: https://github.com/import-js/eslint-plugin-import/issues/1965
+[#1924]: https://github.com/import-js/eslint-plugin-import/issues/1924
+[#1854]: https://github.com/import-js/eslint-plugin-import/issues/1854
+[#1841]: https://github.com/import-js/eslint-plugin-import/issues/1841
+[#1834]: https://github.com/import-js/eslint-plugin-import/issues/1834
+[#1814]: https://github.com/import-js/eslint-plugin-import/issues/1814
+[#1811]: https://github.com/import-js/eslint-plugin-import/issues/1811
+[#1808]: https://github.com/import-js/eslint-plugin-import/issues/1808
+[#1805]: https://github.com/import-js/eslint-plugin-import/issues/1805
+[#1801]: https://github.com/import-js/eslint-plugin-import/issues/1801
+[#1722]: https://github.com/import-js/eslint-plugin-import/issues/1722
+[#1704]: https://github.com/import-js/eslint-plugin-import/issues/1704
+[#1702]: https://github.com/import-js/eslint-plugin-import/issues/1702
+[#1635]: https://github.com/import-js/eslint-plugin-import/issues/1635
+[#1631]: https://github.com/import-js/eslint-plugin-import/issues/1631
+[#1616]: https://github.com/import-js/eslint-plugin-import/issues/1616
+[#1613]: https://github.com/import-js/eslint-plugin-import/issues/1613
+[#1589]: https://github.com/import-js/eslint-plugin-import/issues/1589
+[#1565]: https://github.com/import-js/eslint-plugin-import/issues/1565
+[#1366]: https://github.com/import-js/eslint-plugin-import/issues/1366
+[#1334]: https://github.com/import-js/eslint-plugin-import/issues/1334
+[#1323]: https://github.com/import-js/eslint-plugin-import/issues/1323
+[#1322]: https://github.com/import-js/eslint-plugin-import/issues/1322
+[#1300]: https://github.com/import-js/eslint-plugin-import/issues/1300
+[#1293]: https://github.com/import-js/eslint-plugin-import/issues/1293
+[#1266]: https://github.com/import-js/eslint-plugin-import/issues/1266
+[#1256]: https://github.com/import-js/eslint-plugin-import/issues/1256
+[#1233]: https://github.com/import-js/eslint-plugin-import/issues/1233
+[#1175]: https://github.com/import-js/eslint-plugin-import/issues/1175
+[#1166]: https://github.com/import-js/eslint-plugin-import/issues/1166
+[#1144]: https://github.com/import-js/eslint-plugin-import/issues/1144
+[#1058]: https://github.com/import-js/eslint-plugin-import/issues/1058
+[#1035]: https://github.com/import-js/eslint-plugin-import/issues/1035
+[#931]: https://github.com/import-js/eslint-plugin-import/issues/931
+[#886]: https://github.com/import-js/eslint-plugin-import/issues/886
+[#863]: https://github.com/import-js/eslint-plugin-import/issues/863
+[#842]: https://github.com/import-js/eslint-plugin-import/issues/842
+[#839]: https://github.com/import-js/eslint-plugin-import/issues/839
+[#795]: https://github.com/import-js/eslint-plugin-import/issues/795
+[#793]: https://github.com/import-js/eslint-plugin-import/issues/793
+[#720]: https://github.com/import-js/eslint-plugin-import/issues/720
+[#717]: https://github.com/import-js/eslint-plugin-import/issues/717
+[#686]: https://github.com/import-js/eslint-plugin-import/issues/686
+[#671]: https://github.com/import-js/eslint-plugin-import/issues/671
+[#660]: https://github.com/import-js/eslint-plugin-import/issues/660
+[#653]: https://github.com/import-js/eslint-plugin-import/issues/653
+[#627]: https://github.com/import-js/eslint-plugin-import/issues/627
+[#620]: https://github.com/import-js/eslint-plugin-import/issues/620
+[#609]: https://github.com/import-js/eslint-plugin-import/issues/609
+[#604]: https://github.com/import-js/eslint-plugin-import/issues/604
+[#602]: https://github.com/import-js/eslint-plugin-import/issues/602
+[#601]: https://github.com/import-js/eslint-plugin-import/issues/601
+[#592]: https://github.com/import-js/eslint-plugin-import/issues/592
+[#577]: https://github.com/import-js/eslint-plugin-import/issues/577
+[#570]: https://github.com/import-js/eslint-plugin-import/issues/570
+[#567]: https://github.com/import-js/eslint-plugin-import/issues/567
+[#566]: https://github.com/import-js/eslint-plugin-import/issues/566
+[#545]: https://github.com/import-js/eslint-plugin-import/issues/545
+[#530]: https://github.com/import-js/eslint-plugin-import/issues/530
+[#529]: https://github.com/import-js/eslint-plugin-import/issues/529
+[#519]: https://github.com/import-js/eslint-plugin-import/issues/519
+[#507]: https://github.com/import-js/eslint-plugin-import/issues/507
+[#484]: https://github.com/import-js/eslint-plugin-import/issues/484
+[#478]: https://github.com/import-js/eslint-plugin-import/issues/478
+[#456]: https://github.com/import-js/eslint-plugin-import/issues/456
+[#453]: https://github.com/import-js/eslint-plugin-import/issues/453
+[#452]: https://github.com/import-js/eslint-plugin-import/issues/452
+[#447]: https://github.com/import-js/eslint-plugin-import/issues/447
+[#441]: https://github.com/import-js/eslint-plugin-import/issues/441
+[#423]: https://github.com/import-js/eslint-plugin-import/issues/423
+[#416]: https://github.com/import-js/eslint-plugin-import/issues/416
+[#415]: https://github.com/import-js/eslint-plugin-import/issues/415
+[#402]: https://github.com/import-js/eslint-plugin-import/issues/402
+[#386]: https://github.com/import-js/eslint-plugin-import/issues/386
+[#373]: https://github.com/import-js/eslint-plugin-import/issues/373
+[#370]: https://github.com/import-js/eslint-plugin-import/issues/370
+[#348]: https://github.com/import-js/eslint-plugin-import/issues/348
+[#342]: https://github.com/import-js/eslint-plugin-import/issues/342
+[#328]: https://github.com/import-js/eslint-plugin-import/issues/328
+[#317]: https://github.com/import-js/eslint-plugin-import/issues/317
+[#313]: https://github.com/import-js/eslint-plugin-import/issues/313
+[#311]: https://github.com/import-js/eslint-plugin-import/issues/311
+[#306]: https://github.com/import-js/eslint-plugin-import/issues/306
+[#286]: https://github.com/import-js/eslint-plugin-import/issues/286
+[#283]: https://github.com/import-js/eslint-plugin-import/issues/283
+[#281]: https://github.com/import-js/eslint-plugin-import/issues/281
+[#275]: https://github.com/import-js/eslint-plugin-import/issues/275
+[#272]: https://github.com/import-js/eslint-plugin-import/issues/272
+[#270]: https://github.com/import-js/eslint-plugin-import/issues/270
+[#267]: https://github.com/import-js/eslint-plugin-import/issues/267
+[#266]: https://github.com/import-js/eslint-plugin-import/issues/266
+[#216]: https://github.com/import-js/eslint-plugin-import/issues/216
+[#214]: https://github.com/import-js/eslint-plugin-import/issues/214
+[#210]: https://github.com/import-js/eslint-plugin-import/issues/210
+[#200]: https://github.com/import-js/eslint-plugin-import/issues/200
+[#192]: https://github.com/import-js/eslint-plugin-import/issues/192
+[#191]: https://github.com/import-js/eslint-plugin-import/issues/191
+[#189]: https://github.com/import-js/eslint-plugin-import/issues/189
+[#170]: https://github.com/import-js/eslint-plugin-import/issues/170
+[#155]: https://github.com/import-js/eslint-plugin-import/issues/155
+[#119]: https://github.com/import-js/eslint-plugin-import/issues/119
+[#89]: https://github.com/import-js/eslint-plugin-import/issues/89
+
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.4...HEAD
+[2.23.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.3...v2.23.4
+[2.23.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.2...v2.23.3
+[2.23.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.1...v2.23.2
+[2.23.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.0...v2.23.1
+[2.23.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.22.1...v2.23.0
+[2.22.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.22.0...v2.22.1
+[2.22.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.21.1...v2.22.0
+[2.21.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.21.1...v2.21.2
+[2.21.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.21.0...v2.21.1
+[2.21.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.20.2...v2.21.0
+[2.20.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.20.1...v2.20.2
+[2.20.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.20.0...v2.20.1
+[2.19.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.19.1...v2.20.0
+[2.19.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.19.0...v2.19.1
+[2.19.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.18.2...v2.19.0
+[2.18.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.18.1...v2.18.2
+[2.18.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.18.0...v2.18.1
+[2.18.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.17.3...v2.18.0
+[2.17.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.17.2...v2.17.3
+[2.17.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.17.1...v2.17.2
+[2.17.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.17.0...v2.17.1
+[2.17.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.16.0...v2.17.0
+[2.16.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.15.0...v2.16.0
+[2.15.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.14.0...v2.15.0
+[2.14.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.13.0...v2.14.0
+[2.13.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.12.0...v2.13.0
+[2.12.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.11.0...v2.12.0
+[2.11.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.10.0...v2.11.0
+[2.10.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.9.0...v2.10.0
+[2.9.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.8.0...v2.9.0
+[2.8.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.7.0...v2.8.0
+[2.7.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.6.1...v2.7.0
+[2.6.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.6.0...v2.6.1
+[2.6.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.5.0...v2.6.0
+[2.5.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.4.0...v2.5.0
+[2.4.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.3.0...v2.4.0
+[2.3.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.2.0...v2.3.0
+[2.2.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.1.0...v2.2.0
+[2.1.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.0.1...v2.1.0
+[2.0.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.0.0...v2.0.1
+[2.0.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.16.0...v2.0.0
+[1.16.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.15.0...v1.16.0
+[1.15.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.14.0...v1.15.0
+[1.14.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.13.0...v1.14.0
+[1.13.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.12.0...v1.13.0
+[1.12.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.11.1...v1.12.0
+[1.11.1]: https://github.com/import-js/eslint-plugin-import/compare/v1.11.0...v1.11.1
+[1.11.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.10.3...v1.11.0
+[1.10.3]: https://github.com/import-js/eslint-plugin-import/compare/v1.10.2...v1.10.3
+[1.10.2]: https://github.com/import-js/eslint-plugin-import/compare/v1.10.1...v1.10.2
+[1.10.1]: https://github.com/import-js/eslint-plugin-import/compare/v1.10.0...v1.10.1
+[1.10.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.9.2...v1.10.0
+[1.9.2]: https://github.com/import-js/eslint-plugin-import/compare/v1.9.1...v1.9.2
+[1.9.1]: https://github.com/import-js/eslint-plugin-import/compare/v1.9.0...v1.9.1
+[1.9.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.8.1...v1.9.0
+[1.8.1]: https://github.com/import-js/eslint-plugin-import/compare/v1.8.0...v1.8.1
+[1.8.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.7.0...v1.8.0
+[1.7.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.6.1...v1.7.0
+[1.6.1]: https://github.com/import-js/eslint-plugin-import/compare/v1.6.0...v1.6.1
+[1.6.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.5.0...1.6.0
+[1.5.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.4.0...v1.5.0
+[1.4.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.3.0...v1.4.0
+[1.3.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.2.0...v1.3.0
+[1.2.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.1.0...v1.2.0
+[1.1.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.0.4...v1.1.0
+[1.0.4]: https://github.com/import-js/eslint-plugin-import/compare/v1.0.3...v1.0.4
+[1.0.3]: https://github.com/import-js/eslint-plugin-import/compare/v1.0.2...v1.0.3
+[1.0.2]: https://github.com/import-js/eslint-plugin-import/compare/v1.0.1...v1.0.2
+[1.0.1]: https://github.com/import-js/eslint-plugin-import/compare/v1.0.0...v1.0.1
+[1.0.0]: https://github.com/import-js/eslint-plugin-import/compare/v1.0.0-beta.0...v1.0.0
+[1.0.0-beta.0]: https://github.com/import-js/eslint-plugin-import/compare/v0.13.0...v1.0.0-beta.0
+[0.13.0]: https://github.com/import-js/eslint-plugin-import/compare/v0.12.1...v0.13.0
+[0.12.2]: https://github.com/import-js/eslint-plugin-import/compare/v0.12.1...v0.12.2
+[0.12.1]: https://github.com/import-js/eslint-plugin-import/compare/v0.12.0...v0.12.1
+[0.12.0]: https://github.com/import-js/eslint-plugin-import/compare/v0.11.0...v0.12.0
+[0.11.0]: https://github.com/import-js/eslint-plugin-import/compare/v0.10.1...v0.11.0
 
 [@1pete]: https://github.com/1pete
 [@3nuc]: https://github.com/3nuc
diff --git a/README.md b/README.md
index d7d50eaf51..36801e8103 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
 # eslint-plugin-import
 
-[![build status](https://travis-ci.org/benmosher/eslint-plugin-import.svg?branch=master)](https://travis-ci.org/benmosher/eslint-plugin-import)
-[![Coverage Status](https://coveralls.io/repos/github/benmosher/eslint-plugin-import/badge.svg?branch=master)](https://coveralls.io/github/benmosher/eslint-plugin-import?branch=master)
-[![win32 build status](https://ci.appveyor.com/api/projects/status/3mw2fifalmjlqf56/branch/master?svg=true)](https://ci.appveyor.com/project/benmosher/eslint-plugin-import/branch/master)
+[![build status](https://travis-ci.org/import-js/eslint-plugin-import.svg?branch=master)](https://travis-ci.org/import-js/eslint-plugin-import)
+[![Coverage Status](https://coveralls.io/repos/github/import-js/eslint-plugin-import/badge.svg?branch=master)](https://coveralls.io/github/import-js/eslint-plugin-import?branch=master)
+[![win32 build status](https://ci.appveyor.com/api/projects/status/3mw2fifalmjlqf56/branch/master?svg=true)](https://ci.appveyor.com/project/import-js/eslint-plugin-import/branch/master)
 [![npm](https://img.shields.io/npm/v/eslint-plugin-import.svg)](https://www.npmjs.com/package/eslint-plugin-import)
 [![npm downloads](https://img.shields.io/npm/dt/eslint-plugin-import.svg?maxAge=2592000)](http://www.npmtrends.com/eslint-plugin-import)
 
@@ -190,7 +190,7 @@ runtime (allowing some modules to be included more traditionally via script tags
 In the interest of supporting both of these, v0.11 introduces resolvers.
 
 Currently [Node] and [webpack] resolution have been implemented, but the
-resolvers are just npm packages, so [third party packages are supported](https://github.com/benmosher/eslint-plugin-import/wiki/Resolvers) (and encouraged!).
+resolvers are just npm packages, so [third party packages are supported](https://github.com/import-js/eslint-plugin-import/wiki/Resolvers) (and encouraged!).
 
 You can reference resolvers in several ways (in order of precedence):
 
diff --git a/RELEASE.md b/RELEASE.md
index e16a58993c..34ef1aadc6 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -13,16 +13,16 @@
    at last version's tag.
 
    ```markdown
-   [Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.0.1...HEAD
-   [2.0.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.0.0...v2.0.1
+   [Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.0.1...HEAD
+   [2.0.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.0.0...v2.0.1
    ```
 
    becomes
 
    ```markdown
-   [Unreleased]: https://github.com/benmosher/eslint-plugin-import/compare/v2.1.0...HEAD
-   [2.1.0]: https://github.com/benmosher/eslint-plugin-import/compare/v2.0.1...v2.1.0
-   [2.0.1]: https://github.com/benmosher/eslint-plugin-import/compare/v2.0.0...v2.0.1
+   [Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.1.0...HEAD
+   [2.1.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.0.1...v2.1.0
+   [2.0.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.0.0...v2.0.1
    ```
 
    Generally, don't use `npm version` for this because it creates a tag, which I normally
diff --git a/docs/rules/first.md b/docs/rules/first.md
index eada966c88..cc19003be2 100644
--- a/docs/rules/first.md
+++ b/docs/rules/first.md
@@ -67,4 +67,4 @@ enable this rule.
 - Issue [#255]
 
 [`import/order`]: ./order.md
-[#255]: https://github.com/benmosher/eslint-plugin-import/issues/255
+[#255]: https://github.com/import-js/eslint-plugin-import/issues/255
diff --git a/docs/rules/imports-first.md b/docs/rules/imports-first.md
index b7f20754af..e4cdda1151 100644
--- a/docs/rules/imports-first.md
+++ b/docs/rules/imports-first.md
@@ -1,3 +1,3 @@
 # imports-first
 
-This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md).
+This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/first.md).
diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md
index 7d54e81ff8..7f1b4255a9 100644
--- a/docs/rules/no-cycle.md
+++ b/docs/rules/no-cycle.md
@@ -83,7 +83,7 @@ this rule enabled.
 
 ## Further Reading
 
-- [Original inspiring issue](https://github.com/benmosher/eslint-plugin-import/issues/941)
+- [Original inspiring issue](https://github.com/import-js/eslint-plugin-import/issues/941)
 - Rule to detect that module imports itself: [`no-self-import`]
 - [`import/external-module-folders`] setting
 
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index f59b14d9cc..c37510325e 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -7,7 +7,7 @@ ESLint core has a similar rule ([`no-duplicate-imports`](http://eslint.org/docs/
 is different in two key ways:
 
 1. the paths in the source code don't have to exactly match, they just have to point to the same module on the filesystem. (i.e. `./foo` and `./foo.js`)
-2. this version distinguishes Flow `type` imports from standard imports. ([#334](https://github.com/benmosher/eslint-plugin-import/pull/334))
+2. this version distinguishes Flow `type` imports from standard imports. ([#334](https://github.com/import-js/eslint-plugin-import/pull/334))
 
 ## Rule Details
 
diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index 4c04333ad3..01c13557cf 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -10,7 +10,7 @@ Note: dynamic imports are currently not supported.
 
 ### Usage
 
-In order for this plugin to work, one of the options `missingExports` or `unusedExports` must be enabled (see "Options" section below). In the future, these options will be enabled by default (see https://github.com/benmosher/eslint-plugin-import/issues/1324)
+In order for this plugin to work, one of the options `missingExports` or `unusedExports` must be enabled (see "Options" section below). In the future, these options will be enabled by default (see https://github.com/import-js/eslint-plugin-import/issues/1324)
 
 Example:
 ```
diff --git a/docs/rules/no-useless-path-segments.md b/docs/rules/no-useless-path-segments.md
index 19b7725855..81b56579c1 100644
--- a/docs/rules/no-useless-path-segments.md
+++ b/docs/rules/no-useless-path-segments.md
@@ -72,7 +72,7 @@ import "./pages/index"; // should be "./pages" (auto-fixable)
 import "./pages/index.js"; // should be "./pages" (auto-fixable)
 ```
 
-Note: `noUselessIndex` only avoids ambiguous imports for `.js` files if you haven't specified other resolved file extensions. See [Settings: import/extensions](https://github.com/benmosher/eslint-plugin-import#importextensions) for details.
+Note: `noUselessIndex` only avoids ambiguous imports for `.js` files if you haven't specified other resolved file extensions. See [Settings: import/extensions](https://github.com/import-js/eslint-plugin-import#importextensions) for details.
 
 ### commonjs
 
diff --git a/memo-parser/package.json b/memo-parser/package.json
index 9aa7647b8d..723005d21b 100644
--- a/memo-parser/package.json
+++ b/memo-parser/package.json
@@ -12,7 +12,7 @@
   },
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/benmosher/eslint-plugin-import.git"
+    "url": "git+https://github.com/import-js/eslint-plugin-import.git"
   },
   "keywords": [
     "eslint",
@@ -22,9 +22,9 @@
   "author": "Ben Mosher (me@benmosher.com)",
   "license": "MIT",
   "bugs": {
-    "url": "https://github.com/benmosher/eslint-plugin-import/issues"
+    "url": "https://github.com/import-js/eslint-plugin-import/issues"
   },
-  "homepage": "https://github.com/benmosher/eslint-plugin-import#readme",
+  "homepage": "https://github.com/import-js/eslint-plugin-import#readme",
   "peerDependencies": {
     "eslint": ">=3.5.0"
   },
diff --git a/package.json b/package.json
index 0bc4237988..d475bdf630 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
   },
   "repository": {
     "type": "git",
-    "url": "https://github.com/benmosher/eslint-plugin-import"
+    "url": "https://github.com/import-js/eslint-plugin-import"
   },
   "keywords": [
     "eslint",
@@ -50,9 +50,9 @@
   "author": "Ben Mosher <me@benmosher.com>",
   "license": "MIT",
   "bugs": {
-    "url": "https://github.com/benmosher/eslint-plugin-import/issues"
+    "url": "https://github.com/import-js/eslint-plugin-import/issues"
   },
-  "homepage": "https://github.com/benmosher/eslint-plugin-import",
+  "homepage": "https://github.com/import-js/eslint-plugin-import",
   "devDependencies": {
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index 86554a4231..e8c4d9e2ac 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -51,14 +51,14 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - find files with `.json` extensions (#333, thanks for noticing @jfmengels)
 
-[#2166]: https://github.com/benmosher/eslint-plugin-import/pull/2166
-[#438]: https://github.com/benmosher/eslint-plugin-import/pull/438
-
-[#1663]: https://github.com/benmosher/eslint-plugin-import/issues/1663
-[#1595]: https://github.com/benmosher/eslint-plugin-import/pull/1595
-[#939]: https://github.com/benmosher/eslint-plugin-import/issues/939
-[#531]: https://github.com/benmosher/eslint-plugin-import/issues/531
-[#437]: https://github.com/benmosher/eslint-plugin-import/issues/437
+[#2166]: https://github.com/import-js/eslint-plugin-import/pull/2166
+[#438]: https://github.com/import-js/eslint-plugin-import/pull/438
+
+[#1663]: https://github.com/import-js/eslint-plugin-import/issues/1663
+[#1595]: https://github.com/import-js/eslint-plugin-import/pull/1595
+[#939]: https://github.com/import-js/eslint-plugin-import/issues/939
+[#531]: https://github.com/import-js/eslint-plugin-import/issues/531
+[#437]: https://github.com/import-js/eslint-plugin-import/issues/437
 
 [@jasonkarns]: https://github.com/jasonkarns
 [@lukeapage]: https://github.com/lukeapage
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 336e8fb0e9..c0b4f5d805 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -14,7 +14,7 @@
   },
   "repository": {
     "type": "git",
-    "url": "https://github.com/benmosher/eslint-plugin-import"
+    "url": "https://github.com/import-js/eslint-plugin-import"
   },
   "keywords": [
     "eslint",
@@ -26,9 +26,9 @@
   "author": "Ben Mosher (me@benmosher.com)",
   "license": "MIT",
   "bugs": {
-    "url": "https://github.com/benmosher/eslint-plugin-import/issues"
+    "url": "https://github.com/import-js/eslint-plugin-import/issues"
   },
-  "homepage": "https://github.com/benmosher/eslint-plugin-import",
+  "homepage": "https://github.com/import-js/eslint-plugin-import",
   "dependencies": {
     "debug": "^3.2.7",
     "resolve": "^1.20.0"
diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index edc67627ff..f8ec4c47c2 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -150,41 +150,41 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - `interpret` configs (such as `.babel.js`).
   Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
-[#2023]: https://github.com/benmosher/eslint-plugin-import/pull/2023
-[#1967]: https://github.com/benmosher/eslint-plugin-import/pull/1967
-[#1962]: https://github.com/benmosher/eslint-plugin-import/pull/1962
-[#1705]: https://github.com/benmosher/eslint-plugin-import/pull/1705
-[#1595]: https://github.com/benmosher/eslint-plugin-import/pull/1595
-[#1503]: https://github.com/benmosher/eslint-plugin-import/pull/1503
-[#1297]: https://github.com/benmosher/eslint-plugin-import/pull/1297
-[#1261]: https://github.com/benmosher/eslint-plugin-import/pull/1261
-[#1220]: https://github.com/benmosher/eslint-plugin-import/pull/1220
-[#1091]: https://github.com/benmosher/eslint-plugin-import/pull/1091
-[#969]: https://github.com/benmosher/eslint-plugin-import/pull/969
-[#968]: https://github.com/benmosher/eslint-plugin-import/pull/968
-[#768]: https://github.com/benmosher/eslint-plugin-import/pull/768
-[#683]: https://github.com/benmosher/eslint-plugin-import/pull/683
-[#572]: https://github.com/benmosher/eslint-plugin-import/pull/572
-[#569]: https://github.com/benmosher/eslint-plugin-import/pull/569
-[#533]: https://github.com/benmosher/eslint-plugin-import/pull/533
-[#413]: https://github.com/benmosher/eslint-plugin-import/pull/413
-[#377]: https://github.com/benmosher/eslint-plugin-import/pull/377
-[#363]: https://github.com/benmosher/eslint-plugin-import/pull/363
-[#289]: https://github.com/benmosher/eslint-plugin-import/pull/289
-[#287]: https://github.com/benmosher/eslint-plugin-import/pull/287
-[#278]: https://github.com/benmosher/eslint-plugin-import/pull/278
-[#181]: https://github.com/benmosher/eslint-plugin-import/pull/181
-[#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
-
-[#1219]: https://github.com/benmosher/eslint-plugin-import/issues/1219
-[#788]: https://github.com/benmosher/eslint-plugin-import/issues/788
-[#767]: https://github.com/benmosher/eslint-plugin-import/issues/767
-[#681]: https://github.com/benmosher/eslint-plugin-import/issues/681
-[#435]: https://github.com/benmosher/eslint-plugin-import/issues/435
-[#411]: https://github.com/benmosher/eslint-plugin-import/issues/411
-[#357]: https://github.com/benmosher/eslint-plugin-import/issues/357
-[#286]: https://github.com/benmosher/eslint-plugin-import/issues/286
-[#283]: https://github.com/benmosher/eslint-plugin-import/issues/283
+[#2023]: https://github.com/import-js/eslint-plugin-import/pull/2023
+[#1967]: https://github.com/import-js/eslint-plugin-import/pull/1967
+[#1962]: https://github.com/import-js/eslint-plugin-import/pull/1962
+[#1705]: https://github.com/import-js/eslint-plugin-import/pull/1705
+[#1595]: https://github.com/import-js/eslint-plugin-import/pull/1595
+[#1503]: https://github.com/import-js/eslint-plugin-import/pull/1503
+[#1297]: https://github.com/import-js/eslint-plugin-import/pull/1297
+[#1261]: https://github.com/import-js/eslint-plugin-import/pull/1261
+[#1220]: https://github.com/import-js/eslint-plugin-import/pull/1220
+[#1091]: https://github.com/import-js/eslint-plugin-import/pull/1091
+[#969]: https://github.com/import-js/eslint-plugin-import/pull/969
+[#968]: https://github.com/import-js/eslint-plugin-import/pull/968
+[#768]: https://github.com/import-js/eslint-plugin-import/pull/768
+[#683]: https://github.com/import-js/eslint-plugin-import/pull/683
+[#572]: https://github.com/import-js/eslint-plugin-import/pull/572
+[#569]: https://github.com/import-js/eslint-plugin-import/pull/569
+[#533]: https://github.com/import-js/eslint-plugin-import/pull/533
+[#413]: https://github.com/import-js/eslint-plugin-import/pull/413
+[#377]: https://github.com/import-js/eslint-plugin-import/pull/377
+[#363]: https://github.com/import-js/eslint-plugin-import/pull/363
+[#289]: https://github.com/import-js/eslint-plugin-import/pull/289
+[#287]: https://github.com/import-js/eslint-plugin-import/pull/287
+[#278]: https://github.com/import-js/eslint-plugin-import/pull/278
+[#181]: https://github.com/import-js/eslint-plugin-import/pull/181
+[#164]: https://github.com/import-js/eslint-plugin-import/pull/164
+
+[#1219]: https://github.com/import-js/eslint-plugin-import/issues/1219
+[#788]: https://github.com/import-js/eslint-plugin-import/issues/788
+[#767]: https://github.com/import-js/eslint-plugin-import/issues/767
+[#681]: https://github.com/import-js/eslint-plugin-import/issues/681
+[#435]: https://github.com/import-js/eslint-plugin-import/issues/435
+[#411]: https://github.com/import-js/eslint-plugin-import/issues/411
+[#357]: https://github.com/import-js/eslint-plugin-import/issues/357
+[#286]: https://github.com/import-js/eslint-plugin-import/issues/286
+[#283]: https://github.com/import-js/eslint-plugin-import/issues/283
 
 [@gausie]: https://github.com/gausie
 [@jquense]: https://github.com/jquense
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index fc8c42e6da..32650c07c2 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -16,7 +16,7 @@
   ],
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/benmosher/eslint-plugin-import.git"
+    "url": "git+https://github.com/import-js/eslint-plugin-import.git"
   },
   "keywords": [
     "eslint-plugin-import",
@@ -28,9 +28,9 @@
   "author": "Ben Mosher (me@benmosher.com)",
   "license": "MIT",
   "bugs": {
-    "url": "https://github.com/benmosher/eslint-plugin-import/issues"
+    "url": "https://github.com/import-js/eslint-plugin-import/issues"
   },
-  "homepage": "https://github.com/benmosher/eslint-plugin-import/tree/master/resolvers/webpack",
+  "homepage": "https://github.com/import-js/eslint-plugin-import/tree/master/resolvers/webpack",
   "dependencies": {
     "array-find": "^1.0.0",
     "debug": "^3.2.7",
diff --git a/src/docsUrl.js b/src/docsUrl.js
index ff277251b4..92b838c097 100644
--- a/src/docsUrl.js
+++ b/src/docsUrl.js
@@ -1,6 +1,6 @@
 import pkg from '../package.json';
 
-const repoUrl = 'https://github.com/benmosher/eslint-plugin-import';
+const repoUrl = 'https://github.com/import-js/eslint-plugin-import';
 
 export default function docsUrl(ruleName, commitish = `v${pkg.version}`) {
   return `${repoUrl}/blob/${commitish}/docs/rules/${ruleName}.md`;
diff --git a/tests/src/config/typescript.js b/tests/src/config/typescript.js
index 34df49b38a..e3fdd10995 100644
--- a/tests/src/config/typescript.js
+++ b/tests/src/config/typescript.js
@@ -4,7 +4,7 @@ import { expect } from 'chai';
 const config = require(path.join(__dirname, '..', '..', '..', 'config', 'typescript'));
 
 describe('config typescript', () => {
-  // https://github.com/benmosher/eslint-plugin-import/issues/1525
+  // https://github.com/import-js/eslint-plugin-import/issues/1525
   it('should mark @types paths as external', () => {
     const externalModuleFolders = config.settings['import/external-module-folders'];
     expect(externalModuleFolders).to.exist;
diff --git a/tests/src/core/docsUrl.js b/tests/src/core/docsUrl.js
index 57b186b2f7..91055bf266 100644
--- a/tests/src/core/docsUrl.js
+++ b/tests/src/core/docsUrl.js
@@ -5,10 +5,10 @@ import docsUrl from '../../../src/docsUrl';
 
 describe('docsUrl', function () {
   it('returns the rule documentation URL when given a rule name', function () {
-    expect(docsUrl('foo')).to.equal(`https://github.com/benmosher/eslint-plugin-import/blob/v${pkg.version}/docs/rules/foo.md`);
+    expect(docsUrl('foo')).to.equal(`https://github.com/import-js/eslint-plugin-import/blob/v${pkg.version}/docs/rules/foo.md`);
   });
 
   it('supports an optional commit-ish parameter', function () {
-    expect(docsUrl('foo', 'bar')).to.equal('https://github.com/benmosher/eslint-plugin-import/blob/bar/docs/rules/foo.md');
+    expect(docsUrl('foo', 'bar')).to.equal('https://github.com/import-js/eslint-plugin-import/blob/bar/docs/rules/foo.md');
   });
 });
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index a3ac4b19b8..a8694ddf26 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -398,7 +398,7 @@ ruleTester.run('no-unresolved syntax verification', rule, {
   invalid:[],
 });
 
-// https://github.com/benmosher/eslint-plugin-import/issues/2024
+// https://github.com/import-js/eslint-plugin-import/issues/2024
 ruleTester.run('import() with built-in parser', rule, {
   valid: [].concat(
     testVersion('>=7', () => ({
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 7798a24cee..e7e6b0566d 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -343,7 +343,7 @@ ruleTester.run('order', rule, {
         ],
       }],
     }),
-    // Using pathGroups (a test case for https://github.com/benmosher/eslint-plugin-import/pull/1724)
+    // Using pathGroups (a test case for https://github.com/import-js/eslint-plugin-import/pull/1724)
     test({
       code: `
         import fs from 'fs';
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 949fa8d582..533382369a 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -85,22 +85,22 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
-[#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026
-[#1786]: https://github.com/benmosher/eslint-plugin-import/pull/1786
-[#1671]: https://github.com/benmosher/eslint-plugin-import/pull/1671
-[#1606]: https://github.com/benmosher/eslint-plugin-import/pull/1606
-[#1602]: https://github.com/benmosher/eslint-plugin-import/pull/1602
-[#1591]: https://github.com/benmosher/eslint-plugin-import/pull/1591
-[#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551
-[#1435]: https://github.com/benmosher/eslint-plugin-import/pull/1435
-[#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
-[#1356]: https://github.com/benmosher/eslint-plugin-import/pull/1356
-[#1290]: https://github.com/benmosher/eslint-plugin-import/pull/1290
-[#1218]: https://github.com/benmosher/eslint-plugin-import/pull/1218
-[#1166]: https://github.com/benmosher/eslint-plugin-import/issues/1166
-[#1160]: https://github.com/benmosher/eslint-plugin-import/pull/1160
-[#1035]: https://github.com/benmosher/eslint-plugin-import/issues/1035
-[#599]: https://github.com/benmosher/eslint-plugin-import/pull/599
+[#2026]: https://github.com/import-js/eslint-plugin-import/pull/2026
+[#1786]: https://github.com/import-js/eslint-plugin-import/pull/1786
+[#1671]: https://github.com/import-js/eslint-plugin-import/pull/1671
+[#1606]: https://github.com/import-js/eslint-plugin-import/pull/1606
+[#1602]: https://github.com/import-js/eslint-plugin-import/pull/1602
+[#1591]: https://github.com/import-js/eslint-plugin-import/pull/1591
+[#1551]: https://github.com/import-js/eslint-plugin-import/pull/1551
+[#1435]: https://github.com/import-js/eslint-plugin-import/pull/1435
+[#1409]: https://github.com/import-js/eslint-plugin-import/pull/1409
+[#1356]: https://github.com/import-js/eslint-plugin-import/pull/1356
+[#1290]: https://github.com/import-js/eslint-plugin-import/pull/1290
+[#1218]: https://github.com/import-js/eslint-plugin-import/pull/1218
+[#1166]: https://github.com/import-js/eslint-plugin-import/issues/1166
+[#1160]: https://github.com/import-js/eslint-plugin-import/pull/1160
+[#1035]: https://github.com/import-js/eslint-plugin-import/issues/1035
+[#599]: https://github.com/import-js/eslint-plugin-import/pull/599
 
 [@hulkish]: https://github.com/hulkish
 [@timkraut]: https://github.com/timkraut
diff --git a/utils/package.json b/utils/package.json
index 2ec00e60a4..f83194150c 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -11,7 +11,7 @@
   },
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/benmosher/eslint-plugin-import.git"
+    "url": "git+https://github.com/import-js/eslint-plugin-import.git"
   },
   "keywords": [
     "eslint-plugin-import",
@@ -22,9 +22,9 @@
   "author": "Ben Mosher <me@benmosher.com>",
   "license": "MIT",
   "bugs": {
-    "url": "https://github.com/benmosher/eslint-plugin-import/issues"
+    "url": "https://github.com/import-js/eslint-plugin-import/issues"
   },
-  "homepage": "https://github.com/benmosher/eslint-plugin-import#readme",
+  "homepage": "https://github.com/import-js/eslint-plugin-import#readme",
   "dependencies": {
     "debug": "^3.2.7",
     "pkg-dir": "^2.0.0"
diff --git a/utils/parse.js b/utils/parse.js
index 468a2acdae..3b2ac028f0 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -35,7 +35,7 @@ exports.default = function parse(path, content, context) {
   // @typescript-eslint/parser will parse the entire project with typechecking if you provide
   // "project" or "projects" in parserOptions. Removing these options means the parser will
   // only parse one file in isolate mode, which is much, much faster.
-  // https://github.com/benmosher/eslint-plugin-import/issues/1408#issuecomment-509298962
+  // https://github.com/import-js/eslint-plugin-import/issues/1408#issuecomment-509298962
   delete parserOptions.project;
   delete parserOptions.projects;
 

From 32bf64556329dd61ef959fa7cc17e547d8031cf8 Mon Sep 17 00:00:00 2001
From: Kostya Zgara <k.zgara@seedium.io>
Date: Sat, 7 Aug 2021 23:16:09 +0300
Subject: [PATCH 331/767] [Docs] add description how to use plugin with yarn
 berry

---
 CHANGELOG.md | 3 +++
 README.md    | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b4c027241f..aa7e74693c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Tests] [`order`]: add tests for `pathGroupsExcludedImportTypes: ['type']` ([#2158], thanks [@atav32])
 - [Docs] [`order`]:  improve the documentation for the `pathGroupsExcludedImportTypes` option ([#2156], thanks [@liby])
 - [Tests] [`no-cycle`]: Restructure test files ([#1517], thanks [@soryy708])
+- [Docs] add description how to use plugin with yarn berry ([#2179], thanks [@KostyaZgara])
 
 ## [2.23.4] - 2021-05-29
 
@@ -819,6 +820,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2179]: https://github.com/import-js/eslint-plugin-import/pull/2179
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
 [#2158]: https://github.com/import-js/eslint-plugin-import/pull/2158
 [#2156]: https://github.com/import-js/eslint-plugin-import/pull/2156
@@ -1357,6 +1359,7 @@ for info on changes for earlier releases.
 [@kiwka]: https://github.com/kiwka
 [@klimashkin]: https://github.com/klimashkin
 [@kmui2]: https://github.com/kmui2
+[@KostyaZgara]: https://github.com/KostyaZgara
 [@knpwrs]: https://github.com/knpwrs
 [@laysent]: https://github.com/laysent
 [@le0nik]: https://github.com/le0nik
diff --git a/README.md b/README.md
index 36801e8103..964c123a7e 100644
--- a/README.md
+++ b/README.md
@@ -348,6 +348,8 @@ An array of folders. Resolved modules only from those folders will be considered
 
 This option is also useful in a monorepo setup: list here all directories that contain monorepo's packages and they will be treated as external ones no matter which resolver is used.
 
+If you are using `yarn` PnP as your package manager, add the `.yarn` folder and all your installed dependencies will be considered as `external`, instead of `internal`.
+
 Each item in this array is either a folder's name, its subpath, or its absolute prefix path:
 
 - `jspm_modules` will match any file or folder named `jspm_modules` or which has a direct or non-direct parent named `jspm_modules`, e.g. `/home/me/project/jspm_modules` or `/home/me/project/jspm_modules/some-pkg/index.js`.

From 74fa6c99cc12f79a25cc33e6819b6073344998f1 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 8 Aug 2021 13:48:19 -0700
Subject: [PATCH 332/767] [resolvers/node] v0.3.5

---
 resolvers/node/CHANGELOG.md | 1 +
 resolvers/node/package.json | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index e8c4d9e2ac..2fbf07ab21 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -5,6 +5,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v0.3.5 - 2021-08-08
 ### Added
 - use "module" in the same spot as "jsnext:main" ([#2166], thanks [@MustafaHaddara])
 
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index c0b4f5d805..993f1b89b6 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-node",
-  "version": "0.3.4",
+  "version": "0.3.5",
   "description": "Node default behavior import resolution plugin for eslint-plugin-import.",
   "main": "index.js",
   "files": [

From 546f87f6c7d87a3cbdff7c8c6d0b36729ec9fa8d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 8 Aug 2021 13:51:39 -0700
Subject: [PATCH 333/767] utils: v2.6.2

---
 utils/CHANGELOG.md | 23 +++++++++++++++--------
 utils/package.json |  2 +-
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 533382369a..9160055145 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v2.6.2 - 2021-08-08
+
+### Fixed
+- Use `context.getPhysicalFilename()` when available (ESLint 7.28+) ([#2160], thanks [@pmcelhaney])
+
 ## v2.6.1 - 2021-05-13
 
 ### Fixed
@@ -85,6 +90,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
 [#2026]: https://github.com/import-js/eslint-plugin-import/pull/2026
 [#1786]: https://github.com/import-js/eslint-plugin-import/pull/1786
 [#1671]: https://github.com/import-js/eslint-plugin-import/pull/1671
@@ -102,16 +108,17 @@ Yanked due to critical issue with cache key resulting from #839.
 [#1035]: https://github.com/import-js/eslint-plugin-import/issues/1035
 [#599]: https://github.com/import-js/eslint-plugin-import/pull/599
 
-[@hulkish]: https://github.com/hulkish
-[@timkraut]: https://github.com/timkraut
-[@vikr01]: https://github.com/vikr01
+[@aladdin-add]: https://github.com/aladdin-add
+[@arcanis]: https://github.com/arcanis
 [@bradzacher]: https://github.com/bradzacher
-[@christophercurrie]: https://github.com/christophercurrie
 [@brettz9]: https://github.com/brettz9
-[@JounQin]: https://github.com/JounQin
-[@arcanis]: https://github.com/arcanis
-[@sompylasar]: https://github.com/sompylasar
+[@christophercurrie]: https://github.com/christophercurrie
+[@hulkish]: https://github.com/hulkish
 [@iamnapo]: https://github.com/iamnapo
+[@JounQin]: https://github.com/JounQin
 [@kaiyoma]: https://github.com/kaiyoma
 [@manuth]: https://github.com/manuth
-[@aladdin-add]: https://github.com/aladdin-add
\ No newline at end of file
+[@pmcelhaney]: https://github.com/pmcelhaney
+[@sompylasar]: https://github.com/sompylasar
+[@timkraut]: https://github.com/timkraut
+[@vikr01]: https://github.com/vikr01
\ No newline at end of file
diff --git a/utils/package.json b/utils/package.json
index f83194150c..f726b79585 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.6.1",
+  "version": "2.6.2",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From 202e5e02db46dfda897ec6952d0a73fea1f23bab Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 8 Aug 2021 13:53:37 -0700
Subject: [PATCH 334/767] Bump to v2.24.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 6 +++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa7e74693c..998055e619 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.24.0] - 2021-08-08
+
 ### Added
 - [`no-dynamic-require`]: add option `esmodule` ([#1223], thanks [@vikr01])
 - [`named`]: add `commonjs` option ([#1222], thanks [@vikr01])
@@ -1179,7 +1181,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.4...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.0...HEAD
+[2.24.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.4...v2.24.0
 [2.23.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.3...v2.23.4
 [2.23.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.2...v2.23.3
 [2.23.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.1...v2.23.2
diff --git a/package.json b/package.json
index d475bdf630..e3bc5a8d96 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.23.4",
+  "version": "2.24.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"
@@ -104,8 +104,8 @@
     "array.prototype.flat": "^1.2.4",
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
-    "eslint-import-resolver-node": "^0.3.4",
-    "eslint-module-utils": "^2.6.1",
+    "eslint-import-resolver-node": "^0.3.5",
+    "eslint-module-utils": "^2.6.2",
     "find-up": "^2.0.0",
     "has": "^1.0.3",
     "is-core-module": "^2.4.0",

From ce540b636672854b71420c72fa00f45595aa332b Mon Sep 17 00:00:00 2001
From: Maxim Mazurok <maxim@mazurok.com>
Date: Tue, 10 Aug 2021 00:06:22 +1000
Subject: [PATCH 335/767] [Fix] `ExportMap`: Add default export when
 esModuleInterop is true and anything is exported

Fixes #2183. See #1689.
---
 CHANGELOG.md                                  |  4 ++++
 src/ExportMap.js                              | 22 ++++++++++++++-----
 .../index.d.ts                                | 19 ++++++++++++++++
 .../tsconfig.json                             |  5 +++++
 tests/src/rules/default.js                    | 11 ++++++++++
 5 files changed, 55 insertions(+), 6 deletions(-)
 create mode 100644 tests/files/typescript-export-react-test-renderer/index.d.ts
 create mode 100644 tests/files/typescript-export-react-test-renderer/tsconfig.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 998055e619..d8993f0d3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixe
+- `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok])
+
 ## [2.24.0] - 2021-08-08
 
 ### Added
@@ -822,6 +825,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2184]: https://github.com/import-js/eslint-plugin-import/pull/2184
 [#2179]: https://github.com/import-js/eslint-plugin-import/pull/2179
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
 [#2158]: https://github.com/import-js/eslint-plugin-import/pull/2158
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 76b07f9dc9..46d3cfe88c 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -351,6 +351,7 @@ ExportMap.for = function (context) {
 
 ExportMap.parse = function (path, content, context) {
   const m = new ExportMap(path);
+  const isEsModuleInteropTrue = isEsModuleInterop();
 
   let ast;
   try {
@@ -576,8 +577,6 @@ ExportMap.parse = function (path, content, context) {
       });
     }
 
-    const isEsModuleInteropTrue = isEsModuleInterop();
-
     const exports = ['TSExportAssignment'];
     if (isEsModuleInteropTrue) {
       exports.push('TSNamespaceExportDeclaration');
@@ -606,8 +605,11 @@ ExportMap.parse = function (path, content, context) {
         m.namespace.set('default', captureDoc(source, docStyleParsers, n));
         return;
       }
-      if (isEsModuleInteropTrue) {
-        m.namespace.set('default', {});
+      if (
+        isEsModuleInteropTrue // esModuleInterop is on in tsconfig
+        && !m.namespace.has('default') // and default isn't added already
+      ) {
+        m.namespace.set('default', {}); // add default export
       }
       exportedDecls.forEach((decl) => {
         if (decl.type === 'TSModuleDeclaration') {
@@ -627,8 +629,8 @@ ExportMap.parse = function (path, content, context) {
                 namespaceDecl.declarations.forEach((d) =>
                   recursivePatternCapture(d.id, (id) => m.namespace.set(
                     id.name,
-                    captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode)
-                  ))
+                    captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode),
+                  )),
                 );
               } else {
                 m.namespace.set(
@@ -645,6 +647,14 @@ ExportMap.parse = function (path, content, context) {
     }
   });
 
+  if (
+    isEsModuleInteropTrue // esModuleInterop is on in tsconfig
+    && m.namespace.size > 0 // anything is exported
+    && !m.namespace.has('default') // and default isn't added already
+  ) {
+    m.namespace.set('default', {}); // add default export
+  }
+
   return m;
 };
 
diff --git a/tests/files/typescript-export-react-test-renderer/index.d.ts b/tests/files/typescript-export-react-test-renderer/index.d.ts
new file mode 100644
index 0000000000..ff70c71354
--- /dev/null
+++ b/tests/files/typescript-export-react-test-renderer/index.d.ts
@@ -0,0 +1,19 @@
+// case from @types/react-test-renderer
+
+export {};
+
+export interface ReactTestRendererJSON {
+    type: string;
+    props: { [propName: string]: any };
+    children: null | ReactTestRendererNode[];
+}
+export type ReactTestRendererNode = ReactTestRendererJSON | string;
+export interface ReactTestRendererTree extends ReactTestRendererJSON {
+    nodeType: 'component' | 'host';
+    instance: any;
+    rendered: null | ReactTestRendererTree | ReactTestRendererTree[];
+}
+
+export function create(nextElement: any, options?: any): any;
+
+export function act(callback: () => Promise<any>): Promise<undefined>;
diff --git a/tests/files/typescript-export-react-test-renderer/tsconfig.json b/tests/files/typescript-export-react-test-renderer/tsconfig.json
new file mode 100644
index 0000000000..a72ee3e88b
--- /dev/null
+++ b/tests/files/typescript-export-react-test-renderer/tsconfig.json
@@ -0,0 +1,5 @@
+{
+    "compilerOptions": {
+        "esModuleInterop": true
+    }
+}
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index c7eb780d00..a861fff76f 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -220,6 +220,17 @@ context('TypeScript', function () {
             tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-as-default-namespace/'),
           },
         }),
+        test({
+          code: `import Foo from "./typescript-export-react-test-renderer"`,
+          parser: parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+          parserOptions: {
+            tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-react-test-renderer/'),
+          },
+        }),
         test({
           code: `import foobar from "./typescript-export-assign-property"`,
           parser: parser,

From ec825d0abc1a8b18fb2851c51a64205df1a48cef Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 12 Aug 2021 23:20:22 -0700
Subject: [PATCH 336/767] [meta] add Open Collective

---
 .github/FUNDING.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 8fd7679907..0ef28872fd 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -2,7 +2,7 @@
 
 github: [ljharb]
 patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
+open_collective: eslint-plugin-import # Replace with a single Open Collective username
 ko_fi: # Replace with a single Ko-fi username
 tidelift: npm/eslint-plugin-import
 community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry

From 513bb0b262e57d32852fbc9a69bc73178ac1dda8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 13 Aug 2021 16:09:21 -0700
Subject: [PATCH 337/767] [meta] fix some formatting

---
 CHANGELOG.md                         |  67 +++-
 tests/src/rules/no-unused-modules.js | 553 ++++++++++++++++++---------
 2 files changed, 430 insertions(+), 190 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d8993f0d3c..aa4d0f533e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
-### Fixe
+### Fixed
 - `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok])
 
 ## [2.24.0] - 2021-08-08
@@ -97,6 +97,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Docs] Add import/recommended ruleset to README ([#2034], thanks [@edemaine])
 
 ## [2.22.1] - 2020-09-27
+
 ### Fixed
 - [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
 - [`extensions`]/importType: Fix @/abc being treated as scoped module ([#1854], thanks [@3nuc])
@@ -107,6 +108,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`export`]: add tests for a name collision with `export * from` ([#1704], thanks @tomprats)
 
 ## [2.22.0] - 2020-06-26
+
 ### Added
 - [`no-unused-modules`]: consider exported TypeScript interfaces, types and enums ([#1819], thanks [@nicolashenry])
 - [`no-cycle`]: allow `maxDepth` option to be `"∞"` (thanks [@ljharb])
@@ -127,16 +129,19 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [docs] [`imports-first`]: deprecation info and link to `first` docs ([#1835], thanks [@beatrizrezener])
 
 ## [2.21.2] - 2020-06-09
+
 ### Fixed
 - [`order`]: avoid a crash on TypeScript’s `export import` syntax ([#1808], thanks [@ljharb])
 - [`newline-after-import`]: consider TypeScript `import =` syntax' ([#1811], thanks [@ljharb])
 - [`no-internal-modules`]: avoid a crash on a named export declaration ([#1814], thanks [@ljharb])
 
 ## [2.21.1] - 2020-06-07
+
 ### Fixed
 - TypeScript: [`import/named`]: avoid requiring `typescript` when not using TS ([#1805], thanks [@ljharb])
 
 ## [2.21.0] - 2020-06-07
+
 ### Added
 - [`import/default`]: support default export in TSExportAssignment ([#1528], thanks [@joaovieira])
 - [`no-cycle`]: add `ignoreExternal` option ([#1681], thanks [@sveyret])
@@ -167,6 +172,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [eslint] bump minimum v7 version to v7.2.0
 
 ## [2.20.2] - 2020-03-28
+
 ### Fixed
 - [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
 - [`order`]: recognize ".." as a "parent" path ([#1658], thanks [@golopot])
@@ -176,6 +182,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Docs] `no-webpack-loader-syntax`: Updates webpack URLs ([#1751], thanks [@MikeyBeLike])
 
 ## [2.20.1] - 2020-02-01
+
 ### Fixed
 - [`export`]: Handle function overloading in `*.d.ts` ([#1619], thanks [@IvanGoncharov])
 - [`no-absolute-path`]: fix a crash with invalid import syntax ([#1616], thanks [@ljharb])
@@ -193,6 +200,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Tests] `order`: Add TS import type tests ([#1736], thanks [@kmui2])
 
 ## [2.20.0] - 2020-01-10
+
 ### Added
 - [`order`]: added `caseInsensitive` as an additional option to `alphabetize` ([#1586], thanks [@dbrewer5])
 - [`no-restricted-paths`]: New `except` option per `zone`, allowing exceptions to be defined for a restricted zone ([#1238], thanks [@rsolomon])
@@ -209,10 +217,12 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extensions`]: improve `ignorePackages` docs ([#1248], thanks [@ivo-stefchev])
 
 ## [2.19.1] - 2019-12-08
+
 ### Fixed
 - [`no-extraneous-dependencies`]: ensure `node.source` exists
 
 ## [2.19.0] - 2019-12-08
+
 ### Added
 - [`internal-regex` setting]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
@@ -244,10 +254,12 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unused-modules`]/`eslint-module-utils`: Avoid superfluous calls and code ([#1551], thanks [@brettz9])
 
 ## [2.18.2] - 2019-07-19
+
 ### Fixed
 - Skip warning on type interfaces ([#1425], thanks [@lencioni])
 
 ## [2.18.1] - 2019-07-18
+
 ### Fixed
 - Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
 - [`prefer-default-export`]: don't warn on TypeAlias & TSTypeAliasDeclaration ([#1377], thanks [@sharmilajesupaul])
@@ -258,6 +270,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-extraneous-dependencies`], `importType`: remove lodash ([#1419], thanks [@ljharb])
 
 ## [2.18.0] - 2019-06-24
+
 ### Added
 - Support eslint v6 ([#1393], thanks [@sheepsteak])
 - [`order`]: Adds support for correctly sorting unknown types into a single group ([#1375], thanks [@swernerx])
@@ -272,6 +285,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-named-as-default-member`]: update broken link ([#1389], thanks [@fooloomanzoo])
 
 ## [2.17.3] - 2019-05-23
+
 ### Fixed
 - [`no-common-js`]: Also throw an error when assigning ([#1354], thanks [@charlessuh])
 - [`no-unused-modules`]: don't crash when lint file outside src-folder ([#1347], thanks [@rfermann])
@@ -287,15 +301,18 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - Document `env` option for `eslint-import-resolver-webpack` ([#1363], thanks [@kgregory])
 
 ## [2.17.2] - 2019-04-16
+
 ### Fixed
 - [`no-unused-modules`]: avoid crash when using `ignoreExports`-option ([#1331], [#1323], thanks [@rfermann])
 - [`no-unused-modules`]: make sure that rule with no options will not fail ([#1330], [#1334], thanks [@kiwka])
 
 ## [2.17.1] - 2019-04-13
+
 ### Fixed
 - require v2.4 of `eslint-module-utils` ([#1322])
 
 ## [2.17.0] - 2019-04-13
+
 ### Added
 - [`no-useless-path-segments`]: Add `noUselessIndex` option ([#1290], thanks [@timkraut])
 - [`no-duplicates`]: Add autofix ([#1312], thanks [@lydell])
@@ -321,6 +338,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-commonjs`]: add tests that show corner cases ([#1308], thanks [@TakeScoop])
 
 ## [2.16.0] - 2019-01-29
+
 ### Added
 - `typescript` config ([#1257], thanks [@kirill-konshin])
 
@@ -328,6 +346,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - Memory leak of `SourceCode` objects for all parsed dependencies, resolved. (issue [#1266], thanks [@asapach] and [@sergei-startsev] for digging in)
 
 ## [2.15.0] - 2019-01-22
+
 ### Added
 - new rule: [`no-named-export`] ([#1157], thanks [@fsmaia])
 
@@ -337,6 +356,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`named`]: fix destructuring assignment ([#1232], thanks [@ljqx])
 
 ## [2.14.0] - 2018-08-13
+
 ### Added
 - [`no-useless-path-segments`]: add commonJS (CJS) support ([#1128], thanks [@1pete])
 - [`namespace`]: add JSX check ([#1151], thanks [@jf248])
@@ -352,6 +372,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - add explicit support for RestElement alongside ExperimentalRestProperty (thanks [@ljharb])
 
 ## [2.13.0] - 2018-06-24
+
 ### Added
 - Add ESLint 5 support ([#1122], thanks [@ai] and [@ljharb])
 - Add [`no-relative-parent-imports`] rule: disallow relative imports from parent directories ([#1093], thanks [@chrislloyd])
@@ -360,12 +381,14 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - `namespace` rule: ensure it works in eslint 5/ecmaVersion 2018 (thanks [@ljharb])
 
 ## [2.12.0] - 2018-05-17
+
 ### Added
 - Ignore type imports for [`named`] rule ([#931], thanks [@mattijsbliek])
 - Add documentation for [`no-useless-path-segments`] rule ([#1068], thanks [@manovotny])
 - `packageDir` option for [`no-extraneous-dependencies`] can be array-valued ([#1085], thanks [@hulkish])
 
 ## [2.11.0] - 2018-04-09
+
 ### Added
 - Fixer for [`first`] ([#1046], thanks [@fengkfengk])
 - `allow-require` option for [`no-commonjs`] rule ([#880], thanks [@futpib])
@@ -374,11 +397,13 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - memory/CPU regression where ASTs were held in memory ([#1058], thanks [@klimashkin]/[@lukeapage])
 
 ## [2.10.0] - 2018-03-29
+
 ### Added
 - Autofixer for [`order`] rule ([#908], thanks [@tihonove])
 - Add [`no-cycle`] rule: reports import cycles.
 
 ## [2.9.0] - 2018-02-21
+
 ### Added
 - Add [`group-exports`] rule: style-guide rule to report use of multiple named exports ([#721], thanks [@robertrossmann])
 - Add [`no-self-import`] rule: forbids a module from importing itself. ([#727], [#449], [#447], thanks [@giodamelio]).
@@ -399,14 +424,17 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - TypeError for missing AST fields from TypeScript ([#842] / [#944], thanks [@alexgorbatchev])
 
 ## [2.7.0] - 2017-07-06
+
 ### Changed
 - [`no-absolute-path`] picks up speed boost, optional AMD support ([#843], thanks [@jseminck])
 
 ## [2.6.1] - 2017-06-29
+
 ### Fixed
 - update bundled node resolver dependency to latest version
 
 ## [2.6.0] - 2017-06-23
+
 ### Changed
 - update tests / peerDeps for ESLint 4.0 compatibility ([#871], thanks [@mastilver])
 - [`memo-parser`] updated to require `filePath` on parser options as it melts
@@ -429,6 +457,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - Add `allow` option to [`no-unassigned-import`] to allow for files that match the globs ([#671], [#737], thanks [@kevin940726]).
 
 ## [2.3.0] - 2017-05-18
+
 ### Added
 - [`no-anonymous-default-export`] rule: report anonymous default exports ([#712], thanks [@duncanbeevers]).
 - Add new value to [`order`]'s `newlines-between` option to allow newlines inside import groups ([#627], [#628], thanks [@giodamelio])
@@ -443,8 +472,8 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - "default is a reserved keyword" in no-maned-default tests by locking down babylon to 6.15.0 (#756, thanks @gmathieu)
 - support scoped modules containing non word characters
 
-
 ## [2.2.0] - 2016-11-07
+
 ### Fixed
 - Corrected a few gaffs in the auto-ignore logic to fix major performance issues
   with projects that did not explicitly ignore `node_modules`. ([#654])
@@ -453,6 +482,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - [`prefer-default-export`]: fixed crash on export extensions ([#653])
 
 ## [2.1.0] - 2016-11-02
+
 ### Added
 - Add [`no-named-default`] rule: style-guide rule to report use of unnecessarily named default imports ([#596], thanks [@ntdb])
 - [`no-extraneous-dependencies`]: check globs against CWD + absolute path ([#602] + [#630], thanks [@ljharb])
@@ -465,10 +495,12 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - Fixed documentation for the default values for the [`order`] rule ([#601])
 
 ## [2.0.1] - 2016-10-06
+
 ### Fixed
 - Fixed code that relied on removed dependencies. ([#604])
 
 ## [2.0.0]! - 2016-09-30
+
 ### Added
 - [`unambiguous`] rule: report modules that are not unambiguously ES modules.
 - `recommended` shared config. Roughly `errors` and `warnings` mixed together,
@@ -494,6 +526,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - [`no-internal-modules`]: support `@`-scoped packages ([#577]+[#578], thanks [@spalger])
 
 ## [1.16.0] - 2016-09-22
+
 ### Added
 - Added [`no-dynamic-require`] rule: forbid `require()` calls with expressions. ([#567], [#568])
 - Added [`no-internal-modules`] rule: restrict deep package imports to specific folders. ([#485], thanks [@spalger]!)
@@ -504,6 +537,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - [`default`]: allow re-export of values from ignored files as default ([#545], thanks [@skyrpex])
 
 ## [1.15.0] - 2016-09-12
+
 ### Added
 - Added an `allow` option to [`no-nodejs-modules`] to allow exceptions ([#452], [#509]).
 - Added [`no-absolute-path`] rule ([#530], [#538])
@@ -514,6 +548,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - [`no-named-as-default-member`] Allow default import to have a property named "default" ([#507], [#508], thanks [@jquense] for both!)
 
 ## [1.14.0] - 2016-08-22
+
 ### Added
 - [`import/parsers` setting]: parse some dependencies (i.e. TypeScript!) with a different parser than the ESLint-configured parser. ([#503])
 
@@ -521,6 +556,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - [`namespace`] exception for get property from `namespace` import, which are re-export from commonjs module ([#499] fixes [#416], thanks [@wKich])
 
 ## [1.13.0] - 2016-08-11
+
 ### Added
 - `allowComputed` option for [`namespace`] rule. If set to `true`, won't report
   computed member references to namespaces. (see [#456])
@@ -533,15 +569,18 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
   in an imported file. (fixes [#478], thanks [@rhys-vdw])
 
 ## [1.12.0] - 2016-07-26
+
 ### Added
 - [`import/external-module-folders` setting]: a possibility to configure folders for "external" modules ([#444], thanks [@zloirock])
 
 ## [1.11.1] - 2016-07-20
+
 ### Fixed
 - [`newline-after-import`] exception for `switch` branches with `require`s iff parsed as `sourceType:'module'`.
   (still [#441], thanks again [@ljharb])
 
 ## [1.11.0] - 2016-07-17
+
 ### Added
 - Added an `peerDependencies` option to [`no-extraneous-dependencies`] to allow/forbid peer dependencies ([#423], [#428], thanks [@jfmengels]!).
 
@@ -550,20 +589,24 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
   function expression (e.g. `() => require('a') || require('b')`). ([#441], thanks [@ljharb])
 
 ## [1.10.3] - 2016-07-08
+
 ### Fixed
 - removing `Symbol` dependencies (i.e. `for-of` loops) due to Node 0.10 polyfill
   issue (see [#415]). Should not make any discernible semantic difference.
 
 ## [1.10.2] - 2016-07-04
+
 ### Fixed
 - Something horrible happened during `npm prepublish` of 1.10.1.
   Several `rm -rf node_modules && npm i` and `gulp clean && npm prepublish`s later, it is rebuilt and republished as 1.10.2. Thanks [@rhettlivingston] for noticing and reporting!
 
 ## [1.10.1] - 2016-07-02 [YANKED]
+
 ### Added
 - Officially support ESLint 3.x. (peerDependencies updated to `2.x - 3.x`)
 
 ## [1.10.0] - 2016-06-30
+
 ### Added
 - Added new rule [`no-restricted-paths`]. ([#155]/[#371], thanks [@lo1tuma])
 - [`import/core-modules` setting]: allow configuration of additional module names,
@@ -574,14 +617,17 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - Fixed crash with `newline-after-import` related to the use of switch cases. (fixes [#386], thanks [@ljharb] for reporting) ([#395])
 
 ## [1.9.2] - 2016-06-21
+
 ### Fixed
 - Issues with ignored/CJS files in [`export`] and [`no-deprecated`] rules. ([#348], [#370])
 
 ## [1.9.1] - 2016-06-16
+
 ### Fixed
 - Reordered precedence for loading resolvers. ([#373])
 
 ## [1.9.0] - 2016-06-10
+
 ### Added
 - Added support TomDoc comments to [`no-deprecated`]. ([#321], thanks [@josh])
 - Added support for loading custom resolvers ([#314], thanks [@le0nik])
@@ -590,6 +636,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - [`prefer-default-export`] handles `export function` and `export const` in same file ([#359], thanks [@scottnonnenberg])
 
 ## [1.8.1] - 2016-05-23
+
 ### Fixed
 - `export * from 'foo'` now properly ignores a `default` export from `foo`, if any. ([#328]/[#332], thanks [@jkimbo])
   This impacts all static analysis of imported names. ([`default`], [`named`], [`namespace`], [`export`])
@@ -599,6 +646,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - [`prefer-default-export`] properly handles deep destructuring, `export * from ...`, and files with no exports. ([#342]+[#343], thanks [@scottnonnenberg])
 
 ## [1.8.0] - 2016-05-11
+
 ### Added
 - [`prefer-default-export`], new rule. ([#308], thanks [@gavriguy])
 
@@ -607,6 +655,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - Make [`no-extraneous-dependencies`] handle scoped packages ([#316], thanks [@jfmengels])
 
 ## [1.7.0] - 2016-05-06
+
 ### Added
 - [`newline-after-import`], new rule. ([#245], thanks [@singles])
 - Added an `optionalDependencies` option to [`no-extraneous-dependencies`] to allow/forbid optional dependencies ([#266], thanks [@jfmengels]).
@@ -621,6 +670,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
   module is not resolved. Also, never report for builtins (i.e. `path`). ([#296])
 
 ## [1.6.1] - 2016-04-28
+
 ### Fixed
 - [`no-named-as-default-member`]: don't crash on rest props. ([#281], thanks [@SimenB])
 - support for Node 6: don't pass `null` to `path` functions.
@@ -628,6 +678,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
   config ([#288]).
 
 ## [1.6.0] - 2016-04-25
+
 ### Added
 - add [`no-named-as-default-member`] to `warnings` canned config
 - add [`no-extraneous-dependencies`] rule ([#241], thanks [@jfmengels])
@@ -646,6 +697,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - [`no-named-as-default-member`] had a crash on destructuring in loops (thanks for heads up from [@lemonmade])
 
 ## [1.5.0] - 2016-04-18
+
 ### Added
 - report resolver errors at the top of the linted file
 - add [`no-namespace`] rule ([#239], thanks [@singles])
@@ -658,6 +710,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - support for Node 0.10, via `es6-*` ponyfills. Using native Map/Set/Symbol.
 
 ## [1.4.0] - 2016-03-25
+
 ### Added
 - Resolver plugin interface v2: more explicit response format that more clearly covers the found-but-core-module case, where there is no path.
   Still backwards-compatible with the original version of the resolver spec.
@@ -668,6 +721,7 @@ Yanked due to critical issue in eslint-module-utils with cache key resulting fro
 - using `es6-*` ponyfills instead of `babel-runtime`
 
 ## [1.3.0] - 2016-03-20
+
 Major perf improvements. Between parsing only once and ignoring gigantic, non-module `node_modules`,
 there is very little added time.
 
@@ -683,6 +737,7 @@ memoizing parser, and takes only 27s with naked `babel-eslint` (thus, reparsing
   something that looks like an `export` is detected in the module content.
 
 ## [1.2.0] - 2016-03-19
+
 Thanks [@lencioni] for identifying a huge amount of rework in resolve and kicking
 off a bunch of memoization.
 
@@ -693,6 +748,7 @@ I'm seeing 62% improvement over my normal test codebase when executing only
 - added caching to core/resolve via [#214], configured via [`import/cache` setting]
 
 ## [1.1.0] - 2016-03-15
+
 ### Added
 - Added an [`ignore`](./docs/rules/no-unresolved.md#ignore) option to [`no-unresolved`] for those pesky files that no resolver can find. (still prefer enhancing the Webpack and Node resolvers to using it, though). See [#89] for details.
 
@@ -744,6 +800,7 @@ I'm seeing 62% improvement over my normal test codebase when executing only
 - `babylon` as default import parser (see Breaking)
 
 ## [0.13.0] - 2016-02-08
+
 ### Added
 - [`no-commonjs`] rule
 - [`no-amd`] rule
@@ -752,17 +809,21 @@ I'm seeing 62% improvement over my normal test codebase when executing only
 - Removed vestigial `no-require` rule. [`no-commonjs`] is more complete.
 
 ## [0.12.2] - 2016-02-06 [YANKED]
+
 Unpublished from npm and re-released as 0.13.0. See [#170].
 
 ## [0.12.1] - 2015-12-17
+
 ### Changed
 - Broke docs for rules out into individual files.
 
 ## [0.12.0] - 2015-12-14
+
 ### Changed
 - Ignore [`import/ignore` setting] if exports are actually found in the parsed module. Does this to support use of `jsnext:main` in `node_modules` without the pain of managing an allow list or a nuanced deny list.
 
 ## [0.11.0] - 2015-11-27
+
 ### Added
 - Resolver plugins. Now the linter can read Webpack config, properly follow aliases and ignore externals, dismisses inline loaders, etc. etc.!
 
@@ -1366,8 +1427,8 @@ for info on changes for earlier releases.
 [@kiwka]: https://github.com/kiwka
 [@klimashkin]: https://github.com/klimashkin
 [@kmui2]: https://github.com/kmui2
-[@KostyaZgara]: https://github.com/KostyaZgara
 [@knpwrs]: https://github.com/knpwrs
+[@KostyaZgara]: https://github.com/KostyaZgara
 [@laysent]: https://github.com/laysent
 [@le0nik]: https://github.com/le0nik
 [@lemonmade]: https://github.com/lemonmade
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 283fa3e984..17e52b411b 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -4,8 +4,8 @@ import typescriptConfig from '../../../config/typescript';
 
 import { RuleTester } from 'eslint';
 import fs from 'fs';
-import semver from 'semver';
 import eslintPkg from 'eslint/package.json';
+import semver from 'semver';
 
 // TODO: figure out why these tests fail in eslint 4
 const isESLint4TODO = semver.satisfies(eslintPkg.version, '^4');
@@ -108,34 +108,50 @@ ruleTester.run('no-unused-modules', rule, {
 // tests for  exports
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'import { o2 } from "./file-o";export default () => 12',
-      filename: testFilePath('./no-unused-modules/file-a.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-a.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export const b = 2',
-      filename: testFilePath('./no-unused-modules/file-b.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-b.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const c1 = 3; function c2() { return 3 }; export { c1, c2 }',
-      filename: testFilePath('./no-unused-modules/file-c.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-c.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export function d() { return 4 }',
-      filename: testFilePath('./no-unused-modules/file-d.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-d.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export class q { q0() {} }',
-      filename: testFilePath('./no-unused-modules/file-q.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-q.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const e0 = 5; export { e0 as e }',
-      filename: testFilePath('./no-unused-modules/file-e.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-e.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const l0 = 5; const l = 10; export { l0 as l1, l }; export default () => {}',
-      filename: testFilePath('./no-unused-modules/file-l.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-l.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const o0 = 0; const o1 = 1; export { o0, o1 as o2 }; export default () => {}',
-      filename: testFilePath('./no-unused-modules/file-o.js') }),
+      filename: testFilePath('./no-unused-modules/file-o.js'),
+    }),
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import eslint from 'eslint'
            import fileA from './file-a'
            import { b } from './file-b'
@@ -155,11 +171,14 @@ ruleTester.run('no-unused-modules', rule, {
         error(`exported declaration 'o0' not used within other modules`),
         error(`exported declaration 'o3' not used within other modules`),
         error(`exported declaration 'p' not used within other modules`),
-      ] }),
-    test({ options: unusedExportsOptions,
+      ],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: `const n0 = 'n0'; const n1 = 42; export { n0, n1 }; export default () => {}`,
       filename: testFilePath('./no-unused-modules/file-n.js'),
-      errors: [error(`exported declaration 'default' not used within other modules`)] }),
+      errors: [error(`exported declaration 'default' not used within other modules`)],
+    }),
   ],
 });
 
@@ -167,60 +186,80 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'export default () => 13',
       filename: testFilePath('./no-unused-modules/file-f.js'),
-      errors: [error(`exported declaration 'default' not used within other modules`)] }),
-    test({ options: unusedExportsOptions,
+      errors: [error(`exported declaration 'default' not used within other modules`)],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export const g = 2',
       filename: testFilePath('./no-unused-modules/file-g.js'),
-      errors: [error(`exported declaration 'g' not used within other modules`)] }),
-    test({ options: unusedExportsOptions,
+      errors: [error(`exported declaration 'g' not used within other modules`)],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const h1 = 3; function h2() { return 3 }; const h3 = true; export { h1, h2, h3 }',
       filename: testFilePath('./no-unused-modules/file-h.js'),
-      errors: [error(`exported declaration 'h1' not used within other modules`)] }),
-    test({ options: unusedExportsOptions,
+      errors: [error(`exported declaration 'h1' not used within other modules`)],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const i1 = 3; function i2() { return 3 }; export { i1, i2 }',
       filename: testFilePath('./no-unused-modules/file-i.js'),
       errors: [
         error(`exported declaration 'i1' not used within other modules`),
         error(`exported declaration 'i2' not used within other modules`),
-      ] }),
-    test({ options: unusedExportsOptions,
+      ],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export function j() { return 4 }',
       filename: testFilePath('./no-unused-modules/file-j.js'),
-      errors: [error(`exported declaration 'j' not used within other modules`)] }),
-    test({ options: unusedExportsOptions,
+      errors: [error(`exported declaration 'j' not used within other modules`)],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export class q { q0() {} }',
       filename: testFilePath('./no-unused-modules/file-q.js'),
-      errors: [error(`exported declaration 'q' not used within other modules`)] }),
-    test({ options: unusedExportsOptions,
+      errors: [error(`exported declaration 'q' not used within other modules`)],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const k0 = 5; export { k0 as k }',
       filename: testFilePath('./no-unused-modules/file-k.js'),
-      errors: [error(`exported declaration 'k' not used within other modules`)] }),
+      errors: [error(`exported declaration 'k' not used within other modules`)],
+    }),
   ],
 });
 
-// // test for export from
+// test for export from
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `export { default } from './file-o'`,
-      filename: testFilePath('./no-unused-modules/file-s.js') }),
+      filename: testFilePath('./no-unused-modules/file-s.js'),
+    }),
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `export { k } from '${testFilePath('./no-unused-modules/file-k.js')}'`,
       filename: testFilePath('./no-unused-modules/file-j.js'),
-      errors: [error(`exported declaration 'k' not used within other modules`)] }),
+      errors: [error(`exported declaration 'k' not used within other modules`)],
+    }),
   ],
 });
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'const k0 = 5; export { k0 as k }',
-      filename: testFilePath('./no-unused-modules/file-k.js') }),
+      filename: testFilePath('./no-unused-modules/file-k.js'),
+    }),
   ],
   invalid: [],
 });
@@ -228,24 +267,36 @@ ruleTester.run('no-unused-modules', rule, {
 // test for ignored files
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'export default () => 14',
-      filename: testFilePath('./no-unused-modules/file-ignored-a.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-ignored-a.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export const b = 2',
-      filename: testFilePath('./no-unused-modules/file-ignored-b.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-ignored-b.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const c1 = 3; function c2() { return 3 }; export { c1, c2 }',
-      filename: testFilePath('./no-unused-modules/file-ignored-c.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-ignored-c.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export function d() { return 4 }',
-      filename: testFilePath('./no-unused-modules/file-ignored-d.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-ignored-d.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const f = 5; export { f as e }',
-      filename: testFilePath('./no-unused-modules/file-ignored-e.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-ignored-e.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const l0 = 5; const l = 10; export { l0 as l1, l }; export default () => {}',
-      filename: testFilePath('./no-unused-modules/file-ignored-l.js') }),
+      filename: testFilePath('./no-unused-modules/file-ignored-l.js'),
+    }),
   ],
   invalid: [],
 });
@@ -253,27 +304,35 @@ ruleTester.run('no-unused-modules', rule, {
 // add named import for file with default export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import { f } from '${testFilePath('./no-unused-modules/file-f.js')}'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'export default () => 15',
       filename: testFilePath('./no-unused-modules/file-f.js'),
-      errors: [error(`exported declaration 'default' not used within other modules`)] }),
+      errors: [error(`exported declaration 'default' not used within other modules`)],
+    }),
   ],
 });
 
 // add default import for file with default export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import f from '${testFilePath('./no-unused-modules/file-f.js')}'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export default () => 16',
-      filename: testFilePath('./no-unused-modules/file-f.js') }),
+      filename: testFilePath('./no-unused-modules/file-f.js'),
+    }),
   ],
   invalid: [],
 });
@@ -281,26 +340,34 @@ ruleTester.run('no-unused-modules', rule, {
 // add default import for file with named export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import g from '${testFilePath('./no-unused-modules/file-g.js')}';import {h} from '${testFilePath('./no-unused-modules/file-gg.js')}'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'export const g = 2',
       filename: testFilePath('./no-unused-modules/file-g.js'),
-      errors: [error(`exported declaration 'g' not used within other modules`)] })],
+      errors: [error(`exported declaration 'g' not used within other modules`)],
+    })],
 });
 
 // add named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import { g } from '${testFilePath('./no-unused-modules/file-g.js')}'; import eslint from 'eslint'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export const g = 2',
-      filename: testFilePath('./no-unused-modules/file-g.js') }),
+      filename: testFilePath('./no-unused-modules/file-g.js'),
+    }),
   ],
   invalid: [],
 });
@@ -308,27 +375,35 @@ ruleTester.run('no-unused-modules', rule, {
 // add different named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import { c } from '${testFilePath('./no-unused-modules/file-b.js')}'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'export const b = 2',
       filename: testFilePath('./no-unused-modules/file-b.js'),
-      errors: [error(`exported declaration 'b' not used within other modules`)] }),
+      errors: [error(`exported declaration 'b' not used within other modules`)],
+    }),
   ],
 });
 
 // add renamed named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import { g as g1 } from '${testFilePath('./no-unused-modules/file-g.js')}'; import eslint from 'eslint'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'export const g = 2',
-      filename: testFilePath('./no-unused-modules/file-g.js') }),
+      filename: testFilePath('./no-unused-modules/file-g.js'),
+    }),
   ],
   invalid: [],
 });
@@ -336,30 +411,38 @@ ruleTester.run('no-unused-modules', rule, {
 // add different renamed named import for file with named export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import { g1 as g } from '${testFilePath('./no-unused-modules/file-g.js')}'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'export const g = 2',
       filename: testFilePath('./no-unused-modules/file-g.js'),
-      errors: [error(`exported declaration 'g' not used within other modules`)] }),
+      errors: [error(`exported declaration 'g' not used within other modules`)],
+    }),
   ],
 });
 
 // remove default import for file with default export
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import { a1, a2 } from '${testFilePath('./no-unused-modules/file-a.js')}'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'export default () => 17',
       filename: testFilePath('./no-unused-modules/file-a.js'),
-      errors: [error(`exported declaration 'default' not used within other modules`)] }),
+      errors: [error(`exported declaration 'default' not used within other modules`)],
+    }),
   ],
 });
 
@@ -367,24 +450,30 @@ ruleTester.run('no-unused-modules', rule, {
 ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-m.js'),
       errors: [
         error(`exported declaration 'm1' not used within other modules`),
         error(`exported declaration 'm' not used within other modules`),
         error(`exported declaration 'default' not used within other modules`),
-      ] }),
+      ],
+    }),
   ],
 });
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `import * as m from '${testFilePath('./no-unused-modules/file-m.js')}'; import unknown from 'unknown-module'`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
-    test({ options: unusedExportsOptions,
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
-      filename: testFilePath('./no-unused-modules/file-m.js') }),
+      filename: testFilePath('./no-unused-modules/file-m.js'),
+    }),
   ],
   invalid: [],
 });
@@ -392,82 +481,103 @@ ruleTester.run('no-unused-modules', rule, {
 // remove all exports
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `/* import * as m from '${testFilePath('./no-unused-modules/file-m.js')}' */`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-m.js'),
       errors: [
         error(`exported declaration 'm1' not used within other modules`),
         error(`exported declaration 'm' not used within other modules`),
         error(`exported declaration 'default' not used within other modules`),
-      ] }),
+      ],
+    }),
   ],
 });
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `export * from '${testFilePath('./no-unused-modules/file-m.js')}';`,
-      filename: testFilePath('./no-unused-modules/file-0.js') }),
+      filename: testFilePath('./no-unused-modules/file-0.js'),
+    }),
   ],
   invalid: [],
 });
 ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-m.js'),
-      errors: [error(`exported declaration 'default' not used within other modules`)] }),
+      errors: [error(`exported declaration 'default' not used within other modules`)],
+    }),
   ],
 });
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `export { m1, m} from '${testFilePath('./no-unused-modules/file-m.js')}';`,
       filename: testFilePath('./no-unused-modules/file-0.js'),
       errors: [
         error(`exported declaration 'm1' not used within other modules`),
         error(`exported declaration 'm' not used within other modules`),
-      ] }),
-    test({ options: unusedExportsOptions,
+      ],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-m.js'),
-      errors: [error(`exported declaration 'default' not used within other modules`)] }),
+      errors: [error(`exported declaration 'default' not used within other modules`)],
+    }),
   ],
 });
 
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    // test({ options: unusedExportsOptions,
-    //        code: `export { default, m1 } from '${testFilePath('./no-unused-modules/file-m.js')}';`,
-    //        filename: testFilePath('./no-unused-modules/file-0.js')}),
+    /* TODO:
+    test({
+      options: unusedExportsOptions,
+      code: `export { default, m1 } from '${testFilePath('./no-unused-modules/file-m.js')}';`,
+      filename: testFilePath('./no-unused-modules/file-0.js')
+    }),
+    */
   ],
   invalid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `export { default, m1 } from '${testFilePath('./no-unused-modules/file-m.js')}';`,
       filename: testFilePath('./no-unused-modules/file-0.js'),
       errors: [
         error(`exported declaration 'default' not used within other modules`),
         error(`exported declaration 'm1' not used within other modules`),
-      ] }),
-    test({ options: unusedExportsOptions,
+      ],
+    }),
+    test({
+      options: unusedExportsOptions,
       code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-m.js'),
-      errors: [error(`exported declaration 'm' not used within other modules`)] }),
+      errors: [error(`exported declaration 'm' not used within other modules`)],
+    }),
   ],
 });
 
 // Test that import and export in the same file both counts as usage
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `export const a = 5;export const b = 't1'`,
       filename: testFilePath('./no-unused-modules/import-export-1.js'),
     }),
@@ -478,23 +588,31 @@ ruleTester.run('no-unused-modules', rule, {
 describe('renameDefault', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: 'export { default as Component } from "./Component"',
-        filename: testFilePath('./no-unused-modules/renameDefault/components.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/renameDefault/components.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: 'export default function Component() {}',
-        filename: testFilePath('./no-unused-modules/renameDefault/Component.js') }),
+        filename: testFilePath('./no-unused-modules/renameDefault/Component.js'),
+      }),
     ],
     invalid: [],
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: 'export { default as ComponentA } from "./ComponentA";export { default as ComponentB } from "./ComponentB";',
-        filename: testFilePath('./no-unused-modules/renameDefault-2/components.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/renameDefault-2/components.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: 'export default function ComponentA() {};',
-        filename: testFilePath('./no-unused-modules/renameDefault-2/ComponentA.js') }),
+        filename: testFilePath('./no-unused-modules/renameDefault-2/ComponentA.js'),
+      }),
     ],
     invalid: [],
   });
@@ -508,12 +626,16 @@ describe('test behavior for new file', () => {
   // add import in newly created file
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `import * as m from '${testFilePath('./no-unused-modules/file-m.js')}'`,
-        filename: testFilePath('./no-unused-modules/file-added-0.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/file-added-0.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: 'const m0 = 5; const m = 10; export { m0 as m1, m }; export default () => {}',
-        filename: testFilePath('./no-unused-modules/file-m.js') }),
+        filename: testFilePath('./no-unused-modules/file-m.js'),
+      }),
     ],
     invalid: [],
   });
@@ -522,21 +644,27 @@ describe('test behavior for new file', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [],
     invalid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `export default () => {2}`,
         filename: testFilePath('./no-unused-modules/file-added-0.js'),
-        errors: [error(`exported declaration 'default' not used within other modules`)] }),
+        errors: [error(`exported declaration 'default' not used within other modules`)],
+      }),
     ],
   });
 
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `import def from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
-        filename: testFilePath('./no-unused-modules/file-0.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/file-0.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: `export default () => {}`,
-        filename: testFilePath('./no-unused-modules/file-added-0.js') }),
+        filename: testFilePath('./no-unused-modules/file-added-0.js'),
+      }),
     ],
     invalid: [],
   });
@@ -544,27 +672,34 @@ describe('test behavior for new file', () => {
   // export * only considers named imports. default imports still need to be reported
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `export * from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
-        filename: testFilePath('./no-unused-modules/file-0.js') }),
+        filename: testFilePath('./no-unused-modules/file-0.js'),
+      }),
       // Test export * from 'external-compiled-library'
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `export * from 'external-compiled-library'`,
         filename: testFilePath('./no-unused-modules/file-r.js'),
       }),
     ],
     invalid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `export const z = 'z';export default () => {}`,
         filename: testFilePath('./no-unused-modules/file-added-0.js'),
-        errors: [error(`exported declaration 'default' not used within other modules`)] }),
+        errors: [error(`exported declaration 'default' not used within other modules`)],
+      }),
     ],
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `export const a = 2`,
-        filename: testFilePath('./no-unused-modules/file-added-0.js') }),
+        filename: testFilePath('./no-unused-modules/file-added-0.js'),
+      }),
     ],
     invalid: [],
   });
@@ -573,17 +708,21 @@ describe('test behavior for new file', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [],
     invalid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `export { a } from '${testFilePath('./no-unused-modules/file-added-0.js')}'`,
         filename: testFilePath('./no-unused-modules/file-0.js'),
-        errors: [error(`exported declaration 'a' not used within other modules`)] }),
-      test({ options: unusedExportsOptions,
+        errors: [error(`exported declaration 'a' not used within other modules`)],
+      }),
+      test({
+        options: unusedExportsOptions,
         code: `export const z = 'z';export default () => {}`,
         filename: testFilePath('./no-unused-modules/file-added-0.js'),
         errors: [
           error(`exported declaration 'z' not used within other modules`),
           error(`exported declaration 'default' not used within other modules`),
-        ] }),
+        ],
+      }),
     ],
   });
 
@@ -594,15 +733,19 @@ describe('test behavior for new file', () => {
     });
     ruleTester.run('no-unused-modules', rule, {
       valid: [
-        test({ options: unusedExportsOptions,
+        test({
+          options: unusedExportsOptions,
           code: `export * from '${testFilePath('./no-unused-modules/file-added-1.js')}'`,
-          filename: testFilePath('./no-unused-modules/file-0.js') }),
+          filename: testFilePath('./no-unused-modules/file-0.js'),
+        }),
       ],
       invalid: [
-        test({ options: unusedExportsOptions,
+        test({
+          options: unusedExportsOptions,
           code: `export const z = 'z';export default () => {}`,
           filename: testFilePath('./no-unused-modules/file-added-1.js'),
-          errors: [error(`exported declaration 'default' not used within other modules`)] }),
+          errors: [error(`exported declaration 'default' not used within other modules`)],
+        }),
       ],
     });
     after(() => {
@@ -625,12 +768,16 @@ describe('test behavior for new file', () => {
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `import added from '${testFilePath('./no-unused-modules/file-added-2.js')}'`,
-        filename: testFilePath('./no-unused-modules/file-added-1.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/file-added-1.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: `export default () => {}`,
-        filename: testFilePath('./no-unused-modules/file-added-2.js') }),
+        filename: testFilePath('./no-unused-modules/file-added-2.js'),
+      }),
     ],
     invalid: [],
   });
@@ -647,12 +794,16 @@ describe('test behavior for new file', () => {
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `import { added } from '${testFilePath('./no-unused-modules/file-added-3.js')}'`,
-        filename: testFilePath('./no-unused-modules/file-added-1.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/file-added-1.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: `export const added = () => {}`,
-        filename: testFilePath('./no-unused-modules/file-added-3.js') }),
+        filename: testFilePath('./no-unused-modules/file-added-3.js'),
+      }),
     ],
     invalid: [],
   });
@@ -666,18 +817,24 @@ describe('test behavior for new file', () => {
 describe('test behavior for destructured exports', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `import { destructured } from '${testFilePath('./no-unused-modules/file-destructured-1.js')}'`,
-        filename: testFilePath('./no-unused-modules/file-destructured-2.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/file-destructured-2.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: `export const { destructured } = {};`,
-        filename: testFilePath('./no-unused-modules/file-destructured-1.js') }),
+        filename: testFilePath('./no-unused-modules/file-destructured-1.js'),
+      }),
     ],
     invalid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `export const { destructured2 } = {};`,
         filename: testFilePath('./no-unused-modules/file-destructured-1.js'),
-        errors: [`exported declaration 'destructured2' not used within other modules`] }),
+        errors: [`exported declaration 'destructured2' not used within other modules`],
+      }),
     ],
   });
 });
@@ -688,12 +845,16 @@ describe('test behavior for new file', () => {
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `import * as added from '${testFilePath('./no-unused-modules/file-added-4.js.js')}'`,
-        filename: testFilePath('./no-unused-modules/file-added-1.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/file-added-1.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: `export const added = () => {}; export default () => {}`,
-        filename: testFilePath('./no-unused-modules/file-added-4.js.js') }),
+        filename: testFilePath('./no-unused-modules/file-added-4.js.js'),
+      }),
     ],
     invalid: [],
   });
@@ -707,13 +868,15 @@ describe('test behavior for new file', () => {
 describe('do not report missing export for ignored file', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: [{
-        src: [testFilePath('./no-unused-modules/**/*.js')],
-        ignoreExports: [testFilePath('./no-unused-modules/*ignored*.js')],
-        missingExports: true,
-      }],
-      code: 'export const test = true',
-      filename: testFilePath('./no-unused-modules/file-ignored-a.js') }),
+      test({
+        options: [{
+          src: [testFilePath('./no-unused-modules/**/*.js')],
+          ignoreExports: [testFilePath('./no-unused-modules/*ignored*.js')],
+          missingExports: true,
+        }],
+        code: 'export const test = true',
+        filename: testFilePath('./no-unused-modules/file-ignored-a.js'),
+      }),
     ],
     invalid: [],
   });
@@ -722,9 +885,11 @@ describe('do not report missing export for ignored file', () => {
 // lint file not available in `src`
 ruleTester.run('no-unused-modules', rule, {
   valid: [
-    test({ options: unusedExportsOptions,
+    test({
+      options: unusedExportsOptions,
       code: `export const jsxFoo = 'foo'; export const jsxBar = 'bar'`,
-      filename: testFilePath('../jsx/named.jsx') }),
+      filename: testFilePath('../jsx/named.jsx'),
+    }),
   ],
   invalid: [],
 });
@@ -732,27 +897,39 @@ ruleTester.run('no-unused-modules', rule, {
 describe('do not report unused export for files mentioned in package.json', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: 'export const bin = "bin"',
-        filename: testFilePath('./no-unused-modules/bin.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/bin.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: 'export const binObject = "binObject"',
-        filename: testFilePath('./no-unused-modules/binObject/index.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/binObject/index.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: 'export const browser = "browser"',
-        filename: testFilePath('./no-unused-modules/browser.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/browser.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: 'export const browserObject = "browserObject"',
-        filename: testFilePath('./no-unused-modules/browserObject/index.js') }),
-      test({ options: unusedExportsOptions,
+        filename: testFilePath('./no-unused-modules/browserObject/index.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
         code: 'export const main = "main"',
-        filename: testFilePath('./no-unused-modules/main/index.js') }),
+        filename: testFilePath('./no-unused-modules/main/index.js'),
+      }),
     ],
     invalid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: 'export const privatePkg = "privatePkg"',
         filename: testFilePath('./no-unused-modules/privatePkg/index.js'),
-        errors: [error(`exported declaration 'privatePkg' not used within other modules`)] }),
+        errors: [error(`exported declaration 'privatePkg' not used within other modules`)],
+      }),
     ],
   });
 });
@@ -760,9 +937,11 @@ describe('do not report unused export for files mentioned in package.json', () =
 describe('Avoid errors if re-export all from umd compiled library', () => {
   ruleTester.run('no-unused-modules', rule, {
     valid: [
-      test({ options: unusedExportsOptions,
+      test({
+        options: unusedExportsOptions,
         code: `export * from '${testFilePath('./no-unused-modules/bin.js')}'`,
-        filename: testFilePath('./no-unused-modules/main/index.js') }),
+        filename: testFilePath('./no-unused-modules/main/index.js'),
+      }),
     ],
     invalid: [],
   });

From fa3192a409d328a8208ddbdf4f2c1d0a714e02c6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 14 Aug 2021 15:22:22 -0700
Subject: [PATCH 338/767] [resolvers/node] [fix] when "module" does not exist,
 fall back to "main"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fixes #2186. This is actually exposing a bug with packages that are broken - that ship an invalid "module" field - but it‘s a more friendly and node-accurate behavior to still work when "main" works.
---
 resolvers/node/index.js                       | 33 ++++++++++++++-----
 .../test/package-mains/module-broken/main.js  |  1 +
 .../package-mains/module-broken/package.json  |  4 +++
 resolvers/node/test/packageMains.js           | 13 +++++---
 .../test/package-mains/module-broken/main.js  |  1 +
 .../package-mains/module-broken/package.json  |  4 +++
 resolvers/webpack/test/packageMains.js        | 24 ++++++++------
 7 files changed, 58 insertions(+), 22 deletions(-)
 create mode 100644 resolvers/node/test/package-mains/module-broken/main.js
 create mode 100644 resolvers/node/test/package-mains/module-broken/package.json
 create mode 100644 resolvers/webpack/test/package-mains/module-broken/main.js
 create mode 100644 resolvers/webpack/test/package-mains/module-broken/package.json

diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index 84fc5076b6..899e552e96 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -17,7 +17,8 @@ exports.resolve = function (source, file, config) {
   }
 
   try {
-    resolvedPath = resolve.sync(source, opts(file, config));
+    const cachedFilter = function (pkg, dir) { return packageFilter(pkg, dir, config); };
+    resolvedPath = resolve.sync(source, opts(file, config, cachedFilter));
     log('Resolved to:', resolvedPath);
     return { found: true, path: resolvedPath };
   } catch (err) {
@@ -26,7 +27,7 @@ exports.resolve = function (source, file, config) {
   }
 };
 
-function opts(file, config) {
+function opts(file, config, packageFilter) {
   return Object.assign({
     // more closely matches Node (#333)
     // plus 'mjs' for native modules! (#939)
@@ -36,16 +37,32 @@ function opts(file, config) {
   {
     // path.resolve will handle paths relative to CWD
     basedir: path.dirname(path.resolve(file)),
-    packageFilter: packageFilter,
-
+    packageFilter,
   });
 }
 
-function packageFilter(pkg) {
+function identity(x) { return x; }
+
+function packageFilter(pkg, dir, config) {
+  let found = false;
+  const file = path.join(dir, 'dummy.js');
   if (pkg.module) {
-    pkg.main = pkg.module;
-  } else if (pkg['jsnext:main']) {
-    pkg.main = pkg['jsnext:main'];
+    try {
+      resolve.sync(String(pkg.module).replace(/^(?:\.\/)?/, './'), opts(file, config, identity));
+      pkg.main = pkg.module;
+      found = true;
+    } catch (err) {
+      log('resolve threw error trying to find pkg.module:', err);
+    }
+  }
+  if (!found && pkg['jsnext:main']) {
+    try {
+      resolve.sync(String(pkg['jsnext:main']).replace(/^(?:\.\/)?/, './'), opts(file, config, identity));
+      pkg.main = pkg['jsnext:main'];
+      found = true;
+    } catch (err) {
+      log('resolve threw error trying to find pkg[\'jsnext:main\']:', err);
+    }
   }
   return pkg;
 }
diff --git a/resolvers/node/test/package-mains/module-broken/main.js b/resolvers/node/test/package-mains/module-broken/main.js
new file mode 100644
index 0000000000..f053ebf797
--- /dev/null
+++ b/resolvers/node/test/package-mains/module-broken/main.js
@@ -0,0 +1 @@
+module.exports = {};
diff --git a/resolvers/node/test/package-mains/module-broken/package.json b/resolvers/node/test/package-mains/module-broken/package.json
new file mode 100644
index 0000000000..36a3183866
--- /dev/null
+++ b/resolvers/node/test/package-mains/module-broken/package.json
@@ -0,0 +1,4 @@
+{
+  "main": "./main.js",
+  "module": "./doesNotExist.js"
+}
diff --git a/resolvers/node/test/packageMains.js b/resolvers/node/test/packageMains.js
index 0a7d9463c7..caac6221ca 100644
--- a/resolvers/node/test/packageMains.js
+++ b/resolvers/node/test/packageMains.js
@@ -4,24 +4,29 @@ const chai = require('chai');
 const expect = chai.expect;
 const path = require('path');
 
-const webpack = require('../');
+const resolver = require('../');
 
 const file = path.join(__dirname, 'package-mains', 'dummy.js');
 
 
 describe('packageMains', function () {
   it('captures module', function () {
-    expect(webpack.resolve('./module', file)).property('path')
+    expect(resolver.resolve('./module', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'));
   });
 
   it('captures jsnext', function () {
-    expect(webpack.resolve('./jsnext', file)).property('path')
+    expect(resolver.resolve('./jsnext', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
   });
 
   it('captures module instead of jsnext', function () {
-    expect(webpack.resolve('./module-and-jsnext', file)).property('path')
+    expect(resolver.resolve('./module-and-jsnext', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'module-and-jsnext', 'src', 'index.js'));
   });
+
+  it('falls back from a missing "module" to "main"', function () {
+    expect(resolver.resolve('./module-broken', file)).property('path')
+      .to.equal(path.join(__dirname, 'package-mains', 'module-broken', 'main.js'));
+  });
 });
diff --git a/resolvers/webpack/test/package-mains/module-broken/main.js b/resolvers/webpack/test/package-mains/module-broken/main.js
new file mode 100644
index 0000000000..f053ebf797
--- /dev/null
+++ b/resolvers/webpack/test/package-mains/module-broken/main.js
@@ -0,0 +1 @@
+module.exports = {};
diff --git a/resolvers/webpack/test/package-mains/module-broken/package.json b/resolvers/webpack/test/package-mains/module-broken/package.json
new file mode 100644
index 0000000000..36a3183866
--- /dev/null
+++ b/resolvers/webpack/test/package-mains/module-broken/package.json
@@ -0,0 +1,4 @@
+{
+  "main": "./main.js",
+  "module": "./doesNotExist.js"
+}
diff --git a/resolvers/webpack/test/packageMains.js b/resolvers/webpack/test/packageMains.js
index 96becbc8ce..fef3dde073 100644
--- a/resolvers/webpack/test/packageMains.js
+++ b/resolvers/webpack/test/packageMains.js
@@ -4,7 +4,7 @@ const chai = require('chai');
 const expect = chai.expect;
 const path = require('path');
 
-const webpack = require('../');
+const resolver = require('../');
 
 const file = path.join(__dirname, 'package-mains', 'dummy.js');
 
@@ -12,43 +12,47 @@ const file = path.join(__dirname, 'package-mains', 'dummy.js');
 describe('packageMains', function () {
 
   it('captures module', function () {
-    expect(webpack.resolve('./module', file)).property('path')
+    expect(resolver.resolve('./module', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'));
   });
 
   it('captures jsnext', function () {
-    expect(webpack.resolve('./jsnext', file)).property('path')
+    expect(resolver.resolve('./jsnext', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
   });
 
   it('captures module instead of jsnext', function () {
-    expect(webpack.resolve('./module-and-jsnext', file)).property('path')
+    expect(resolver.resolve('./module-and-jsnext', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'module-and-jsnext', 'src', 'index.js'));
   });
 
+  it('falls back from a missing "module" to "main"', function () {
+    expect(resolver.resolve('./module-broken', file)).property('path')
+      .to.equal(path.join(__dirname, 'package-mains', 'module-broken', 'main.js'));
+  });
+
   it('captures webpack', function () {
-    expect(webpack.resolve('./webpack', file)).property('path')
+    expect(resolver.resolve('./webpack', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'webpack.js'));
   });
 
   it('captures jam (array path)', function () {
-    expect(webpack.resolve('./jam', file)).property('path')
+    expect(resolver.resolve('./jam', file)).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'jam', 'jam.js'));
   });
 
   it('uses configured packageMains, if provided', function () {
-    expect(webpack.resolve('./webpack', file, { config: 'webpack.alt.config.js' })).property('path')
+    expect(resolver.resolve('./webpack', file, { config: 'webpack.alt.config.js' })).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'webpack', 'index.js'));
   });
 
   it('always defers to module, regardless of config', function () {
-    expect(webpack.resolve('./module', file, { config: 'webpack.alt.config.js' })).property('path')
+    expect(resolver.resolve('./module', file, { config: 'webpack.alt.config.js' })).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'module', 'src', 'index.js'));
   });
 
   it('always defers to jsnext:main, regardless of config', function () {
-    expect(webpack.resolve('./jsnext', file, { config: 'webpack.alt.config.js' })).property('path')
+    expect(resolver.resolve('./jsnext', file, { config: 'webpack.alt.config.js' })).property('path')
       .to.equal(path.join(__dirname, 'package-mains', 'jsnext', 'src', 'index.js'));
   });
-
 });

From f0c1756ed2821c5ef4eae5ef90490cb4b78ab9b2 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 14 Aug 2021 16:33:20 -0700
Subject: [PATCH 339/767] [meta] fix some formatting

---
 CHANGELOG.md                                |  2 +-
 docs/rules/no-unresolved.md                 |  2 +-
 resolvers/webpack/index.js                  | 21 +++++++-------
 src/rules/dynamic-import-chunkname.js       |  2 +-
 src/rules/first.js                          |  2 +-
 src/rules/no-unresolved.js                  | 31 +++++++++++----------
 src/rules/no-unused-modules.js              |  2 +-
 src/rules/order.js                          |  6 ++--
 src/rules/prefer-default-export.js          |  3 +-
 tests/files/foo-bar-resolver-no-version.js  |  6 ++--
 tests/files/foo-bar-resolver-v1.js          | 14 ++++------
 tests/files/foo-bar-resolver-v2.js          | 10 +++----
 tests/files/typescript.ts                   |  6 ++--
 tests/src/rules/newline-after-import.js     |  2 +-
 tests/src/rules/no-cycle.js                 |  2 +-
 tests/src/rules/no-unresolved.js            |  4 +--
 tests/src/rules/no-useless-path-segments.js |  2 +-
 utils/moduleVisitor.js                      |  2 +-
 18 files changed, 55 insertions(+), 64 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa4d0f533e..349167e836 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,7 +20,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
 - [`extensions`]: avoid crashing on partially typed import/export statements ([#2118], thanks [@ljharb])
-- [`no-extraneous-dependencies`]: add ESM intermediate package.json support] ([#2121], thanks [@paztis])
+- [`no-extraneous-dependencies`]: add ESM intermediate package.json support ([#2121], thanks [@paztis])
 - Use `context.getPhysicalFilename()` when available (ESLint 7.28+) ([#2160], thanks [@pmcelhaney])
 - [`extensions`]/`importType`: fix isScoped treating @/abc as scoped module ([#2146], thanks [@rperello])
 
diff --git a/docs/rules/no-unresolved.md b/docs/rules/no-unresolved.md
index 30cd8cb2b8..ae6177dfd9 100644
--- a/docs/rules/no-unresolved.md
+++ b/docs/rules/no-unresolved.md
@@ -6,7 +6,7 @@ as defined by standard Node `require.resolve` behavior.
 See [settings](../../README.md#settings) for customization options for the resolution (i.e.
 additional filetypes, `NODE_PATH`, etc.)
 
-This rule can also optionally report on unresolved modules in CommonJS `require('./foo')` calls and AMD `require(['./foo'], function (foo){...})` and `define(['./foo'], function (foo){...})`.
+This rule can also optionally report on unresolved modules in CommonJS `require('./foo')` calls and AMD `require(['./foo'], function (foo) {...})` and `define(['./foo'], function (foo) {...})`.
 
 To enable this, send `{ commonjs: true/false, amd: true/false }` as a rule option.
 Both are disabled by default.
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 50832f8f31..c7a3fbcae0 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -118,8 +118,7 @@ exports.resolve = function (source, file, settings) {
 
     if (typeof configIndex !== 'undefined' && webpackConfig.length > configIndex) {
       webpackConfig = webpackConfig[configIndex];
-    }
-    else {
+    } else {
       webpackConfig = find(webpackConfig, function findFirstWithResolve(config) {
         return !!config.resolve;
       });
@@ -311,16 +310,16 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
 /* eslint-disable */
 // from https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L365
 function makeRootPlugin(ModulesInRootPlugin, name, root) {
-  if(typeof root === "string")
+  if (typeof root === 'string') {
     return new ModulesInRootPlugin(name, root);
-  else if(Array.isArray(root)) {
+  } else if (Array.isArray(root)) {
     return function() {
-      root.forEach(function(root) {
+      root.forEach(function (root) {
         this.apply(new ModulesInRootPlugin(name, root));
       }, this);
     };
   }
-  return function() {};
+  return function () {};
 }
 /* eslint-enable */
 
@@ -436,17 +435,17 @@ function findConfigPath(configPath, packageDir) {
 }
 
 function registerCompiler(moduleDescriptor) {
-  if(moduleDescriptor) {
-    if(typeof moduleDescriptor === 'string') {
+  if (moduleDescriptor) {
+    if (typeof moduleDescriptor === 'string') {
       require(moduleDescriptor);
-    } else if(!Array.isArray(moduleDescriptor)) {
+    } else if (!Array.isArray(moduleDescriptor)) {
       moduleDescriptor.register(require(moduleDescriptor.module));
     } else {
-      for(let i = 0; i < moduleDescriptor.length; i++) {
+      for (let i = 0; i < moduleDescriptor.length; i++) {
         try {
           registerCompiler(moduleDescriptor[i]);
           break;
-        } catch(e) {
+        } catch (e) {
           log('Failed to register compiler for moduleDescriptor[]:', i, moduleDescriptor);
         }
       }
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 7a21ec62d9..16cd85a4f8 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -69,7 +69,7 @@ module.exports = {
 
         try {
           // just like webpack itself does
-          vm.runInNewContext(`(function(){return {${comment.value}}})()`);
+          vm.runInNewContext(`(function() {return {${comment.value}}})()`);
         }
         catch (error) {
           context.report({
diff --git a/src/rules/first.js b/src/rules/first.js
index a3b7f24e03..93e9fc5536 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -42,7 +42,7 @@ module.exports = {
         const errorInfos = [];
         let shouldSort = true;
         let lastSortNodesIndex = 0;
-        body.forEach(function (node, index){
+        body.forEach(function (node, index) {
           if (!anyExpressions && isPossibleDirective(node)) {
             return;
           }
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index 61dc0b6c70..719bbded9d 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -15,35 +15,36 @@ module.exports = {
       url: docsUrl('no-unresolved'),
     },
 
-    schema: [ makeOptionsSchema({
-      caseSensitive: { type: 'boolean', default: true },
-    })],
+    schema: [
+      makeOptionsSchema({
+        caseSensitive: { type: 'boolean', default: true },
+      }),
+    ],
   },
 
   create: function (context) {
-
     function checkSourceValue(source) {
-      const shouldCheckCase = !CASE_SENSITIVE_FS &&
-        (!context.options[0] || context.options[0].caseSensitive !== false);
+      const shouldCheckCase = !CASE_SENSITIVE_FS
+        && (!context.options[0] || context.options[0].caseSensitive !== false);
 
       const resolvedPath = resolve(source.value, context);
 
       if (resolvedPath === undefined) {
-        context.report(source,
-          `Unable to resolve path to module '${source.value}'.`);
-      }
-
-      else if (shouldCheckCase) {
+        context.report(
+          source,
+          `Unable to resolve path to module '${source.value}'.`
+        );
+      } else if (shouldCheckCase) {
         const cacheSettings = ModuleCache.getSettings(context.settings);
         if (!fileExistsWithCaseSync(resolvedPath, cacheSettings)) {
-          context.report(source,
-            `Casing of ${source.value} does not match the underlying filesystem.`);
+          context.report(
+            source,
+            `Casing of ${source.value} does not match the underlying filesystem.`
+          );
         }
-
       }
     }
 
     return moduleVisitor(checkSourceValue, context.options[0]);
-
   },
 };
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 205259eef9..d49674e7e5 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -540,7 +540,7 @@ module.exports = {
 
       const value = exportsKey === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportsKey;
 
-      if (typeof exportStatement !== 'undefined'){
+      if (typeof exportStatement !== 'undefined') {
         if (exportStatement.whereUsed.size < 1) {
           context.report(
             node,
diff --git a/src/rules/order.js b/src/rules/order.js
index ce34604c64..857a46e3d0 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -47,8 +47,7 @@ function takeTokensAfterWhile(sourceCode, node, condition) {
   for (let i = 0; i < tokens.length; i++) {
     if (condition(tokens[i])) {
       result.push(tokens[i]);
-    }
-    else {
+    } else {
       break;
     }
   }
@@ -61,8 +60,7 @@ function takeTokensBeforeWhile(sourceCode, node, condition) {
   for (let i = tokens.length - 1; i >= 0; i--) {
     if (condition(tokens[i])) {
       result.push(tokens[i]);
-    }
-    else {
+    } else {
       break;
     }
   }
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 5e77126dc0..3cd2224cdf 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -69,8 +69,7 @@ module.exports = {
           node.declaration.declarations.forEach(function(declaration) {
             captureDeclaration(declaration.id);
           });
-        }
-        else {
+        } else {
           // captures 'export function foo() {}' syntax
           specifierExportCount++;
         }
diff --git a/tests/files/foo-bar-resolver-no-version.js b/tests/files/foo-bar-resolver-no-version.js
index 89d4eb13e2..f00198562e 100644
--- a/tests/files/foo-bar-resolver-no-version.js
+++ b/tests/files/foo-bar-resolver-no-version.js
@@ -5,10 +5,8 @@ exports.resolveImport = function (modulePath, sourceFile, config) {
   if (sourceFileName === 'foo.js') {
     return path.join(__dirname, 'bar.jsx')
   }
-  else if (sourceFileName === 'exception.js') {
+  if (sourceFileName === 'exception.js') {
     throw new Error('foo-bar-resolver-v1 resolveImport test exception')
   }
-  else {
-    return undefined
-  }
+  return undefined;
 }
diff --git a/tests/files/foo-bar-resolver-v1.js b/tests/files/foo-bar-resolver-v1.js
index 8aafe7aa45..af9da1b7a6 100644
--- a/tests/files/foo-bar-resolver-v1.js
+++ b/tests/files/foo-bar-resolver-v1.js
@@ -3,14 +3,12 @@ var path = require('path')
 exports.resolveImport = function (modulePath, sourceFile, config) {
   var sourceFileName = path.basename(sourceFile)
   if (sourceFileName === 'foo.js') {
-    return path.join(__dirname, 'bar.jsx')
+    return path.join(__dirname, 'bar.jsx');
   }
-  else if (sourceFileName === 'exception.js') {
-    throw new Error('foo-bar-resolver-v1 resolveImport test exception')
+  if (sourceFileName === 'exception.js') {
+    throw new Error('foo-bar-resolver-v1 resolveImport test exception');
   }
-  else {
-    return undefined
-  }
-}
+  return undefined;
+};
 
-exports.interfaceVersion = 1
+exports.interfaceVersion = 1;
diff --git a/tests/files/foo-bar-resolver-v2.js b/tests/files/foo-bar-resolver-v2.js
index 9bb68171b7..7f8bcc0f86 100644
--- a/tests/files/foo-bar-resolver-v2.js
+++ b/tests/files/foo-bar-resolver-v2.js
@@ -5,12 +5,10 @@ exports.resolve = function (modulePath, sourceFile, config) {
   if (sourceFileName === 'foo.js') {
     return { found: true, path: path.join(__dirname, 'bar.jsx') }
   }
-  else if (sourceFileName === 'exception.js') {
+  if (sourceFileName === 'exception.js') {
     throw new Error('foo-bar-resolver-v2 resolve test exception')
   }
-  else {
-    return { found: false }
-  }
-}
+  return { found: false };
+};
 
-exports.interfaceVersion = 2
+exports.interfaceVersion = 2;
diff --git a/tests/files/typescript.ts b/tests/files/typescript.ts
index 7f90314e45..f8fe2e8e07 100644
--- a/tests/files/typescript.ts
+++ b/tests/files/typescript.ts
@@ -23,14 +23,14 @@ export function getFoo() : MyType {
 }
 
 export module MyModule {
-  export function ModuleFunction(){}
+  export function ModuleFunction() {}
 }
 
 export namespace MyNamespace {
-  export function NamespaceFunction(){}
+  export function NamespaceFunction() {}
 
   export module NSModule {
-    export function NSModuleFunction(){}
+    export function NSModuleFunction() {}
   }
 }
 
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 867a648575..39f4c42914 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -26,7 +26,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       code: `const x = () => require('baz') && require('bar')`,
       parserOptions: { ecmaVersion: 6 } ,
     },
-    `function x(){ require('baz'); }`,
+    `function x() { require('baz'); }`,
     `a(require('b'), require('c'), require('d'));`,
     `function foo() {
       switch (renderData.modalViewKey) {
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 11fc515f0b..c4e3235e78 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -61,7 +61,7 @@ ruleTester.run('no-cycle', rule, {
         options: [{ maxDepth: 1 }],
       }),
       test({
-        code: `import("./${testDialect}/depth-two").then(function({ foo }){})`,
+        code: `import("./${testDialect}/depth-two").then(function({ foo }) {})`,
         options: [{ maxDepth: 1 }],
         parser: require.resolve('babel-eslint'),
       }),
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index a8694ddf26..d21ee2fd8c 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -122,7 +122,7 @@ function runResolverTests(resolver) {
         type: 'Literal',
         }] }),
       rest({
-        code: "import('in-alternate-root').then(function({DEEP}){});",
+        code: "import('in-alternate-root').then(function({DEEP}) {});",
         errors: [{
           message: 'Unable to resolve path to module \'in-alternate-root\'.',
           type: 'Literal',
@@ -138,7 +138,7 @@ function runResolverTests(resolver) {
 
       // check with eslint parser
       testVersion('>= 7', () => rest({
-        code: "import('in-alternate-root').then(function({DEEP}){});",
+        code: "import('in-alternate-root').then(function({DEEP}) {});",
         errors: [{
           message: 'Unable to resolve path to module \'in-alternate-root\'.',
           type: 'Literal',
diff --git a/tests/src/rules/no-useless-path-segments.js b/tests/src/rules/no-useless-path-segments.js
index 313424d349..21d9a5f704 100644
--- a/tests/src/rules/no-useless-path-segments.js
+++ b/tests/src/rules/no-useless-path-segments.js
@@ -32,7 +32,7 @@ function runResolverTests(resolver) {
         parser: require.resolve('babel-eslint') }),
       test({ code: 'import("..")',
         parser: require.resolve('babel-eslint') }),
-      test({ code: 'import("fs").then(function(fs){})',
+      test({ code: 'import("fs").then(function(fs) {})',
         parser: require.resolve('babel-eslint') }),
     ],
 
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index 69269985bd..7f783624b4 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -131,7 +131,7 @@ function makeOptionsSchema(additionalProperties) {
     'additionalProperties': false,
   };
 
-  if (additionalProperties){
+  if (additionalProperties) {
     for (const key in additionalProperties) {
       base.properties[key] = additionalProperties[key];
     }

From 750ba250552bb93433401fb4d20780df75fc2b35 Mon Sep 17 00:00:00 2001
From: Wenfang Du <no_reply_mail@163.com>
Date: Mon, 9 Aug 2021 21:19:28 +0800
Subject: [PATCH 340/767] [Docs] `extensions`: improved cases for using `@/...`

---
 CHANGELOG.md             | 2 ++
 docs/rules/extensions.md | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 349167e836..e569fe33f7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extensions`]/`importType`: fix isScoped treating @/abc as scoped module ([#2146], thanks [@rperello])
 
 ### Changed
+- [Docs] [`extensions`]: improved cases for using `@/...` ([#2140], thanks [@wenfangdu])
 - [Docs] [`extensions`]: removed incorrect cases ([#2138], thanks [@wenfangdu])
 - [Tests] [`order`]: add tests for `pathGroupsExcludedImportTypes: ['type']` ([#2158], thanks [@atav32])
 - [Docs] [`order`]:  improve the documentation for the `pathGroupsExcludedImportTypes` option ([#2156], thanks [@liby])
@@ -892,6 +893,7 @@ for info on changes for earlier releases.
 [#2158]: https://github.com/import-js/eslint-plugin-import/pull/2158
 [#2156]: https://github.com/import-js/eslint-plugin-import/pull/2156
 [#2146]: https://github.com/import-js/eslint-plugin-import/pull/2146
+[#2140]: https://github.com/import-js/eslint-plugin-import/pull/2140
 [#2138]: https://github.com/import-js/eslint-plugin-import/pull/2138
 [#2121]: https://github.com/import-js/eslint-plugin-import/pull/2121
 [#2112]: https://github.com/import-js/eslint-plugin-import/pull/2112
diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md
index bf29dbe5fb..575895c5a0 100644
--- a/docs/rules/extensions.md
+++ b/docs/rules/extensions.md
@@ -109,6 +109,8 @@ import foo from './foo';
 import bar from './bar';
 
 import Component from './Component';
+
+import foo from '@/foo';
 ```
 
 The following patterns are not considered problems when configuration set to "always":
@@ -121,6 +123,8 @@ import bar from './bar.json';
 import Component from './Component.jsx';
 
 import * as path from 'path';
+
+import foo from '@/foo.js';
 ```
 
 The following patterns are considered problems when configuration set to "ignorePackages":
@@ -145,6 +149,7 @@ import Component from './Component.jsx';
 
 import express from 'express';
 
+import foo from '@/foo'
 ```
 
 The following patterns are not considered problems when configuration set to `['error', 'always', {ignorePackages: true} ]`:
@@ -156,6 +161,7 @@ import baz from 'foo/baz.js';
 
 import express from 'express';
 
+import foo from '@/foo';
 ```
 
 ## When Not To Use It

From 8be2ec2e526aa457075d79e96c5993e96764f734 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 15 Aug 2021 09:52:49 -0700
Subject: [PATCH 341/767] [resolvers/node] v0.3.6

---
 resolvers/node/CHANGELOG.md | 10 +++++++---
 resolvers/node/package.json |  2 +-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index 2fbf07ab21..c237855a2e 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -5,6 +5,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v0.3.6 - 2021-08-15
+### Fixed
+- when "module" does not exist, fall back to "main" ([#2186], thanks [@ljharb])
+
 ## v0.3.5 - 2021-08-08
 ### Added
 - use "module" in the same spot as "jsnext:main" ([#2166], thanks [@MustafaHaddara])
@@ -52,13 +56,13 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - find files with `.json` extensions (#333, thanks for noticing @jfmengels)
 
+[#2186]: https://github.com/import-js/eslint-plugin-import/issues/2186
 [#2166]: https://github.com/import-js/eslint-plugin-import/pull/2166
-[#438]: https://github.com/import-js/eslint-plugin-import/pull/438
-
 [#1663]: https://github.com/import-js/eslint-plugin-import/issues/1663
 [#1595]: https://github.com/import-js/eslint-plugin-import/pull/1595
 [#939]: https://github.com/import-js/eslint-plugin-import/issues/939
 [#531]: https://github.com/import-js/eslint-plugin-import/issues/531
+[#438]: https://github.com/import-js/eslint-plugin-import/pull/438
 [#437]: https://github.com/import-js/eslint-plugin-import/issues/437
 
 [@jasonkarns]: https://github.com/jasonkarns
@@ -66,4 +70,4 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@SkeLLLa]: https://github.com/SkeLLLa
 [@ljharb]: https://github.com/ljharb
 [@opichals]: https://github.com/opichals
-[@MustafaHaddara]: https://github.com/MustafaHaddara
\ No newline at end of file
+[@MustafaHaddara]: https://github.com/MustafaHaddara
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 993f1b89b6..5e7e9dea75 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-node",
-  "version": "0.3.5",
+  "version": "0.3.6",
   "description": "Node default behavior import resolution plugin for eslint-plugin-import.",
   "main": "index.js",
   "files": [

From 7610790b0c989e4fceb63be2d75db35e4962dbb5 Mon Sep 17 00:00:00 2001
From: himynameisdave <dave@fossa.com>
Date: Mon, 16 Aug 2021 10:09:55 -0700
Subject: [PATCH 342/767] =?UTF-8?q?[Docs]=20`max-dependencies`:=20?=
 =?UTF-8?q?=F0=9F=93=96=20Document=20`ignoreTypeImports`=20option?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

See #1847.
---
 CHANGELOG.md                   |  5 +++++
 docs/rules/max-dependencies.md | 38 +++++++++++++++++++++++++++-------
 2 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e569fe33f7..93ca6b6377 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok])
 
+### Changed
+- [Docs] `max-dependencies`: 📖 Document `ignoreTypeImports` option ([#2196], thanks [@himynameisdave])
+
 ## [2.24.0] - 2021-08-08
 
 ### Added
@@ -887,6 +890,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2196]: https://github.com/import-js/eslint-plugin-import/pull/2196
 [#2184]: https://github.com/import-js/eslint-plugin-import/pull/2184
 [#2179]: https://github.com/import-js/eslint-plugin-import/pull/2179
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
@@ -1401,6 +1405,7 @@ for info on changes for earlier releases.
 [@grit96]: https://github.com/grit96
 [@guillaumewuip]: https://github.com/guillaumewuip
 [@hayes]: https://github.com/hayes
+[@himynameisdave]: https://github.com/himynameisdave
 [@hulkish]: https://github.com/hulkish
 [@Hypnosphi]: https://github.com/Hypnosphi
 [@isiahmeadows]: https://github.com/isiahmeadows
diff --git a/docs/rules/max-dependencies.md b/docs/rules/max-dependencies.md
index 20d29cf0e9..3bead8273d 100644
--- a/docs/rules/max-dependencies.md
+++ b/docs/rules/max-dependencies.md
@@ -6,20 +6,20 @@ This is a useful rule because a module with too many dependencies is a code smel
 
 Importing multiple named exports from a single module will only count once (e.g. `import {x, y, z} from './foo'` will only count as a single dependency).
 
-### Options
+## Options
 
-This rule takes the following option:
-
-`max`: The maximum number of dependencies allowed. Anything over will trigger the rule. **Default is 10** if the rule is enabled and no `max` is specified.
-
-You can set the option like this:
+This rule has the following options, with these defaults:
 
 ```js
-"import/max-dependencies": ["error", {"max": 10}]
+"import/max-dependencies": ["error", {
+  "max": 10,
+  "ignoreTypeImports": false,
+}]
 ```
 
+### `max`
 
-## Example
+This option sets the maximum number of dependencies allowed. Anything over will trigger the rule. **Default is 10** if the rule is enabled and no `max` is specified.
 
 Given a max value of `{"max": 2}`:
 
@@ -39,6 +39,28 @@ const anotherA = require('./a'); // still 1
 import {x, y, z} from './foo'; // 2
 ```
 
+### `ignoreTypeImports`
+
+Ignores `type` imports. Type imports are a feature released in TypeScript 3.8, you can [read more here](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export). Defaults to `false`.
+
+Given `{"max": 2, "ignoreTypeImports": true}`:
+
+### Fail
+
+```ts
+import a from './a';
+import b from './b';
+import c from './c';
+```
+
+### Pass
+
+```ts
+import a from './a';
+import b from './b';
+import type c from './c'; // Doesn't count against max
+```
+
 ## When Not To Use It
 
 If you don't care how many dependencies a module has.

From ce8b203d7907f8744b050a84797e3456011360b6 Mon Sep 17 00:00:00 2001
From: yosuke ota <otameshiyo23@gmail.com>
Date: Mon, 16 Aug 2021 18:53:52 +0900
Subject: [PATCH 343/767] [Fix] `no-amd`, `no-commonjs`: fix test cases

---
 tests/src/rules/no-amd.js      | 2 +-
 tests/src/rules/no-commonjs.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/src/rules/no-amd.js b/tests/src/rules/no-amd.js
index 74c89c4116..91e29234c8 100644
--- a/tests/src/rules/no-amd.js
+++ b/tests/src/rules/no-amd.js
@@ -2,7 +2,7 @@ import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
-const ruleTester = new RuleTester();
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015, sourceType: 'module' } });
 
 ruleTester.run('no-amd', require('rules/no-amd'), {
   valid: [
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index b1d8c03c1d..a2e3464ca7 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -5,7 +5,7 @@ import semver from 'semver';
 const EXPORT_MESSAGE = 'Expected "export" or "export default"';
 const IMPORT_MESSAGE = 'Expected "import" instead of "require()"';
 
-const ruleTester = new RuleTester();
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015, sourceType: 'module' } });
 
 ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
   valid: [

From b2bf591749b7a2031f402b143f6c767db4f59bd5 Mon Sep 17 00:00:00 2001
From: yosuke ota <otameshiyo23@gmail.com>
Date: Tue, 17 Aug 2021 16:55:27 +0900
Subject: [PATCH 344/767] [Tests] `cli`: test the current plugin, not an
 installed one

---
 tests/src/cli.js | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tests/src/cli.js b/tests/src/cli.js
index 91d3dfc158..b0285593b1 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -7,6 +7,7 @@ import { expect } from 'chai';
 import { CLIEngine } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
+import * as importPlugin from '../../src/index';
 
 describe('CLI regression tests', function () {
   describe('issue #210', function () {
@@ -20,6 +21,7 @@ describe('CLI regression tests', function () {
           'named': 2,
         },
       });
+      cli.addPlugin('eslint-plugin-import', importPlugin);
     });
     it("doesn't throw an error on gratuitous, erroneous self-reference", function () {
       expect(() => cli.executeOnFiles(['./tests/files/issue210.js'])).not.to.throw();
@@ -38,6 +40,7 @@ describe('CLI regression tests', function () {
           rulePaths: ['./src/rules'],
           ignore: false,
         });
+        cli.addPlugin('eslint-plugin-import', importPlugin);
       }
     });
 

From 3ff4d772331219a55e4c65925950bda0c6301e5f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 17 Aug 2021 21:44:33 -0700
Subject: [PATCH 345/767] =?UTF-8?q?[Fix]=20`named`,=20`namespace`:=20prope?=
 =?UTF-8?q?rly=20set=20reexports=20on=20`export=20*=20as=20=E2=80=A6=20fro?=
 =?UTF-8?q?m`?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fixes #1998. Fixes #2161.
---
 CHANGELOG.md                          |  3 ++
 src/ExportMap.js                      | 66 +++++++++++++++------------
 src/rules/namespace.js                | 12 ++---
 tests/files/export-star-2/middle.js   |  1 +
 tests/files/export-star-2/upstream.js |  1 +
 tests/files/export-star/extfield.js   |  1 +
 tests/files/export-star/extfield2.js  |  1 +
 tests/files/export-star/models.js     |  2 +
 tests/src/rules/named.js              | 12 ++++-
 tests/src/rules/namespace.js          | 14 +++++-
 10 files changed, 75 insertions(+), 38 deletions(-)
 create mode 100644 tests/files/export-star-2/middle.js
 create mode 100644 tests/files/export-star-2/upstream.js
 create mode 100644 tests/files/export-star/extfield.js
 create mode 100644 tests/files/export-star/extfield2.js
 create mode 100644 tests/files/export-star/models.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 93ca6b6377..e59d246266 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok])
+- [`named`], [`namespace`]: properly set reexports on `export * as … from` ([#1998], [#2161], thanks [@ljharb])
 
 ### Changed
 - [Docs] `max-dependencies`: 📖 Document `ignoreTypeImports` option ([#2196], thanks [@himynameisdave])
@@ -1145,10 +1146,12 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2161]: https://github.com/import-js/eslint-plugin-import/issues/2161
 [#2118]: https://github.com/import-js/eslint-plugin-import/issues/2118
 [#2067]: https://github.com/import-js/eslint-plugin-import/issues/2067
 [#2056]: https://github.com/import-js/eslint-plugin-import/issues/2056
 [#2063]: https://github.com/import-js/eslint-plugin-import/issues/2063
+[#1998]: https://github.com/import-js/eslint-plugin-import/issues/1998
 [#1965]: https://github.com/import-js/eslint-plugin-import/issues/1965
 [#1924]: https://github.com/import-js/eslint-plugin-import/issues/1924
 [#1854]: https://github.com/import-js/eslint-plugin-import/issues/1854
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 46d3cfe88c..f49841835b 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -414,6 +414,39 @@ ExportMap.parse = function (path, content, context) {
     return object;
   }
 
+  function processSpecifier(s, n, m) {
+    const nsource = n.source && n.source.value;
+    const exportMeta = {};
+    let local;
+
+    switch (s.type) {
+    case 'ExportDefaultSpecifier':
+      if (!n.source) return;
+      local = 'default';
+      break;
+    case 'ExportNamespaceSpecifier':
+      m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
+        get() { return resolveImport(nsource); },
+      }));
+      return;
+    case 'ExportAllDeclaration':
+      local = s.exported ? s.exported.name : s.local.name;
+      break;
+    case 'ExportSpecifier':
+      if (!n.source) {
+        m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local));
+        return;
+      }
+      // else falls through
+    default:
+      local = s.local.name;
+      break;
+    }
+
+    // todo: JSDoc
+    m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) });
+  }
+
   function captureDependency({ source }, isOnlyImportingTypes, importedSpecifiers = new Set()) {
     if (source == null) return null;
 
@@ -489,6 +522,9 @@ ExportMap.parse = function (path, content, context) {
     if (n.type === 'ExportAllDeclaration') {
       const getter = captureDependency(n, n.exportKind === 'type');
       if (getter) m.dependencies.add(getter);
+      if (n.exported) {
+        processSpecifier(n, n.exported, m);
+      }
       return;
     }
 
@@ -546,35 +582,7 @@ ExportMap.parse = function (path, content, context) {
         }
       }
 
-      const nsource = n.source && n.source.value;
-      n.specifiers.forEach((s) => {
-        const exportMeta = {};
-        let local;
-
-        switch (s.type) {
-        case 'ExportDefaultSpecifier':
-          if (!n.source) return;
-          local = 'default';
-          break;
-        case 'ExportNamespaceSpecifier':
-          m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
-            get() { return resolveImport(nsource); },
-          }));
-          return;
-        case 'ExportSpecifier':
-          if (!n.source) {
-            m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local));
-            return;
-          }
-          // else falls through
-        default:
-          local = s.local.name;
-          break;
-        }
-
-        // todo: JSDoc
-        m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) });
-      });
+      n.specifiers.forEach((s) => processSpecifier(s, n, m));
     }
 
     const exports = ['TSExportAssignment'];
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index a23cfeac88..74ee9dae3c 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -60,7 +60,7 @@ module.exports = {
               if (!imports.size) {
                 context.report(
                   specifier,
-                  `No exported names found in module '${declaration.source.value}'.`
+                  `No exported names found in module '${declaration.source.value}'.`,
                 );
               }
               namespaces.set(specifier.local.name, imports);
@@ -69,7 +69,7 @@ module.exports = {
             case 'ImportSpecifier': {
               const meta = imports.get(
                 // default to 'default' for default http://i.imgur.com/nj6qAWy.jpg
-                specifier.imported ? specifier.imported.name : 'default'
+                specifier.imported ? specifier.imported.name : 'default',
               );
               if (!meta || !meta.namespace) { break; }
               namespaces.set(specifier.local.name, meta.namespace);
@@ -96,7 +96,7 @@ module.exports = {
         if (!imports.size) {
           context.report(
             namespace,
-            `No exported names found in module '${declaration.source.value}'.`
+            `No exported names found in module '${declaration.source.value}'.`,
           );
         }
       },
@@ -111,7 +111,7 @@ module.exports = {
         if (dereference.parent.type === 'AssignmentExpression' && dereference.parent.left === dereference) {
           context.report(
             dereference.parent,
-            `Assignment to member of namespace '${dereference.object.name}'.`
+            `Assignment to member of namespace '${dereference.object.name}'.`,
           );
         }
 
@@ -125,7 +125,7 @@ module.exports = {
             if (!allowComputed) {
               context.report(
                 dereference.property,
-                `Unable to validate computed reference to imported namespace '${dereference.object.name}'.`
+                `Unable to validate computed reference to imported namespace '${dereference.object.name}'.`,
               );
             }
             return;
@@ -134,7 +134,7 @@ module.exports = {
           if (!namespace.has(dereference.property.name)) {
             context.report(
               dereference.property,
-              makeMessage(dereference.property, namepath)
+              makeMessage(dereference.property, namepath),
             );
             break;
           }
diff --git a/tests/files/export-star-2/middle.js b/tests/files/export-star-2/middle.js
new file mode 100644
index 0000000000..2fc07cd9a3
--- /dev/null
+++ b/tests/files/export-star-2/middle.js
@@ -0,0 +1 @@
+export * as myName from './upstream';
diff --git a/tests/files/export-star-2/upstream.js b/tests/files/export-star-2/upstream.js
new file mode 100644
index 0000000000..cc798ff50d
--- /dev/null
+++ b/tests/files/export-star-2/upstream.js
@@ -0,0 +1 @@
+export const a = 1;
diff --git a/tests/files/export-star/extfield.js b/tests/files/export-star/extfield.js
new file mode 100644
index 0000000000..7a4e8a723a
--- /dev/null
+++ b/tests/files/export-star/extfield.js
@@ -0,0 +1 @@
+export default 42;
diff --git a/tests/files/export-star/extfield2.js b/tests/files/export-star/extfield2.js
new file mode 100644
index 0000000000..5f2610afc7
--- /dev/null
+++ b/tests/files/export-star/extfield2.js
@@ -0,0 +1 @@
+export default NaN;
diff --git a/tests/files/export-star/models.js b/tests/files/export-star/models.js
new file mode 100644
index 0000000000..1091770f7f
--- /dev/null
+++ b/tests/files/export-star/models.js
@@ -0,0 +1,2 @@
+export * as ExtfieldModel from './extfield';
+export * as Extfield2Model from './extfield2';
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 57e40c91ac..0d8c0b7edf 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES, getTSParsers } from '../utils';
+import { test, SYNTAX_CASES, getTSParsers, testFilePath, testVersion } from '../utils';
 import { RuleTester } from 'eslint';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
@@ -182,10 +182,18 @@ ruleTester.run('named', rule, {
     }),
 
     ...SYNTAX_CASES,
+
+    ...[].concat(testVersion('>= 6', () => ({
+      code: `import { ExtfieldModel, Extfield2Model } from './models';`,
+      filename: testFilePath('./export-star/downstream.js'),
+      parserOptions: {
+        sourceType: 'module',
+        ecmaVersion: 2020,
+      },
+    })) || []),
   ],
 
   invalid: [
-
     test({ code: 'import { somethingElse } from "./test-module"',
       errors: [ error('somethingElse', './test-module') ] }),
 
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index ce55bccc35..802d5b440b 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES, getTSParsers } from '../utils';
+import { test, SYNTAX_CASES, getTSParsers, testVersion, testFilePath } from '../utils';
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
 
@@ -172,6 +172,18 @@ const valid = [
     export const getExampleColor = () => color.example
     `,
   }),
+
+  ...[].concat(testVersion('>= 6', () => ({
+    code: `
+      import * as middle from './middle';
+
+      console.log(middle.myName);
+    `,
+    filename: testFilePath('export-star-2/downstream.js'),
+    parserOptions: {
+      ecmaVersion: 2020,
+    },
+  })) || []),
 ];
 
 const invalid = [

From 3977c42452e0e7a2c9f787a6e5f7ca5ec9986d8f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 17 Aug 2021 23:40:01 -0700
Subject: [PATCH 346/767] [Tests] clean up tests, ensure `test()` is used
 properly

---
 tests/src/rules/first.js                 | 143 ++---
 tests/src/rules/no-duplicates.js         |  13 +-
 tests/src/rules/order.js                 | 636 +++++++++++------------
 tests/src/rules/prefer-default-export.js |  76 ++-
 tests/src/utils.js                       |   3 +
 5 files changed, 411 insertions(+), 460 deletions(-)

diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index 3f7301319d..9d27870677 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -7,60 +7,71 @@ const rule = require('rules/first');
 
 ruleTester.run('first', rule, {
   valid: [
-    test({ code: "import { x } from './foo'; import { y } from './bar';\
-                  export { x, y }" }),
+    test({
+      code: "import { x } from './foo'; import { y } from './bar';\
+            export { x, y }",
+    }),
     test({ code: "import { x } from 'foo'; import { y } from './bar'" }),
     test({ code: "import { x } from './foo'; import { y } from 'bar'" }),
-    test({ code: "import { x } from './foo'; import { y } from 'bar'",
+    test({
+      code: "import { x } from './foo'; import { y } from 'bar'",
       options: ['disable-absolute-first'],
     }),
-    test({ code: "'use directive';\
-                  import { x } from 'foo';" }),  
+    test({
+      code: "'use directive';\
+            import { x } from 'foo';",
+    }),
   ],
   invalid: [
-    test({ code: "import { x } from './foo';\
-                  export { x };\
-                  import { y } from './bar';",
-    errors: 1,
-    output: "import { x } from './foo';\
-                  import { y } from './bar';\
-                  export { x };",
+    test({
+      code: "import { x } from './foo';\
+              export { x };\
+              import { y } from './bar';",
+      errors: 1,
+      output: "import { x } from './foo';\
+              import { y } from './bar';\
+              export { x };",
     }),
-    test({ code: "import { x } from './foo';\
-                  export { x };\
-                  import { y } from './bar';\
-                  import { z } from './baz';",
-    errors: 2,
-    output: "import { x } from './foo';\
-                  import { y } from './bar';\
-                  import { z } from './baz';\
-                  export { x };",
+    test({
+      code: "import { x } from './foo';\
+              export { x };\
+              import { y } from './bar';\
+              import { z } from './baz';",
+      errors: 2,
+      output: "import { x } from './foo';\
+              import { y } from './bar';\
+              import { z } from './baz';\
+              export { x };",
     }),
-    test({ code: "import { x } from './foo'; import { y } from 'bar'",
+    test({
+      code: "import { x } from './foo'; import { y } from 'bar'",
       options: ['absolute-first'],
       errors: 1,
     }),
-    test({ code: "import { x } from 'foo';\
-                  'use directive';\
-                  import { y } from 'bar';",
-    errors: 1,
-    output: "import { x } from 'foo';\
-                  import { y } from 'bar';\
-                  'use directive';",
+    test({
+      code: "import { x } from 'foo';\
+              'use directive';\
+              import { y } from 'bar';",
+      errors: 1,
+      output: "import { x } from 'foo';\
+              import { y } from 'bar';\
+              'use directive';",
     }),
-    test({ code: "var a = 1;\
-                  import { y } from './bar';\
-                  if (true) { x() };\
-                  import { x } from './foo';\
-                  import { z } from './baz';",
-    errors: 3,
-    output: "import { y } from './bar';\
-                  var a = 1;\
-                  if (true) { x() };\
-                  import { x } from './foo';\
-                  import { z } from './baz';",
+    test({
+      code: "var a = 1;\
+              import { y } from './bar';\
+              if (true) { x() };\
+              import { x } from './foo';\
+              import { z } from './baz';",
+      errors: 3,
+      output: "import { y } from './bar';\
+              var a = 1;\
+              if (true) { x() };\
+              import { x } from './foo';\
+              import { z } from './baz';",
     }),
-    test({ code: "if (true) { console.log(1) }import a from 'b'",
+    test({
+      code: "if (true) { console.log(1) }import a from 'b'",
       errors: 1,
       output: "import a from 'b'\nif (true) { console.log(1) }",
     }),  
@@ -72,7 +83,7 @@ context('TypeScript', function () {
     .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
     .forEach((parser) => {
       const parserConfig = {
-        parser: parser,
+        parser,
         settings: {
           'import/parsers': { [parser]: ['.ts'] },
           'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -81,35 +92,29 @@ context('TypeScript', function () {
 
       ruleTester.run('order', rule, {
         valid: [
-          test(
-            {
-              code: `
-                import y = require('bar');
-                import { x } from 'foo';
-                import z = require('baz');
-              `,
-              parser,
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import y = require('bar');
+              import { x } from 'foo';
+              import z = require('baz');
+            `,
+            ...parserConfig,
+          }),
         ],
         invalid: [
-          test(
-            {
-              code: `
-                import { x } from './foo';
-                import y = require('bar');
-              `,
-              options: ['absolute-first'],
-              parser,
-              errors: [
-                {
-                  message: 'Absolute imports should come before relative imports.',
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import { x } from './foo';
+              import y = require('bar');
+            `,
+            options: ['absolute-first'],
+            ...parserConfig,
+            errors: [
+              {
+                message: 'Absolute imports should come before relative imports.',
+              },
+            ],
+          }),
         ],
       });
     });
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index d16f37b103..d1b9c74567 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -420,7 +420,7 @@ context('TypeScript', function() {
     .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
     .forEach((parser) => {
       const parserConfig = {
-        parser: parser,
+        parser,
         settings: {
           'import/parsers': { [parser]: ['.ts'] },
           'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -430,13 +430,10 @@ context('TypeScript', function() {
       ruleTester.run('no-duplicates', rule, {
         valid: [
         // #1667: ignore duplicate if is a typescript type import
-          test(
-            {
-              code: "import type { x } from './foo'; import y from './foo'",
-              parser,
-            },
-            parserConfig,
-          ),
+          test({
+            code: "import type { x } from './foo'; import y from './foo'",
+            ...parserConfig,
+          }),
         ],
         invalid: [],
       });
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index e7e6b0566d..61bf1bb70f 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2286,7 +2286,7 @@ context('TypeScript', function () {
     .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
     .forEach((parser) => {
       const parserConfig = {
-        parser: parser,
+        parser,
         settings: {
           'import/parsers': { [parser]: ['.ts'] },
           'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -2298,352 +2298,316 @@ context('TypeScript', function () {
           // #1667: typescript type import support
 
           // Option alphabetize: {order: 'asc'}
-          test(
-            {
-              code: `
-                import c from 'Bar';
-                import type { C } from 'Bar';
-                import b from 'bar';
-                import a from 'foo';
-                import type { A } from 'foo';
-
-                import index from './';
-              `,
-              parser,
-              options: [
-                {
-                  groups: ['external', 'index'],
-                  alphabetize: { order: 'asc' },
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import b from 'bar';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index'],
+                alphabetize: { order: 'asc' },
+              },
+            ],
+          }),
           // Option alphabetize: {order: 'desc'}
-          test(
-            {
-              code: `
-                import a from 'foo';
-                import type { A } from 'foo';
-                import b from 'bar';
-                import c from 'Bar';
-                import type { C } from 'Bar';
-
-                import index from './';
-              `,
-              parser,
-              options: [
-                {
-                  groups: ['external', 'index'],
-                  alphabetize: { order: 'desc' },
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import a from 'foo';
+              import type { A } from 'foo';
+              import b from 'bar';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index'],
+                alphabetize: { order: 'desc' },
+              },
+            ],
+          }),
           // Option alphabetize: {order: 'asc'} with type group
-          test(
-            {
-              code: `
-                import c from 'Bar';
-                import b from 'bar';
-                import a from 'foo';
-
-                import index from './';
-
-                import type { C } from 'Bar';
-                import type { A } from 'foo';
-              `,
-              parser,
-              options: [
-                {
-                  groups: ['external', 'index', 'type'],
-                  alphabetize: { order: 'asc' },
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import c from 'Bar';
+              import b from 'bar';
+              import a from 'foo';
+
+              import index from './';
+
+              import type { C } from 'Bar';
+              import type { A } from 'foo';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index', 'type'],
+                alphabetize: { order: 'asc' },
+              },
+            ],
+          }),
           // Option alphabetize: {order: 'asc'} with type group & path group
-          test(
-            {
-              // only: true,
-              code: `
-                import c from 'Bar';
-                import a from 'foo';
-
-                import b from 'dirA/bar';
-
-                import index from './';
-
-                import type { C } from 'dirA/Bar';
-                import type { A } from 'foo';
-              `,
-              parser,
-              options: [
-                {
-                  alphabetize: { order: 'asc' },
-                  groups: ['external', 'internal', 'index', 'type'],
-                  pathGroups: [
-                    {
-                      pattern: 'dirA/**',
-                      group: 'internal',
-                    },
-                  ],
-                  'newlines-between': 'always',
-                  pathGroupsExcludedImportTypes: ['type'],
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            // only: true,
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+
+              import type { C } from 'dirA/Bar';
+              import type { A } from 'foo';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                pathGroupsExcludedImportTypes: ['type'],
+              },
+            ],
+          }),
           // Option alphabetize: {order: 'asc'} with path group
-          test(
-            {
-              // only: true,
-              code: `
-                import c from 'Bar';
-                import type { A } from 'foo';
-                import a from 'foo';
-
-                import type { C } from 'dirA/Bar';
-                import b from 'dirA/bar';
-
-                import index from './';
-              `,
-              parser,
-              options: [
-                {
-                  alphabetize: { order: 'asc' },
-                  groups: ['external', 'internal', 'index'],
-                  pathGroups: [
-                    {
-                      pattern: 'dirA/**',
-                      group: 'internal',
-                    },
-                  ],
-                  'newlines-between': 'always',
-                  pathGroupsExcludedImportTypes: [],
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            // only: true,
+            code: `
+              import c from 'Bar';
+              import type { A } from 'foo';
+              import a from 'foo';
+
+              import type { C } from 'dirA/Bar';
+              import b from 'dirA/bar';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                pathGroupsExcludedImportTypes: [],
+              },
+            ],
+          }),
           // Option alphabetize: {order: 'desc'} with type group
-          test(
-            {
-              code: `
-                import a from 'foo';
-                import b from 'bar';
-                import c from 'Bar';
-
-                import index from './';
-
-                import type { A } from 'foo';
-                import type { C } from 'Bar';
-              `,
-              parser,
-              options: [
-                {
-                  groups: ['external', 'index', 'type'],
-                  alphabetize: { order: 'desc' },
-                },
-              ],
-            },
-            parserConfig,
-          ),
-          test(
-            {
-              code: `
-                import { Partner } from '@models/partner/partner';
-                import { PartnerId } from '@models/partner/partner-id';
-              `,
-              parser,
-              options: [
-                {
-                  alphabetize: { order: 'asc' },
-                },
-              ],
-            },
-            parserConfig,
-          ),
-          test(
-            {
-              code: `
-                import { serialize, parse, mapFieldErrors } from '@vtaits/form-schema';
-                import type { GetFieldSchema } from '@vtaits/form-schema';
-                import { useMemo, useCallback } from 'react';
-                import type { ReactElement, ReactNode } from 'react';
-                import { Form } from 'react-final-form';
-                import type { FormProps as FinalFormProps } from 'react-final-form';
-              `,
-              parser,
-              options: [
-                {
-                  alphabetize: { order: 'asc' },
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import a from 'foo';
+              import b from 'bar';
+              import c from 'Bar';
+
+              import index from './';
+
+              import type { A } from 'foo';
+              import type { C } from 'Bar';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index', 'type'],
+                alphabetize: { order: 'desc' },
+              },
+            ],
+          }),
+          test({
+            code: `
+              import { Partner } from '@models/partner/partner';
+              import { PartnerId } from '@models/partner/partner-id';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+              },
+            ],
+          }),
+          test({
+            code: `
+              import { serialize, parse, mapFieldErrors } from '@vtaits/form-schema';
+              import type { GetFieldSchema } from '@vtaits/form-schema';
+              import { useMemo, useCallback } from 'react';
+              import type { ReactElement, ReactNode } from 'react';
+              import { Form } from 'react-final-form';
+              import type { FormProps as FinalFormProps } from 'react-final-form';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+              },
+            ],
+          }),
         ],
         invalid: [
           // Option alphabetize: {order: 'asc'}
-          test(
-            {
-              code: `
-                import b from 'bar';
-                import c from 'Bar';
-                import type { C } from 'Bar';
-                import a from 'foo';
-                import type { A } from 'foo';
-
-                import index from './';
-              `,
-              output: `
-                import c from 'Bar';
-                import type { C } from 'Bar';
-                import b from 'bar';
-                import a from 'foo';
-                import type { A } from 'foo';
-
-                import index from './';
-              `,
-              parser,
-              options: [
-                {
-                  groups: ['external', 'index'],
-                  alphabetize: { order: 'asc' },
-                },
-              ],
-              errors: [
-                {
-                  message: semver.satisfies(eslintPkg.version, '< 3')
-                    ? '`bar` import should occur after import of `Bar`'
-                    : /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import b from 'bar';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import index from './';
+            `,
+            output: `
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import b from 'bar';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index'],
+                alphabetize: { order: 'asc' },
+              },
+            ],
+            errors: [
+              {
+                message: semver.satisfies(eslintPkg.version, '< 3')
+                  ? '`bar` import should occur after import of `Bar`'
+                  : /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,
+              },
+            ],
+          }),
           // Option alphabetize: {order: 'desc'}
-          test(
-            {
-              code: `
-                import a from 'foo';
-                import type { A } from 'foo';
-                import c from 'Bar';
-                import type { C } from 'Bar';
-                import b from 'bar';
-
-                import index from './';
-              `,
-              output: `
-                import a from 'foo';
-                import type { A } from 'foo';
-                import b from 'bar';
-                import c from 'Bar';
-                import type { C } from 'Bar';
-
-                import index from './';
-              `,
-              parser,
-              options: [
-                {
-                  groups: ['external', 'index'],
-                  alphabetize: { order: 'desc' },
-                },
-              ],
-              errors: [
-                {
-                  message: semver.satisfies(eslintPkg.version, '< 3')
-                    ? '`bar` import should occur before import of `Bar`'
-                    : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
-                },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import a from 'foo';
+              import type { A } from 'foo';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import b from 'bar';
+
+              import index from './';
+            `,
+            output: `
+              import a from 'foo';
+              import type { A } from 'foo';
+              import b from 'bar';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index'],
+                alphabetize: { order: 'desc' },
+              },
+            ],
+            errors: [
+              {
+                message: semver.satisfies(eslintPkg.version, '< 3')
+                  ? '`bar` import should occur before import of `Bar`'
+                  : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
+              },
+            ],
+          }),
           // Option alphabetize: {order: 'asc'} with type group
-          test(
-            {
-              code: `
-                import b from 'bar';
-                import c from 'Bar';
-                import a from 'foo';
-
-                import index from './';
-
-                import type { A } from 'foo';
-                import type { C } from 'Bar';
-              `,
-              output: `
-                import c from 'Bar';
-                import b from 'bar';
-                import a from 'foo';
-
-                import index from './';
-
-                import type { C } from 'Bar';
-                import type { A } from 'foo';
-              `,
-              parser,
-              options: [
-                {
-                  groups: ['external', 'index', 'type'],
-                  alphabetize: { order: 'asc' },
-                },
-              ],
-              errors: semver.satisfies(eslintPkg.version, '< 3') ? [
-                { message: '`Bar` import should occur before import of `bar`' },
-                { message: '`Bar` import should occur before import of `foo`' },
-              ] : [
-                { message: /(`Bar` import should occur before import of `bar`)|(`bar` import should occur after import of `Bar`)/ },
-                { message: /(`Bar` import should occur before import of `foo`)|(`foo` import should occur after import of `Bar`)/ },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import b from 'bar';
+              import c from 'Bar';
+              import a from 'foo';
+
+              import index from './';
+
+              import type { A } from 'foo';
+              import type { C } from 'Bar';
+            `,
+            output: `
+              import c from 'Bar';
+              import b from 'bar';
+              import a from 'foo';
+
+              import index from './';
+
+              import type { C } from 'Bar';
+              import type { A } from 'foo';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index', 'type'],
+                alphabetize: { order: 'asc' },
+              },
+            ],
+            errors: semver.satisfies(eslintPkg.version, '< 3') ? [
+              { message: '`Bar` import should occur before import of `bar`' },
+              { message: '`Bar` import should occur before import of `foo`' },
+            ] : [
+              { message: /(`Bar` import should occur before import of `bar`)|(`bar` import should occur after import of `Bar`)/ },
+              { message: /(`Bar` import should occur before import of `foo`)|(`foo` import should occur after import of `Bar`)/ },
+            ],
+          }),
           // Option alphabetize: {order: 'desc'} with type group
-          test(
-            {
-              code: `
-                import a from 'foo';
-                import c from 'Bar';
-                import b from 'bar';
-
-                import index from './';
-
-                import type { C } from 'Bar';
-                import type { A } from 'foo';
-              `,
-              output: `
-                import a from 'foo';
-                import b from 'bar';
-                import c from 'Bar';
-
-                import index from './';
-
-                import type { A } from 'foo';
-                import type { C } from 'Bar';
-              `,
-              parser,
-              options: [
-                {
-                  groups: ['external', 'index', 'type'],
-                  alphabetize: { order: 'desc' },
-                },
-              ],
-              errors: semver.satisfies(eslintPkg.version, '< 3') ? [
-                { message: '`bar` import should occur before import of `Bar`' },
-                { message: '`foo` import should occur before import of `Bar`' },
-              ] : [
-                { message: /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/ },
-                { message: /(`foo` import should occur before import of `Bar`)|(`Bar` import should occur after import of `foo`)/ },
-              ],
-            },
-            parserConfig,
-          ),
+          test({
+            code: `
+              import a from 'foo';
+              import c from 'Bar';
+              import b from 'bar';
+
+              import index from './';
+
+              import type { C } from 'Bar';
+              import type { A } from 'foo';
+            `,
+            output: `
+              import a from 'foo';
+              import b from 'bar';
+              import c from 'Bar';
+
+              import index from './';
+
+              import type { A } from 'foo';
+              import type { C } from 'Bar';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index', 'type'],
+                alphabetize: { order: 'desc' },
+              },
+            ],
+            errors: semver.satisfies(eslintPkg.version, '< 3') ? [
+              { message: '`bar` import should occur before import of `Bar`' },
+              { message: '`foo` import should occur before import of `Bar`' },
+            ] : [
+              { message: /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/ },
+              { message: /(`foo` import should occur before import of `Bar`)|(`Bar` import should occur after import of `foo`)/ },
+            ],
+          }),
           // warns for out of order unassigned imports (warnOnUnassignedImports enabled)
           test({
             code: `
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 4efa47f5fc..34323fe53d 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -151,7 +151,7 @@ ruleTester.run('prefer-default-export', rule, {
 context('TypeScript', function() {
   getNonDefaultParsers().forEach((parser) => {
     const parserConfig = {
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -161,52 +161,34 @@ context('TypeScript', function() {
     ruleTester.run('prefer-default-export', rule, {
       valid: [
         // Exporting types
-        test(
-          {
-            code: `
-        export type foo = string;
-        export type bar = number;`,
-            parser,
-          },
-          parserConfig,
-        ),
-        test(
-          {
-            code: `
-        export type foo = string;
-        export type bar = number;`,
-            parser,
-          },
-          parserConfig,
-        ),
-        test(
-          {
-            code: 'export type foo = string',
-            parser,
-          },
-          parserConfig,
-        ),
-        test(
-          {
-            code: 'export type foo = string',
-            parser,
-          },
-          parserConfig,
-        ),
-        test(
-          {
-            code: 'export interface foo { bar: string; }',
-            parser,
-          },
-          parserConfig,
-        ),
-        test(
-          {
-            code: 'export interface foo { bar: string; }; export function goo() {}',
-            parser,
-          },
-          parserConfig,
-        ),
+        test({
+          code: `
+          export type foo = string;
+          export type bar = number;`,
+          ...parserConfig,
+        }),
+        test({
+          code: `
+          export type foo = string;
+          export type bar = number;`,
+          ...parserConfig,
+        }),
+        test({
+          code: 'export type foo = string',
+          ...parserConfig,
+        }),
+        test({
+          code: 'export type foo = string',
+          ...parserConfig,
+        }),
+        test({
+          code: 'export interface foo { bar: string; }',
+          ...parserConfig,
+        }),
+        test({
+          code: 'export interface foo { bar: string; }; export function goo() {}',
+          ...parserConfig,
+        }),
       ],
       invalid: [],
     });
diff --git a/tests/src/utils.js b/tests/src/utils.js
index a76826de51..e805e9545d 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -32,6 +32,9 @@ export function testVersion(specifier, t) {
 }
 
 export function test(t) {
+  if (arguments.length !== 1) {
+    throw new SyntaxError('`test` requires exactly one object argument');
+  }
   return Object.assign({
     filename: FILENAME,
   }, t, {

From 712ee494407bf08c7e1ffcbc19b5d95c4ecf7655 Mon Sep 17 00:00:00 2001
From: Nathan Walters <nwalters@nerdwallet.com>
Date: Tue, 17 Aug 2021 14:29:19 -0700
Subject: [PATCH 347/767] [fix] `no-duplicates`: correctly handle case of mixed
 default/named type imports

Co-authored-by: Nathan Walters <nwalters@nerdwallet.com>
Co-authored-by: Gord Pearson <gord.pearson@shopify.com>
---
 CHANGELOG.md                     |  6 ++-
 src/rules/no-duplicates.js       | 22 ++++++++---
 tests/src/rules/no-duplicates.js | 65 +++++++++++++++++++++++++++++++-
 3 files changed, 85 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e59d246266..a05937ab5b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok])
 - [`named`], [`namespace`]: properly set reexports on `export * as … from` ([#1998], [#2161], thanks [@ljharb])
+- [`no-duplicates`]: correctly handle case of mixed default/named type imports ([#2149], thanks [@GoodForOneFare], [@nwalters512])
 
 ### Changed
 - [Docs] `max-dependencies`: 📖 Document `ignoreTypeImports` option ([#2196], thanks [@himynameisdave])
@@ -897,6 +898,7 @@ for info on changes for earlier releases.
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
 [#2158]: https://github.com/import-js/eslint-plugin-import/pull/2158
 [#2156]: https://github.com/import-js/eslint-plugin-import/pull/2156
+[#2149]: https://github.com/benmosher/eslint-plugin-import/pull/2149
 [#2146]: https://github.com/import-js/eslint-plugin-import/pull/2146
 [#2140]: https://github.com/import-js/eslint-plugin-import/pull/2140
 [#2138]: https://github.com/import-js/eslint-plugin-import/pull/2138
@@ -1404,6 +1406,7 @@ for info on changes for earlier releases.
 [@gavriguy]: https://github.com/gavriguy
 [@giodamelio]: https://github.com/giodamelio
 [@golopot]: https://github.com/golopot
+[@GoodForOneFare]: https://github.com/GoodForOneFare
 [@graingert]: https://github.com/graingert
 [@grit96]: https://github.com/grit96
 [@guillaumewuip]: https://github.com/guillaumewuip
@@ -1471,6 +1474,7 @@ for info on changes for earlier releases.
 [@nicolashenry]: https://github.com/nicolashenry
 [@noelebrun]: https://github.com/noelebrun
 [@ntdb]: https://github.com/ntdb
+[@nwalters512]: https://github.com/nwalters512
 [@panrafal]: https://github.com/panrafal
 [@paztis]: https://github.com/paztis
 [@pcorpet]: https://github.com/pcorpet
@@ -1533,4 +1537,4 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xpl]: https://github.com/xpl
 [@yordis]: https://github.com/yordis
-[@zloirock]: https://github.com/zloirock
\ No newline at end of file
+[@zloirock]: https://github.com/zloirock
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 43a29506be..6344101970 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -276,13 +276,22 @@ module.exports = {
 
     const imported = new Map();
     const nsImported = new Map();
-    const typesImported = new Map();
+    const defaultTypesImported = new Map();
+    const namedTypesImported = new Map();
+
+    function getImportMap(n) {
+      if (n.importKind === 'type') {
+        return n.specifiers[0].type === 'ImportDefaultSpecifier' ? defaultTypesImported : namedTypesImported;
+      }
+
+      return hasNamespace(n) ? nsImported : imported;
+    }
+
     return {
-      'ImportDeclaration': function (n) {
+      ImportDeclaration(n) {
         // resolved path will cover aliased duplicates
         const resolvedPath = resolver(n.source.value);
-        const importMap = n.importKind === 'type' ? typesImported :
-          (hasNamespace(n) ? nsImported : imported);
+        const importMap = getImportMap(n);
 
         if (importMap.has(resolvedPath)) {
           importMap.get(resolvedPath).push(n);
@@ -291,10 +300,11 @@ module.exports = {
         }
       },
 
-      'Program:exit': function () {
+      'Program:exit'() {
         checkImports(imported, context);
         checkImports(nsImported, context);
-        checkImports(typesImported, context);
+        checkImports(defaultTypesImported, context);
+        checkImports(namedTypesImported, context);
       },
     };
   },
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index d1b9c74567..c6b355ab88 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -434,8 +434,71 @@ context('TypeScript', function() {
             code: "import type { x } from './foo'; import y from './foo'",
             ...parserConfig,
           }),
+          test({
+            code: "import type x from './foo'; import type y from './bar'",
+            ...parserConfig,
+          }),
+          test({
+            code: "import type {x} from './foo'; import type {y} from './bar'",
+            ...parserConfig,
+          }),
+          test({
+            code: "import type x from './foo'; import type {y} from './foo'",
+            ...parserConfig,
+          }),
+        ],
+        invalid: [
+          test({
+            code: "import type x from './foo'; import type y from './foo'",
+            ...parserConfig,
+            errors: [
+              {
+                line: 1,
+                column: 20,
+                message: "'./foo' imported multiple times.",
+              },
+              {
+                line: 1,
+                column: 48,
+                message: "'./foo' imported multiple times.",
+              },
+            ],
+          }),
+          test({
+            code: "import type x from './foo'; import type x from './foo'",
+            output: "import type x from './foo'; ",
+            ...parserConfig,
+            errors: [
+              {
+                line: 1,
+                column: 20,
+                message: "'./foo' imported multiple times.",
+              },
+              {
+                line: 1,
+                column: 48,
+                message: "'./foo' imported multiple times.",
+              },
+            ],
+          }),
+          test({
+            code: "import type {x} from './foo'; import type {y} from './foo'",
+            ...parserConfig,
+            output: `import type {x,y} from './foo'; `,
+            errors: [
+              {
+                line: 1,
+                column: 22,
+                message: "'./foo' imported multiple times.",
+              },
+              {
+                line: 1,
+                column: 52,
+                message: "'./foo' imported multiple times.",
+              },
+            ],
+          }),
         ],
-        invalid: [],
       });
     });
 });

From c5d208debf4c11c7db60d2304fddc7bf54283e79 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 19 Aug 2021 13:13:47 -0700
Subject: [PATCH 348/767] [Deps] update `eslint-import-resolver-node`,
 `is-core-module`, `object.values`, `tsconfig-paths`

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index e3bc5a8d96..e4b000068a 100644
--- a/package.json
+++ b/package.json
@@ -104,16 +104,16 @@
     "array.prototype.flat": "^1.2.4",
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
-    "eslint-import-resolver-node": "^0.3.5",
+    "eslint-import-resolver-node": "^0.3.6",
     "eslint-module-utils": "^2.6.2",
     "find-up": "^2.0.0",
     "has": "^1.0.3",
-    "is-core-module": "^2.4.0",
+    "is-core-module": "^2.6.0",
     "minimatch": "^3.0.4",
-    "object.values": "^1.1.3",
+    "object.values": "^1.1.4",
     "pkg-up": "^2.0.0",
     "read-pkg-up": "^3.0.0",
     "resolve": "^1.20.0",
-    "tsconfig-paths": "^3.9.0"
+    "tsconfig-paths": "^3.10.1"
   }
 }

From 62cb4b5ad3f73f5cbec3f26f9794348afc9e482c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 19 Aug 2021 13:17:34 -0700
Subject: [PATCH 349/767] [Dev Deps] update `coveralls`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index e4b000068a..461706b4e8 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,7 @@
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
     "chai": "^4.3.4",
-    "coveralls": "^3.1.0",
+    "coveralls": "^3.1.1",
     "cross-env": "^4.0.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0",
     "eslint-import-resolver-node": "file:./resolvers/node",

From 4dc4651f787ddb3ee774da608f4adcf2fab38a46 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 19 Aug 2021 13:18:29 -0700
Subject: [PATCH 350/767] [resolvers/webpack] [Deps] update `is-core-module`,
 `is-regex`

---
 resolvers/webpack/package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 32650c07c2..1e9fdd3ab1 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -38,8 +38,8 @@
     "find-root": "^1.1.0",
     "has": "^1.0.3",
     "interpret": "^1.4.0",
-    "is-core-module": "^2.4.0",
-    "is-regex": "^1.1.3",
+    "is-core-module": "^2.6.0",
+    "is-regex": "^1.1.4",
     "lodash": "^4.17.21",
     "resolve": "^1.20.0",
     "semver": "^5.7.1"

From 6171a7aa996fdb12fc7abc88bbdcd32b301ad906 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 19 Aug 2021 13:21:06 -0700
Subject: [PATCH 351/767] Bump to v2.24.1

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a05937ab5b..4991b7a9a4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.24.1] - 2021-08-19
+
 ### Fixed
 - `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok])
 - [`named`], [`namespace`]: properly set reexports on `export * as … from` ([#1998], [#2161], thanks [@ljharb])
@@ -1257,7 +1259,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.0...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.1...HEAD
+[2.24.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.0...v2.24.1
 [2.24.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.4...v2.24.0
 [2.23.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.3...v2.23.4
 [2.23.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.2...v2.23.3
diff --git a/package.json b/package.json
index 461706b4e8..df42105dfa 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.24.0",
+  "version": "2.24.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 6c957e7df178d1b81d01cf219d62ba91b4e6d9e8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 19 Aug 2021 15:32:03 -0700
Subject: [PATCH 352/767] [Deps] pin `tsconfig-paths` due to a breaking change
 in v3.10

See https://github.com/dividab/tsconfig-paths/issues/171
---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index df42105dfa..d1a6bd5e01 100644
--- a/package.json
+++ b/package.json
@@ -114,6 +114,6 @@
     "pkg-up": "^2.0.0",
     "read-pkg-up": "^3.0.0",
     "resolve": "^1.20.0",
-    "tsconfig-paths": "^3.10.1"
+    "tsconfig-paths": "~3.9.0"
   }
 }

From 9485c8300dbf17047804adf9529dce21d64db0f5 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 20 Aug 2021 08:54:06 -0700
Subject: [PATCH 353/767] [meta] rename default branch

---
 README.md                      | 14 ++++++++++----
 RELEASE.md                     |  6 +++---
 docs/rules/imports-first.md    |  2 +-
 docs/rules/unambiguous.md      |  2 +-
 resolvers/webpack/package.json |  2 +-
 src/rules/no-commonjs.js       |  2 +-
 utils/moduleVisitor.js         |  2 +-
 7 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index 964c123a7e..d800cbfe57 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
 # eslint-plugin-import
 
-[![build status](https://travis-ci.org/import-js/eslint-plugin-import.svg?branch=master)](https://travis-ci.org/import-js/eslint-plugin-import)
-[![Coverage Status](https://coveralls.io/repos/github/import-js/eslint-plugin-import/badge.svg?branch=master)](https://coveralls.io/github/import-js/eslint-plugin-import?branch=master)
-[![win32 build status](https://ci.appveyor.com/api/projects/status/3mw2fifalmjlqf56/branch/master?svg=true)](https://ci.appveyor.com/project/import-js/eslint-plugin-import/branch/master)
+[![github actions][actions-image]][actions-url]
+[![travis-ci](https://travis-ci.org/import-js/eslint-plugin-import.svg?branch=main)](https://travis-ci.org/import-js/eslint-plugin-import)
+[![coverage][codecov-image]][codecov-url]
+[![win32 build status](https://ci.appveyor.com/api/projects/status/3mw2fifalmjlqf56/branch/main?svg=true)](https://ci.appveyor.com/project/import-js/eslint-plugin-import/branch/main)
 [![npm](https://img.shields.io/npm/v/eslint-plugin-import.svg)](https://www.npmjs.com/package/eslint-plugin-import)
 [![npm downloads](https://img.shields.io/npm/dt/eslint-plugin-import.svg?maxAge=2592000)](http://www.npmtrends.com/eslint-plugin-import)
 
@@ -171,7 +172,7 @@ extends:
   - plugin:import/typescript # this line does the trick
 ```
 
-[`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser
+[`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser
 
 # Resolvers
 
@@ -510,3 +511,8 @@ In Package Settings / SublimeLinter / User Settings:
 
 I believe this defaults to `3`, so you may not need to alter it depending on your
 project folder max depth.
+
+[codecov-image]: https://codecov.io/gh/import-js/eslint-plugin-import/branch/main/graphs/badge.svg
+[codecov-url]: https://app.codecov.io/gh/import-js/eslint-plugin-import/
+[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/import-js/eslint-plugin-import
+[actions-url]: https://github.com/import-js/eslint-plugin-import
diff --git a/RELEASE.md b/RELEASE.md
index 34ef1aadc6..6c048dc093 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -1,9 +1,9 @@
 # Release steps
 
-1. create a `release-[x.y.z]` branch from tip of `master` (or whatever release commit)
+1. create a `release-[x.y.z]` branch from tip of `main` (or whatever release commit)
 
    ```bash
-   git checkout master && git pull && git checkout -b release-2.1.0
+   git checkout main && git pull && git checkout -b release-2.1.0
    ```
 
 2. bump `package.json` + update CHANGELOG version links for all releasing packages (i.e., root + any resolvers)
@@ -49,6 +49,6 @@
 7. merge `release-[x.y.z]` into `release` (
    - ideally fast-forward, probably with Git CLI instead of Github
 
-8. merge `release` into `master`
+8. merge `release` into `main`
 
 Done!
diff --git a/docs/rules/imports-first.md b/docs/rules/imports-first.md
index e4cdda1151..7dadffa684 100644
--- a/docs/rules/imports-first.md
+++ b/docs/rules/imports-first.md
@@ -1,3 +1,3 @@
 # imports-first
 
-This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/first.md).
+This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/import-js/eslint-plugin-import/blob/HEAD/docs/rules/first.md).
diff --git a/docs/rules/unambiguous.md b/docs/rules/unambiguous.md
index 7955c3fbc8..92839b0c35 100644
--- a/docs/rules/unambiguous.md
+++ b/docs/rules/unambiguous.md
@@ -51,4 +51,4 @@ a `module`.
 - [node-eps#13](https://github.com/nodejs/node-eps/issues/13)
 
 [`parserOptions.sourceType`]: http://eslint.org/docs/user-guide/configuring#specifying-parser-options
-[Unambiguous JavaScript Grammar]: https://github.com/nodejs/node-eps/blob/master/002-es-modules.md#32-determining-if-source-is-an-es-module
+[Unambiguous JavaScript Grammar]: https://github.com/nodejs/node-eps/blob/HEAD/002-es-modules.md#32-determining-if-source-is-an-es-module
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 1e9fdd3ab1..fd805af8b7 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -30,7 +30,7 @@
   "bugs": {
     "url": "https://github.com/import-js/eslint-plugin-import/issues"
   },
-  "homepage": "https://github.com/import-js/eslint-plugin-import/tree/master/resolvers/webpack",
+  "homepage": "https://github.com/import-js/eslint-plugin-import/tree/HEAD/resolvers/webpack",
   "dependencies": {
     "array-find": "^1.0.0",
     "debug": "^3.2.7",
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index 08d29a0cdb..98f759cbc2 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -33,7 +33,7 @@ function validateScope(scope) {
   return scope.variableScope.type === 'module';
 }
 
-// https://github.com/estree/estree/blob/master/es5.md
+// https://github.com/estree/estree/blob/HEAD/es5.md
 function isConditional(node) {
   if (
     node.type === 'IfStatement'
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index 7f783624b4..8fb2b2604c 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -37,7 +37,7 @@ exports.default = function visitModules(visitor, options) {
   // for esmodule dynamic `import()` calls
   function checkImportCall(node) {
     let modulePath;
-    // refs https://github.com/estree/estree/blob/master/es2020.md#importexpression
+    // refs https://github.com/estree/estree/blob/HEAD/es2020.md#importexpression
     if (node.type === 'ImportExpression') {
       modulePath = node.source;
     } else if (node.type === 'CallExpression') {

From 94d6739ebc9fc0e0f06319c90ffad32da94e8a41 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 20 Aug 2021 20:46:04 -0700
Subject: [PATCH 354/767] [Tests] `no-extraneous-dependencies`: add passing
 test case of webpack loader syntax

Closes #1969
---
 tests/src/rules/no-extraneous-dependencies.js | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 7a11074684..370cce7e39 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -160,7 +160,10 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     }),
 
     test({
-      code: 'import "alias/esm-package/esm-module";',
+      code: `
+        import "alias/esm-package/esm-module";
+        import 'expose-loader?exposes[]=$&exposes[]=jQuery!jquery';
+      `,
       settings: { 'import/resolver': 'webpack' },
     }),
   ],

From aa8d566b288eb0fdce24f3a51f8a65cf520c2133 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 22 Aug 2021 08:54:35 -0700
Subject: [PATCH 355/767] [Fix] `no-duplicates`: avoid crash with empty `import
 type {}`

Fixes #2201
---
 CHANGELOG.md                     | 2 ++
 src/rules/no-duplicates.js       | 2 +-
 tests/src/rules/no-duplicates.js | 7 +++++++
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4991b7a9a4..59bcfb4be3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok])
 - [`named`], [`namespace`]: properly set reexports on `export * as … from` ([#1998], [#2161], thanks [@ljharb])
 - [`no-duplicates`]: correctly handle case of mixed default/named type imports ([#2149], thanks [@GoodForOneFare], [@nwalters512])
+- [`no-duplicates`]: avoid crash with empty `import type {}` ([#2201], thanks [@ljharb])
 
 ### Changed
 - [Docs] `max-dependencies`: 📖 Document `ignoreTypeImports` option ([#2196], thanks [@himynameisdave])
@@ -1150,6 +1151,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2201]: https://github.com/import-js/eslint-plugin-import/issues/2201
 [#2161]: https://github.com/import-js/eslint-plugin-import/issues/2161
 [#2118]: https://github.com/import-js/eslint-plugin-import/issues/2118
 [#2067]: https://github.com/import-js/eslint-plugin-import/issues/2067
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 6344101970..6e03fcaef0 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -281,7 +281,7 @@ module.exports = {
 
     function getImportMap(n) {
       if (n.importKind === 'type') {
-        return n.specifiers[0].type === 'ImportDefaultSpecifier' ? defaultTypesImported : namedTypesImported;
+        return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? defaultTypesImported : namedTypesImported;
       }
 
       return hasNamespace(n) ? nsImported : imported;
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index c6b355ab88..faf096acec 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -446,6 +446,13 @@ context('TypeScript', function() {
             code: "import type x from './foo'; import type {y} from './foo'",
             ...parserConfig,
           }),
+          test({
+            code: `
+              import type {} from './module';
+              import {} from './module2';
+            `,
+            ...parserConfig,
+          }),
         ],
         invalid: [
           test({

From 4aff27c6a25099f2617d0de7a6ddeb6a3fed3ff6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 23 Aug 2021 16:59:22 -0700
Subject: [PATCH 356/767] [Tests] test on TS parser v2, v3, and v4

---
 .github/workflows/node-4+.yml |  5 +++++
 package.json                  |  2 +-
 tests/dep-time-travel.sh      | 15 ++++++++-------
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 6456762fce..b13e3b88cf 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -33,6 +33,11 @@ jobs:
           - 3
           - 2
         include:
+          - node-version: 'lts/*'
+            eslint: 7
+            ts-parser: 3
+            env:
+              TS_PARSER: 3
           - node-version: 'lts/*'
             eslint: 7
             ts-parser: 2
diff --git a/package.json b/package.json
index d1a6bd5e01..9369f8875d 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,7 @@
   "devDependencies": {
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
-    "@typescript-eslint/parser": "^2.23.0 || ^3.3.0",
+    "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3",
     "array.prototype.flatmap": "^1.2.4",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index ad00568e4c..d6f5aedfc2 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -8,10 +8,16 @@ export NPM_CONFIG_LEGACY_PEER_DEPS=true
 
 npm install --no-save "eslint@${ESLINT_VERSION}" --ignore-scripts
 
-# completely remove the new TypeScript parser for ESLint < v5
-if [[ "$ESLINT_VERSION" -lt "5" ]]; then
+
+
+if [[ -n "$TS_PARSER" ]]; then # if TS parser is manually set, always use it
+  echo "Downgrading @typescript-eslint/parser..."
+  npm i --no-save "@typescript-eslint/parser@${TS_PARSER}"
+elif [[ "$ESLINT_VERSION" -lt "5" ]]; then # completely remove the new TypeScript parser for ESLint < v5
   echo "Removing @typescript-eslint/parser..."
   npm uninstall --no-save @typescript-eslint/parser
+elif [[ "$TRAVIS_NODE_VERSION" -lt "10" ]]; then # TS parser 3 requires node 10+
+  npm i --no-save "@typescript-eslint/parser@3"
 fi
 
 # use these alternate TypeScript dependencies for ESLint < v4
@@ -28,8 +34,3 @@ if [[ "$TRAVIS_NODE_VERSION" -lt "8" ]]; then
   echo "Downgrading eslint-import-resolver-typescript..."
   npm i --no-save eslint-import-resolver-typescript@1.0.2
 fi
-
-if [[ -n "$TS_PARSER" ]]; then
-  echo "Downgrading @typescript-eslint/parser..."
-  npm i --no-save @typescript-eslint/parser@2
-fi

From 75170fabd5bc34d6d2a57a738134a1eb1cf7cf8b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 24 Aug 2021 13:35:51 -0700
Subject: [PATCH 357/767] [Tests] `named`: add passing tests

Related to #2199
---
 tests/files/export-star-3/b.ts |   1 +
 tests/files/export-star-3/c.ts |   0
 tests/src/rules/named.js       | 160 +++++++++++++++------------------
 3 files changed, 74 insertions(+), 87 deletions(-)
 create mode 100644 tests/files/export-star-3/b.ts
 create mode 100644 tests/files/export-star-3/c.ts

diff --git a/tests/files/export-star-3/b.ts b/tests/files/export-star-3/b.ts
new file mode 100644
index 0000000000..5a91d016fb
--- /dev/null
+++ b/tests/files/export-star-3/b.ts
@@ -0,0 +1 @@
+export * as b from './c';
diff --git a/tests/files/export-star-3/c.ts b/tests/files/export-star-3/c.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 0d8c0b7edf..56babfa509 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -352,105 +352,91 @@ ruleTester.run('named (export *)', rule, {
 
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
+    const settings = {
+      'import/parsers': { [parser]: ['.ts'] },
+      'import/resolver': { 'eslint-import-resolver-typescript': true },
+    };
+
+    const valid = [];
+    const invalid = [
+      test({
+        code: `import {a} from './export-star-3/b';`,
+        filename: testFilePath('./export-star-3/a.js'),
+        parser: parser,
+        settings: settings,
+      }),
+    ];
+
     [
       'typescript',
       'typescript-declare',
       'typescript-export-assign-namespace',
       'typescript-export-assign-namespace-merged',
     ].forEach((source) => {
-      ruleTester.run(`named`, rule, {
-        valid: [
-          test({
-            code: `import { MyType } from "./${source}"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import { Foo } from "./${source}"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import { Bar } from "./${source}"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import { getFoo } from "./${source}"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `import { MyEnum } from "./${source}"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `
+      valid.push(
+        test({
+          code: `import { MyType } from "./${source}"`,
+          parser: parser,
+          settings: settings,
+        }),
+        test({
+          code: `import { Foo } from "./${source}"`,
+          parser: parser,
+          settings: settings,
+        }),
+        test({
+          code: `import { Bar } from "./${source}"`,
+          parser: parser,
+          settings: settings,
+        }),
+        test({
+          code: `import { getFoo } from "./${source}"`,
+          parser: parser,
+          settings: settings,
+        }),
+        test({
+          code: `import { MyEnum } from "./${source}"`,
+          parser: parser,
+          settings: settings,
+        }),
+        test({
+          code: `
               import { MyModule } from "./${source}"
               MyModule.ModuleFunction()
             `,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-          test({
-            code: `
+          parser: parser,
+          settings: settings,
+        }),
+        test({
+          code: `
               import { MyNamespace } from "./${source}"
               MyNamespace.NSModule.NSModuleFunction()
             `,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-          }),
-        ],
-
-        invalid: [
-          test({
-            code: `import { MissingType } from "./${source}"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-            errors: [{
-              message: `MissingType not found in './${source}'`,
-              type: 'Identifier',
-            }],
-          }),
-          test({
-            code: `import { NotExported } from "./${source}"`,
-            parser: parser,
-            settings: {
-              'import/parsers': { [parser]: ['.ts'] },
-              'import/resolver': { 'eslint-import-resolver-typescript': true },
-            },
-            errors: [{
-              message: `NotExported not found in './${source}'`,
-              type: 'Identifier',
-            }],
-          }),
-        ],
-      });
+          parser: parser,
+          settings: settings,
+        }),
+      );
+
+      invalid.push(
+        test({
+          code: `import { MissingType } from "./${source}"`,
+          parser: parser,
+          settings: settings,
+          errors: [{
+            message: `MissingType not found in './${source}'`,
+            type: 'Identifier',
+          }],
+        }),
+        test({
+          code: `import { NotExported } from "./${source}"`,
+          parser: parser,
+          settings: settings,
+          errors: [{
+            message: `NotExported not found in './${source}'`,
+            type: 'Identifier',
+          }],
+        }),
+      );
     });
   });
 });

From 51d39732a40a6cee00ecb5d5badfa3dbc74bd6fb Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 24 Aug 2021 14:50:19 -0700
Subject: [PATCH 358/767] [Deps] unpin `tsconfig-paths`

https://github.com/dividab/tsconfig-paths/issues/171 fixed in https://github.com/dividab/tsconfig-paths/pull/173
---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 9369f8875d..6523398cdf 100644
--- a/package.json
+++ b/package.json
@@ -114,6 +114,6 @@
     "pkg-up": "^2.0.0",
     "read-pkg-up": "^3.0.0",
     "resolve": "^1.20.0",
-    "tsconfig-paths": "~3.9.0"
+    "tsconfig-paths": "^3.11.0"
   }
 }

From 033ba646c63b31feac2896d5c311a37aecd88405 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 24 Aug 2021 15:30:04 -0700
Subject: [PATCH 359/767] [Fix] `named`, `namespace`: properly handle
 ExportAllDeclarations

Fixes #2199
---
 CHANGELOG.md     | 4 ++++
 src/ExportMap.js | 6 +++---
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 59bcfb4be3..b1bbaffd27 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixes
+- [`named`], [`namespace`]: properly handle ExportAllDeclarations ([#2199], thanks [@ljharb])
+
 ## [2.24.1] - 2021-08-19
 
 ### Fixed
@@ -1152,6 +1155,7 @@ for info on changes for earlier releases.
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
 [#2201]: https://github.com/import-js/eslint-plugin-import/issues/2201
+[#2199]: https://github.com/import-js/eslint-plugin-import/issues/2199
 [#2161]: https://github.com/import-js/eslint-plugin-import/issues/2161
 [#2118]: https://github.com/import-js/eslint-plugin-import/issues/2118
 [#2067]: https://github.com/import-js/eslint-plugin-import/issues/2067
diff --git a/src/ExportMap.js b/src/ExportMap.js
index f49841835b..5bda83dd35 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -421,7 +421,7 @@ ExportMap.parse = function (path, content, context) {
 
     switch (s.type) {
     case 'ExportDefaultSpecifier':
-      if (!n.source) return;
+      if (!nsource) return;
       local = 'default';
       break;
     case 'ExportNamespaceSpecifier':
@@ -430,8 +430,8 @@ ExportMap.parse = function (path, content, context) {
       }));
       return;
     case 'ExportAllDeclaration':
-      local = s.exported ? s.exported.name : s.local.name;
-      break;
+      m.namespace.set(s.exported.name, addNamespace(exportMeta, s.source.value));
+      return;
     case 'ExportSpecifier':
       if (!n.source) {
         m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local));

From 924b435072a75529a56e678f2382b31821633b0b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 24 Aug 2021 15:40:52 -0700
Subject: [PATCH 360/767] Bump to v2.24.2

---
 CHANGELOG.md | 9 ++++++---
 package.json | 2 +-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1bbaffd27..355985a816 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
-### Fixes
+## [2.24.2] - 2021-08-24
+
+### Fixed
 - [`named`], [`namespace`]: properly handle ExportAllDeclarations ([#2199], thanks [@ljharb])
 
 ## [2.24.1] - 2021-08-19
@@ -1265,8 +1267,9 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.1...HEAD
-[2.24.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.0...v2.24.1
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.2...HEAD
+[2.24.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.1...v2.24.2
+[2.24.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.0...v2.24.1
 [2.24.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.4...v2.24.0
 [2.23.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.3...v2.23.4
 [2.23.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.2...v2.23.3
diff --git a/package.json b/package.json
index 6523398cdf..dd7cbcb350 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.24.1",
+  "version": "2.24.2",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 4a9be638407b8a01c5f70b077a407fc36805cdd7 Mon Sep 17 00:00:00 2001
From: yosuke ota <otameshiyo23@gmail.com>
Date: Mon, 16 Aug 2021 12:48:15 +0900
Subject: [PATCH 361/767] [Tests] use ESLint class in `cli` test

---
 tests/src/cli.js | 163 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 111 insertions(+), 52 deletions(-)

diff --git a/tests/src/cli.js b/tests/src/cli.js
index b0285593b1..9867e04985 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -4,85 +4,144 @@
 import path from 'path';
 
 import { expect } from 'chai';
-import { CLIEngine } from 'eslint';
+import { CLIEngine, ESLint } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import * as importPlugin from '../../src/index';
 
 describe('CLI regression tests', function () {
   describe('issue #210', function () {
+    let eslint;
     let cli;
     before(function () {
-      cli = new CLIEngine({
-        useEslintrc: false,
-        configFile: './tests/files/issue210.config.js',
-        rulePaths: ['./src/rules'],
-        rules: {
-          'named': 2,
-        },
-      });
-      cli.addPlugin('eslint-plugin-import', importPlugin);
+      if (ESLint) {
+        eslint = new ESLint({
+          useEslintrc: false,
+          overrideConfigFile: './tests/files/issue210.config.js',
+          rulePaths: ['./src/rules'],
+          overrideConfig: {
+            rules: {
+              'named': 2,
+            },
+          },
+          plugins: { 'eslint-plugin-import': importPlugin },
+        });
+      } else {
+        cli = new CLIEngine({
+          useEslintrc: false,
+          configFile: './tests/files/issue210.config.js',
+          rulePaths: ['./src/rules'],
+          rules: {
+            'named': 2,
+          },
+        });
+        cli.addPlugin('eslint-plugin-import', importPlugin);
+      }
     });
     it("doesn't throw an error on gratuitous, erroneous self-reference", function () {
-      expect(() => cli.executeOnFiles(['./tests/files/issue210.js'])).not.to.throw();
+      if (eslint) {
+        return eslint.lintFiles(['./tests/files/issue210.js'])
+          .catch(() => expect.fail());
+      } else {
+        expect(() => cli.executeOnFiles(['./tests/files/issue210.js'])).not.to.throw();
+      }
     });
   });
 
   describe('issue #1645', function () {
+    let eslint;
     let cli;
     beforeEach(function () {
       if (semver.satisfies(eslintPkg.version, '< 6')) {
         this.skip();
       } else {
-        cli = new CLIEngine({
-          useEslintrc: false,
-          configFile: './tests/files/just-json-files/.eslintrc.json',
-          rulePaths: ['./src/rules'],
-          ignore: false,
-        });
-        cli.addPlugin('eslint-plugin-import', importPlugin);
+        if (ESLint) {
+          eslint = new ESLint({
+            useEslintrc: false,
+            overrideConfigFile: './tests/files/just-json-files/.eslintrc.json',
+            rulePaths: ['./src/rules'],
+            ignore: false,
+            plugins: { 'eslint-plugin-import': importPlugin },
+          });
+        } else {
+          cli = new CLIEngine({
+            useEslintrc: false,
+            configFile: './tests/files/just-json-files/.eslintrc.json',
+            rulePaths: ['./src/rules'],
+            ignore: false,
+          });
+          cli.addPlugin('eslint-plugin-import', importPlugin);
+        }
       }
     });
 
     it('throws an error on invalid JSON', () => {
       const invalidJSON = './tests/files/just-json-files/invalid.json';
-      const results = cli.executeOnFiles([invalidJSON]);
-      expect(results).to.eql({
-        results: [
-          {
-            filePath: path.resolve(invalidJSON),
-            messages: [
+      if (eslint) {
+        return eslint.lintFiles([invalidJSON]).then(results => {
+          expect(results).to.eql(
+            [
               {
-                column: 2,
-                endColumn: 3,
-                endLine: 1,
-                line: 1,
-                message: 'Expected a JSON object, array or literal.',
-                nodeType: results.results[0].messages[0].nodeType, // we don't care about this one
-                ruleId: 'json/*',
-                severity: 2,
-                source: results.results[0].messages[0].source, // NewLine-characters might differ depending on git-settings
+                filePath: path.resolve(invalidJSON),
+                messages: [
+                  {
+                    column: 2,
+                    endColumn: 3,
+                    endLine: 1,
+                    line: 1,
+                    message: 'Expected a JSON object, array or literal.',
+                    nodeType: results[0].messages[0].nodeType, // we don't care about this one
+                    ruleId: 'json/*',
+                    severity: 2,
+                    source: results[0].messages[0].source, // NewLine-characters might differ depending on git-settings
+                  },
+                ],
+                errorCount: 1,
+                ...(semver.satisfies(eslintPkg.version, '>= 7.32 || ^8.0.0-0') && {
+                  fatalErrorCount: 0,
+                }),
+                warningCount: 0,
+                fixableErrorCount: 0,
+                fixableWarningCount: 0,
+                source: results[0].source, // NewLine-characters might differ depending on git-settings
+                usedDeprecatedRules: results[0].usedDeprecatedRules, // we don't care about this one
               },
             ],
-            errorCount: 1,
-            ...(semver.satisfies(eslintPkg.version, '>= 7.32') && {
-              fatalErrorCount: 0,
-            }),
-            warningCount: 0,
-            fixableErrorCount: 0,
-            fixableWarningCount: 0,
-            source: results.results[0].source, // NewLine-characters might differ depending on git-settings
-          },
-        ],
-        ...(semver.satisfies(eslintPkg.version, '>= 7.32') && {
-          fatalErrorCount: 0,
-        }),
-        errorCount: 1,
-        warningCount: 0,
-        fixableErrorCount: 0,
-        fixableWarningCount: 0,
-        usedDeprecatedRules: results.usedDeprecatedRules, // we don't care about this one
-      });
+          );
+        });
+      } else {
+        const results = cli.executeOnFiles([invalidJSON]);
+        expect(results).to.eql({
+          results: [
+            {
+              filePath: path.resolve(invalidJSON),
+              messages: [
+                {
+                  column: 2,
+                  endColumn: 3,
+                  endLine: 1,
+                  line: 1,
+                  message: 'Expected a JSON object, array or literal.',
+                  nodeType: results.results[0].messages[0].nodeType, // we don't care about this one
+                  ruleId: 'json/*',
+                  severity: 2,
+                  source: results.results[0].messages[0].source, // NewLine-characters might differ depending on git-settings
+                },
+              ],
+              errorCount: 1,
+              warningCount: 0,
+              fixableErrorCount: 0,
+              fixableWarningCount: 0,
+              source: results.results[0].source, // NewLine-characters might differ depending on git-settings
+            },
+          ],
+          errorCount: 1,
+          warningCount: 0,
+          fixableErrorCount: 0,
+          fixableWarningCount: 0,
+          usedDeprecatedRules: results.usedDeprecatedRules, // we don't care about this one
+        });
+      }
     });
   });
 });

From 49ada27a495899d0247bc9661ed0f055e970fe3b Mon Sep 17 00:00:00 2001
From: coderaiser <mnemonic.enemy@gmail.com>
Date: Mon, 16 Aug 2021 16:52:28 +0300
Subject: [PATCH 362/767] [New] `no-unused-modules`: add eslint v8 support

 - https://eslint.org/docs/8.0.0/user-guide/migrating-to-8.0.0
---
 CHANGELOG.md                   |  4 +++
 src/rules/no-unused-modules.js | 66 +++++++++++++++++++---------------
 2 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 355985a816..cc7dca9593 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Added
+- [`no-unused-modules`]: add eslint v8 support ([#2194], thanks [@coderaiser])
+
 ## [2.24.2] - 2021-08-24
 
 ### Fixed
@@ -901,6 +904,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2196]: https://github.com/import-js/eslint-plugin-import/pull/2196
+[#2194]: https://github.com/import-js/eslint-plugin-import/pull/2194
 [#2184]: https://github.com/import-js/eslint-plugin-import/pull/2184
 [#2179]: https://github.com/import-js/eslint-plugin-import/pull/2179
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index d49674e7e5..dd258e94e8 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -13,45 +13,55 @@ import readPkgUp from 'read-pkg-up';
 import values from 'object.values';
 import includes from 'array-includes';
 
-// eslint/lib/util/glob-util has been moved to eslint/lib/util/glob-utils with version 5.3
-// and has been moved to eslint/lib/cli-engine/file-enumerator in version 6
+let FileEnumerator;
 let listFilesToProcess;
+
 try {
-  const FileEnumerator = require('eslint/lib/cli-engine/file-enumerator').FileEnumerator;
+  ({ FileEnumerator } = require('eslint/use-at-your-own-risk'));
+} catch (e) {
+  try {
+    // has been moved to eslint/lib/cli-engine/file-enumerator in version 6
+    ({ FileEnumerator } = require('eslint/lib/cli-engine/file-enumerator'));
+  } catch (e) {
+    try {
+      // eslint/lib/util/glob-util has been moved to eslint/lib/util/glob-utils with version 5.3
+      const { listFilesToProcess: originalListFilesToProcess } = require('eslint/lib/util/glob-utils');
+
+      // Prevent passing invalid options (extensions array) to old versions of the function.
+      // https://github.com/eslint/eslint/blob/v5.16.0/lib/util/glob-utils.js#L178-L280
+      // https://github.com/eslint/eslint/blob/v5.2.0/lib/util/glob-util.js#L174-L269
+      listFilesToProcess = function (src, extensions) {
+        return originalListFilesToProcess(src, {
+          extensions: extensions,
+        });
+      };
+    } catch (e) {
+      const { listFilesToProcess: originalListFilesToProcess } = require('eslint/lib/util/glob-util');
+      
+      listFilesToProcess = function (src, extensions) {
+        const patterns = src.reduce((carry, pattern) => {
+          return carry.concat(extensions.map((extension) => {
+            return /\*\*|\*\./.test(pattern) ? pattern : `${pattern}/**/*${extension}`;
+          }));
+        }, src.slice());
+    
+        return originalListFilesToProcess(patterns);
+      };
+    }
+  }
+}
+
+if (FileEnumerator) {
   listFilesToProcess = function (src, extensions) {
     const e = new FileEnumerator({
       extensions: extensions,
     });
+
     return Array.from(e.iterateFiles(src), ({ filePath, ignored }) => ({
       ignored,
       filename: filePath,
     }));
   };
-} catch (e1) {
-  // Prevent passing invalid options (extensions array) to old versions of the function.
-  // https://github.com/eslint/eslint/blob/v5.16.0/lib/util/glob-utils.js#L178-L280
-  // https://github.com/eslint/eslint/blob/v5.2.0/lib/util/glob-util.js#L174-L269
-  let originalListFilesToProcess;
-  try {
-    originalListFilesToProcess = require('eslint/lib/util/glob-utils').listFilesToProcess;
-    listFilesToProcess = function (src, extensions) {
-      return originalListFilesToProcess(src, {
-        extensions: extensions,
-      });
-    };
-  } catch (e2) {
-    originalListFilesToProcess = require('eslint/lib/util/glob-util').listFilesToProcess;
-
-    listFilesToProcess = function (src, extensions) {
-      const patterns = src.reduce((carry, pattern) => {
-        return carry.concat(extensions.map((extension) => {
-          return /\*\*|\*\./.test(pattern) ? pattern : `${pattern}/**/*${extension}`;
-        }));
-      }, src.slice());
-
-      return originalListFilesToProcess(patterns);
-    };
-  }
 }
 
 const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration';

From 1359e247b2368f8bb6bc0fefc70fabf6bc49b075 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 27 Aug 2021 21:37:12 -0700
Subject: [PATCH 363/767] [eslint] enable `object-shorthand`,
 `space-before-function-paren`

---
 .eslintrc                                     | 10 +++
 resolvers/webpack/index.js                    |  8 +--
 resolvers/webpack/test/config.js              | 10 +--
 src/rules/default.js                          |  2 +-
 src/rules/dynamic-import-chunkname.js         |  2 +-
 src/rules/export.js                           |  2 +-
 src/rules/exports-last.js                     |  4 +-
 src/rules/extensions.js                       |  2 +-
 src/rules/first.js                            |  4 +-
 src/rules/named.js                            |  2 +-
 src/rules/newline-after-import.js             |  4 +-
 src/rules/no-absolute-path.js                 |  2 +-
 src/rules/no-amd.js                           |  2 +-
 src/rules/no-anonymous-default-export.js      |  2 +-
 src/rules/no-commonjs.js                      |  2 +-
 src/rules/no-cycle.js                         |  2 +-
 src/rules/no-deprecated.js                    |  2 +-
 src/rules/no-duplicates.js                    |  4 +-
 src/rules/no-dynamic-require.js               |  2 +-
 src/rules/no-extraneous-dependencies.js       |  2 +-
 src/rules/no-mutable-exports.js               |  2 +-
 src/rules/no-named-as-default-member.js       |  2 +-
 src/rules/no-named-as-default.js              |  2 +-
 src/rules/no-named-default.js                 |  2 +-
 src/rules/no-namespace.js                     |  2 +-
 src/rules/no-nodejs-modules.js                |  2 +-
 src/rules/no-self-import.js                   |  2 +-
 src/rules/no-unresolved.js                    |  2 +-
 src/rules/no-unused-modules.js                |  4 +-
 src/rules/no-webpack-loader-syntax.js         |  2 +-
 src/rules/order.js                            | 30 ++++-----
 src/rules/prefer-default-export.js            | 18 +++---
 src/rules/unambiguous.js                      |  4 +-
 tests/src/core/eslintParser.js                |  2 +-
 tests/src/core/getExports.js                  |  2 +-
 tests/src/core/importType.js                  | 50 +++++++--------
 tests/src/core/parse.js                       |  4 +-
 tests/src/core/parseStubParser.js             |  2 +-
 tests/src/core/resolve.js                     | 64 +++++++++----------
 tests/src/rules/default.js                    | 26 ++++----
 tests/src/rules/export.js                     |  4 +-
 tests/src/rules/max-dependencies.js           |  6 +-
 tests/src/rules/named.js                      | 40 ++++++------
 tests/src/rules/namespace.js                  |  8 +--
 tests/src/rules/newline-after-import.js       | 14 ++--
 tests/src/rules/no-deprecated.js              |  2 +-
 tests/src/rules/no-duplicates.js              |  2 +-
 tests/src/rules/no-extraneous-dependencies.js |  2 +-
 tests/src/rules/no-internal-modules.js        |  2 +-
 tests/src/rules/no-unused-modules.js          | 28 ++++----
 tests/src/rules/no-webpack-loader-syntax.js   |  2 +-
 tests/src/rules/prefer-default-export.js      |  2 +-
 tests/src/utils.js                            |  2 +-
 53 files changed, 209 insertions(+), 199 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 146ac91d7a..923b8fd088 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -31,6 +31,10 @@
         "no-shadow": 1,
         "no-var": 2,
         "object-curly-spacing": [2, "always"],
+        "object-shorthand": ["error", "always", {
+            "ignoreConstructors": false,
+            "avoidQuotes": true,
+        }],
         "one-var": [2, "never"],
         "prefer-const": 2,
         "quotes": [2, "single", {
@@ -38,6 +42,12 @@
             "avoidEscape": true,
         }],
         "semi": [2, "always"],
+        "space-before-function-paren": ["error", {
+            "anonymous": "always",
+            "named": "never",
+            "asyncArrow": "always",
+        }],
+  
         "eslint-plugin/consistent-output": [
             "error",
             "always",
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index c7a3fbcae0..3411eb75e5 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -163,7 +163,7 @@ exports.resolve = function (source, file, settings) {
 const MAX_CACHE = 10;
 const _cache = [];
 function getResolveSync(configPath, webpackConfig, cwd) {
-  const cacheKey = { configPath: configPath, webpackConfig: webpackConfig };
+  const cacheKey = { configPath, webpackConfig };
   let cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
   if (!cached) {
     cached = {
@@ -265,7 +265,7 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
   resolver.apply(
     resolveConfig.packageAlias
       ? new DirectoryDescriptionFileFieldAliasPlugin('package.json', resolveConfig.packageAlias)
-      : function() {},
+      : function () {},
     new ModuleAliasPlugin(resolveConfig.alias || {}),
     makeRootPlugin(ModulesInRootPlugin, 'module', resolveConfig.root),
     new ModulesInDirectoriesPlugin(
@@ -302,7 +302,7 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
 
   resolver.apply.apply(resolver, resolvePlugins);
 
-  return function() {
+  return function () {
     return resolver.resolveSync.apply(resolver, arguments);
   };
 }
@@ -391,7 +391,7 @@ function findExternal(source, externals, context, resolveSync) {
 }
 
 function findConfigPath(configPath, packageDir) {
-  const extensions = Object.keys(interpret.extensions).sort(function(a, b) {
+  const extensions = Object.keys(interpret.extensions).sort(function (a, b) {
     return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length;
   });
   let extension;
diff --git a/resolvers/webpack/test/config.js b/resolvers/webpack/test/config.js
index 069c2e3942..35f46e66c2 100644
--- a/resolvers/webpack/test/config.js
+++ b/resolvers/webpack/test/config.js
@@ -101,7 +101,7 @@ describe('config', function () {
       .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
   });
 
-  it('finds the config at option env when config is a function', function() {
+  it('finds the config at option env when config is a function', function () {
     const settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
       env: {
@@ -113,7 +113,7 @@ describe('config', function () {
       .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
   });
 
-  it('finds the config at option env when config is an array of functions', function() {
+  it('finds the config at option env when config is an array of functions', function () {
     const settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.multiple.js')),
       env: {
@@ -125,7 +125,7 @@ describe('config', function () {
       .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
   });
 
-  it('passes argv to config when it is a function', function() {
+  it('passes argv to config when it is a function', function () {
     const settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
       argv: {
@@ -137,7 +137,7 @@ describe('config', function () {
       .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'));
   });
 
-  it('passes a default empty argv object to config when it is a function', function() {
+  it('passes a default empty argv object to config when it is a function', function () {
     const settings = {
       config: require(path.join(__dirname, './files/webpack.function.config.js')),
       argv: undefined,
@@ -146,7 +146,7 @@ describe('config', function () {
     expect(function () { resolve('baz', file, settings); }).to.not.throw(Error);
   });
 
-  it('prevents async config using', function() {
+  it('prevents async config using', function () {
     const settings = {
       config: require(path.join(__dirname, './files/webpack.config.async.js')),
     };
diff --git a/src/rules/default.js b/src/rules/default.js
index 797519a64c..b8277b4525 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -10,7 +10,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
 
     function checkDefault(specifierType, node) {
 
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 16cd85a4f8..859e9fea46 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -24,7 +24,7 @@ module.exports = {
     }],
   },
 
-  create: function (context) {
+  create(context) {
     const config = context.options[0];
     const { importFunctions = [] } = config || {};
     const { webpackChunknameFormat = '[0-9a-zA-Z-_/.]+' } = config || {};
diff --git a/src/rules/export.js b/src/rules/export.js
index 386211baaf..be75fa07f2 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -54,7 +54,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     const namespace = new Map([[rootProgram, new Map()]]);
 
     function addNamed(name, node, parent, isType) {
diff --git a/src/rules/exports-last.js b/src/rules/exports-last.js
index ea044f32b6..e89aa7eefe 100644
--- a/src/rules/exports-last.js
+++ b/src/rules/exports-last.js
@@ -15,9 +15,9 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     return {
-      Program: function ({ body }) {
+      Program({ body }) {
         const lastNonExportStatementIndex = body.reduce(function findLastIndex(acc, item, index) {
           if (isNonExportStatement(item)) {
             return index;
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 921b981e0e..e116d2f866 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -103,7 +103,7 @@ module.exports = {
     },
   },
 
-  create: function (context) {
+  create(context) {
 
     const props = buildProperties(context);
 
diff --git a/src/rules/first.js b/src/rules/first.js
index 93e9fc5536..eb613d330b 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -21,8 +21,8 @@ module.exports = {
     ],
   },
 
-  create: function (context) {
-    function isPossibleDirective (node) {
+  create(context) {
+    function isPossibleDirective(node) {
       return node.type === 'ExpressionStatement' &&
         node.expression.type === 'Literal' &&
         typeof node.expression.value === 'string';
diff --git a/src/rules/named.js b/src/rules/named.js
index 2770d51fa2..24e6bc0ac5 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -21,7 +21,7 @@ module.exports = {
     ],
   },
 
-  create: function (context) {
+  create(context) {
     const options = context.options[0] || {};
 
     function checkSpecifiers(key, type, node) {
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index cf5dce831e..1b946b35ad 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -72,7 +72,7 @@ module.exports = {
       },
     ],
   },
-  create: function (context) {
+  create(context) {
     let level = 0;
     const requireCalls = [];
 
@@ -138,7 +138,7 @@ after ${type} statement not followed by another ${type}.`,
     return {
       ImportDeclaration: checkImport,
       TSImportEqualsDeclaration: checkImport,
-      CallExpression: function(node) {
+      CallExpression(node) {
         if (isStaticRequire(node) && level === 0) {
           requireCalls.push(node);
         }
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index cc81c5c4be..4111fd7e67 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -11,7 +11,7 @@ module.exports = {
     schema: [ makeOptionsSchema() ],
   },
 
-  create: function (context) {
+  create(context) {
     function reportIfAbsolute(source) {
       if (typeof source.value === 'string' && isAbsolute(source.value)) {
         context.report(source, 'Do not import modules using an absolute path');
diff --git a/src/rules/no-amd.js b/src/rules/no-amd.js
index 7a0771bd57..187273589c 100644
--- a/src/rules/no-amd.js
+++ b/src/rules/no-amd.js
@@ -18,7 +18,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     return {
       'CallExpression': function (node) {
         if (context.getScope().type !== 'module') return;
diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js
index 8ea3365861..f1f495ca38 100644
--- a/src/rules/no-anonymous-default-export.js
+++ b/src/rules/no-anonymous-default-export.js
@@ -86,7 +86,7 @@ module.exports = {
     ],
   },
 
-  create: function (context) {
+  create(context) {
     const options = Object.assign({}, defaults, context.options[0]);
 
     return {
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index 98f759cbc2..9e157f46db 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -88,7 +88,7 @@ module.exports = {
     },
   },
 
-  create: function (context) {
+  create(context) {
     const options = normalizeLegacyOptions(context.options);
 
     return {
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index ec4cfeae9a..dda5a679d2 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -36,7 +36,7 @@ module.exports = {
     })],
   },
 
-  create: function (context) {
+  create(context) {
     const myPath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
     if (myPath === '<text>') return {}; // can't cycle-check a non-file
 
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index 628759bd42..4913d389b5 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -21,7 +21,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     const deprecated = new Map();
     const namespaces = new Map();
 
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 6e03fcaef0..c887b39e7a 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -261,7 +261,7 @@ module.exports = {
     ],
   },
 
-  create: function (context) {
+  create(context) {
     // Prepare the resolver from options.
     const considerQueryStringOption = context.options[0] &&
       context.options[0]['considerQueryString'];
@@ -300,7 +300,7 @@ module.exports = {
         }
       },
 
-      'Program:exit'() {
+      'Program:exit': function () {
         checkImports(imported, context);
         checkImports(nsImported, context);
         checkImports(defaultTypesImported, context);
diff --git a/src/rules/no-dynamic-require.js b/src/rules/no-dynamic-require.js
index f8900088df..8267fd26e9 100644
--- a/src/rules/no-dynamic-require.js
+++ b/src/rules/no-dynamic-require.js
@@ -38,7 +38,7 @@ module.exports = {
     ],
   },
 
-  create: function (context) {
+  create(context) {
     const options = context.options[0] || {};
 
     return {
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 9403931f53..8d2e294ccb 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -252,7 +252,7 @@ module.exports = {
     ],
   },
 
-  create: function (context) {
+  create(context) {
     const options = context.options[0] || {};
     const filename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
     const deps = getDependencies(context, options.packageDir) || extractDepFields({});
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index a1635bb7ae..c506c997cc 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -9,7 +9,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     function checkDeclaration(node) {
       const { kind } = node;
       if (kind === 'var' || kind === 'let') {
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index 09bb5e34a3..ef2000e229 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -21,7 +21,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function(context) {
+  create(context) {
 
     const fileImports = new Map();
     const allPropertyLookups = new Map();
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index 7313e61268..7c1ef0e04c 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -11,7 +11,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     function checkDefault(nameKey, defaultSpecifier) {
       // #566: default is a valid specifier
       if (defaultSpecifier[nameKey].name === 'default') return;
diff --git a/src/rules/no-named-default.js b/src/rules/no-named-default.js
index d1c15d62e0..116c89cf57 100644
--- a/src/rules/no-named-default.js
+++ b/src/rules/no-named-default.js
@@ -9,7 +9,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     return {
       'ImportDeclaration': function (node) {
         node.specifiers.forEach(function (im) {
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index 472b93dd09..fb3d76052a 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -32,7 +32,7 @@ module.exports = {
     }],
   },
 
-  create: function (context) {
+  create(context) {
     const firstOption = context.options[0] || {};
     const ignoreGlobs = firstOption.ignore;
 
diff --git a/src/rules/no-nodejs-modules.js b/src/rules/no-nodejs-modules.js
index cbfb384d32..1e3207d208 100644
--- a/src/rules/no-nodejs-modules.js
+++ b/src/rules/no-nodejs-modules.js
@@ -31,7 +31,7 @@ module.exports = {
     ],
   },
 
-  create: function (context) {
+  create(context) {
     const options = context.options[0] || {};
     const allowed = options.allow || [];
 
diff --git a/src/rules/no-self-import.js b/src/rules/no-self-import.js
index 58c393b662..a5f464b242 100644
--- a/src/rules/no-self-import.js
+++ b/src/rules/no-self-import.js
@@ -30,7 +30,7 @@ module.exports = {
 
     schema: [],
   },
-  create: function (context) {
+  create(context) {
     return moduleVisitor((source, node) => {
       isImportingSelf(context, node, source.value);
     }, { commonjs: true });
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index 719bbded9d..236692b6e1 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -22,7 +22,7 @@ module.exports = {
     ],
   },
 
-  create: function (context) {
+  create(context) {
     function checkSourceValue(source) {
       const shouldCheckCase = !CASE_SENSITIVE_FS
         && (!context.options[0] || context.options[0].caseSensitive !== false);
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index dd258e94e8..ae6646f875 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -32,7 +32,7 @@ try {
       // https://github.com/eslint/eslint/blob/v5.2.0/lib/util/glob-util.js#L174-L269
       listFilesToProcess = function (src, extensions) {
         return originalListFilesToProcess(src, {
-          extensions: extensions,
+          extensions,
         });
       };
     } catch (e) {
@@ -54,7 +54,7 @@ try {
 if (FileEnumerator) {
   listFilesToProcess = function (src, extensions) {
     const e = new FileEnumerator({
-      extensions: extensions,
+      extensions,
     });
 
     return Array.from(e.iterateFiles(src), ({ filePath, ignored }) => ({
diff --git a/src/rules/no-webpack-loader-syntax.js b/src/rules/no-webpack-loader-syntax.js
index b3228e0d28..2f49ad6c6a 100644
--- a/src/rules/no-webpack-loader-syntax.js
+++ b/src/rules/no-webpack-loader-syntax.js
@@ -18,7 +18,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     return moduleVisitor((source, node) => {
       reportIfNonStandard(context, node, source.value);
     }, { commonjs: true });
diff --git a/src/rules/order.js b/src/rules/order.js
index 857a46e3d0..2f4ef08b70 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -196,7 +196,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
   if (order === 'before') {
     context.report({
       node: secondNode.node,
-      message: message,
+      message,
       fix: canFix && (fixer =>
         fixer.replaceTextRange(
           [firstRootStart, secondRootEnd],
@@ -206,7 +206,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
   } else if (order === 'after') {
     context.report({
       node: secondNode.node,
-      message: message,
+      message,
       fix: canFix && (fixer =>
         fixer.replaceTextRange(
           [secondRootStart, firstRootEnd],
@@ -259,7 +259,7 @@ function getSorter(ascending) {
 }
 
 function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
-  const groupedByRanks = imported.reduce(function(acc, importedItem) {
+  const groupedByRanks = imported.reduce(function (acc, importedItem) {
     if (!Array.isArray(acc[importedItem.rank])) {
       acc[importedItem.rank] = [];
     }
@@ -275,14 +275,14 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
     : (a, b) => sorterFn(a.value, b.value);
 
   // sort imports locally within their group
-  groupRanks.forEach(function(groupRank) {
+  groupRanks.forEach(function (groupRank) {
     groupedByRanks[groupRank].sort(comparator);
   });
 
   // assign globally unique rank to each import
   let newRank = 0;
-  const alphabetizedRanks = groupRanks.sort().reduce(function(acc, groupRank) {
-    groupedByRanks[groupRank].forEach(function(importedItem) {
+  const alphabetizedRanks = groupRanks.sort().reduce(function (acc, groupRank) {
+    groupedByRanks[groupRank].forEach(function (importedItem) {
       acc[`${importedItem.value}|${importedItem.node.importKind}`] = parseInt(groupRank, 10) + newRank;
       newRank += 1;
     });
@@ -290,7 +290,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
   }, {});
 
   // mutate the original group-rank with alphabetized-rank
-  imported.forEach(function(importedItem) {
+  imported.forEach(function (importedItem) {
     importedItem.rank = alphabetizedRanks[`${importedItem.value}|${importedItem.node.importKind}`];
   });
 }
@@ -359,11 +359,11 @@ const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling'
 // Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
 // Will throw an error if it contains a type that does not exist, or has a duplicate
 function convertGroupsToRanks(groups) {
-  const rankObject = groups.reduce(function(res, group, index) {
+  const rankObject = groups.reduce(function (res, group, index) {
     if (typeof group === 'string') {
       group = [group];
     }
-    group.forEach(function(groupItem) {
+    group.forEach(function (groupItem) {
       if (types.indexOf(groupItem) === -1) {
         throw new Error('Incorrect configuration of the rule: Unknown type `' +
           JSON.stringify(groupItem) + '`');
@@ -376,11 +376,11 @@ function convertGroupsToRanks(groups) {
     return res;
   }, {});
 
-  const omittedTypes = types.filter(function(type) {
+  const omittedTypes = types.filter(function (type) {
     return rankObject[type] === undefined;
   });
 
-  const ranks = omittedTypes.reduce(function(res, type) {
+  const ranks = omittedTypes.reduce(function (res, type) {
     res[type] = groups.length;
     return res;
   }, rankObject);
@@ -457,7 +457,7 @@ function removeNewLineAfterImport(context, currentImport, previousImport) {
   return undefined;
 }
 
-function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
+function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports) {
   const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
     const linesBetweenImports = context.getSourceCode().lines.slice(
       previousImport.node.loc.end.line,
@@ -468,7 +468,7 @@ function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
   };
   let previousImport = imported[0];
 
-  imported.slice(1).forEach(function(currentImport) {
+  imported.slice(1).forEach(function (currentImport) {
     const emptyLinesBetween = getNumberOfEmptyLinesBetween(currentImport, previousImport);
 
     if (newlinesBetweenImports === 'always'
@@ -581,7 +581,7 @@ module.exports = {
     ],
   },
 
-  create: function importOrderRule (context) {
+  create: function importOrderRule(context) {
     const options = context.options[0] || {};
     const newlinesBetweenImports = options['newlines-between'] || 'ignore';
     const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external', 'object']);
@@ -600,7 +600,7 @@ module.exports = {
     } catch (error) {
       // Malformed configuration
       return {
-        Program: function(node) {
+        Program(node) {
           context.report(node, error.message);
         },
       };
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 3cd2224cdf..a8c52bb1a0 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -11,7 +11,7 @@ module.exports = {
     schema: [],
   },
 
-  create: function(context) {
+  create(context) {
     let specifierExportCount = 0;
     let hasDefaultExport = false;
     let hasStarExport = false;
@@ -22,7 +22,7 @@ module.exports = {
       if (identifierOrPattern && identifierOrPattern.type === 'ObjectPattern') {
         // recursively capture
         identifierOrPattern.properties
-          .forEach(function(property) {
+          .forEach(function (property) {
             captureDeclaration(property.value);
           });
       } else if (identifierOrPattern && identifierOrPattern.type === 'ArrayPattern') {
@@ -35,11 +35,11 @@ module.exports = {
     }
 
     return {
-      'ExportDefaultSpecifier': function() {
+      'ExportDefaultSpecifier': function () {
         hasDefaultExport = true;
       },
 
-      'ExportSpecifier': function(node) {
+      'ExportSpecifier': function (node) {
         if (node.exported.name === 'default') {
           hasDefaultExport = true;
         } else {
@@ -48,7 +48,7 @@ module.exports = {
         }
       },
 
-      'ExportNamedDeclaration': function(node) {
+      'ExportNamedDeclaration': function (node) {
         // if there are specifiers, node.declaration should be null
         if (!node.declaration) return;
 
@@ -66,7 +66,7 @@ module.exports = {
         }
 
         if (node.declaration.declarations) {
-          node.declaration.declarations.forEach(function(declaration) {
+          node.declaration.declarations.forEach(function (declaration) {
             captureDeclaration(declaration.id);
           });
         } else {
@@ -77,15 +77,15 @@ module.exports = {
         namedExportNode = node;
       },
 
-      'ExportDefaultDeclaration': function() {
+      'ExportDefaultDeclaration': function () {
         hasDefaultExport = true;
       },
 
-      'ExportAllDeclaration': function() {
+      'ExportAllDeclaration': function () {
         hasStarExport = true;
       },
 
-      'Program:exit': function() {
+      'Program:exit': function () {
         if (specifierExportCount === 1 && !hasDefaultExport && !hasStarExport && !hasTypeExport) {
           context.report(namedExportNode, 'Prefer default export.');
         }
diff --git a/src/rules/unambiguous.js b/src/rules/unambiguous.js
index c0570b066e..576b3379ee 100644
--- a/src/rules/unambiguous.js
+++ b/src/rules/unambiguous.js
@@ -15,14 +15,14 @@ module.exports = {
     schema: [],
   },
 
-  create: function (context) {
+  create(context) {
     // ignore non-modules
     if (context.parserOptions.sourceType !== 'module') {
       return {};
     }
 
     return {
-      Program: function (ast) {
+      Program(ast) {
         if (!isModule(ast)) {
           context.report({
             node: ast,
diff --git a/tests/src/core/eslintParser.js b/tests/src/core/eslintParser.js
index 492b83ea4d..f53a394def 100644
--- a/tests/src/core/eslintParser.js
+++ b/tests/src/core/eslintParser.js
@@ -1,5 +1,5 @@
 module.exports = {
-  parseForESLint: function() {
+  parseForESLint() {
     return {
       ast: {},
     };
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 74c8d9ee93..2c9f70d5ba 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -13,7 +13,7 @@ import * as unambiguous from 'eslint-module-utils/unambiguous';
 describe('ExportMap', function () {
   const fakeContext = Object.assign(
     semver.satisfies(eslintPkg.version, '>= 7.28') ? {
-      getFilename: function () { throw new Error('Should call getPhysicalFilename() instead of getFilename()'); },
+      getFilename() { throw new Error('Should call getPhysicalFilename() instead of getFilename()'); },
       getPhysicalFilename: getFilename,
     } : {
       getFilename,
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 3a50002125..0dcd5266bb 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -9,18 +9,18 @@ describe('importType(name)', function () {
   const context = testContext();
   const pathToTestFiles = path.join(__dirname, '..', '..', 'files');
 
-  it("should return 'absolute' for paths starting with a /", function() {
+  it("should return 'absolute' for paths starting with a /", function () {
     expect(importType('/', context)).to.equal('absolute');
     expect(importType('/path', context)).to.equal('absolute');
     expect(importType('/some/path', context)).to.equal('absolute');
   });
 
-  it("should return 'builtin' for node.js modules", function() {
+  it("should return 'builtin' for node.js modules", function () {
     expect(importType('fs', context)).to.equal('builtin');
     expect(importType('path', context)).to.equal('builtin');
   });
 
-  it("should return 'external' for non-builtin modules without a relative path", function() {
+  it("should return 'external' for non-builtin modules without a relative path", function () {
     expect(importType('lodash', context)).to.equal('external');
     expect(importType('async', context)).to.equal('external');
     expect(importType('chalk', context)).to.equal('external');
@@ -29,7 +29,7 @@ describe('importType(name)', function () {
     expect(importType('lodash/fp', context)).to.equal('external');
   });
 
-  it("should return 'external' for scopes packages", function() {
+  it("should return 'external' for scopes packages", function () {
     expect(importType('@cycle/', context)).to.equal('external');
     expect(importType('@cycle/core', context)).to.equal('external');
     expect(importType('@cycle/dom', context)).to.equal('external');
@@ -38,7 +38,7 @@ describe('importType(name)', function () {
     expect(importType('@some-thing/something/some-directory/someModule.js', context)).to.equal('external');
   });
 
-  it("should return 'external' for external modules that redirect to its parent module using package.json", function() {
+  it("should return 'external' for external modules that redirect to its parent module using package.json", function () {
     expect(importType('eslint-import-test-order-redirect/module', context)).to.equal('external');
     expect(importType('@eslint/import-test-order-redirect-scoped/module', context)).to.equal('external');
   });
@@ -75,13 +75,13 @@ describe('importType(name)', function () {
     expect(importType('constants', pathContext)).to.equal('internal');
   });
 
-  it("should return 'parent' for internal modules that go through the parent", function() {
+  it("should return 'parent' for internal modules that go through the parent", function () {
     expect(importType('../foo', context)).to.equal('parent');
     expect(importType('../../foo', context)).to.equal('parent');
     expect(importType('../bar/foo', context)).to.equal('parent');
   });
 
-  it("should return 'sibling' for internal modules that are connected to one of the siblings", function() {
+  it("should return 'sibling' for internal modules that are connected to one of the siblings", function () {
     expect(importType('./foo', context)).to.equal('sibling');
     expect(importType('./foo/bar', context)).to.equal('sibling');
     expect(importType('./importType', context)).to.equal('sibling');
@@ -90,19 +90,19 @@ describe('importType(name)', function () {
     expect(importType('./importType/index.js', context)).to.equal('sibling');
   });
 
-  it("should return 'index' for sibling index file", function() {
+  it("should return 'index' for sibling index file", function () {
     expect(importType('.', context)).to.equal('index');
     expect(importType('./', context)).to.equal('index');
     expect(importType('./index', context)).to.equal('index');
     expect(importType('./index.js', context)).to.equal('index');
   });
 
-  it("should return 'unknown' for any unhandled cases", function() {
+  it("should return 'unknown' for any unhandled cases", function () {
     expect(importType('  /malformed', context)).to.equal('unknown');
     expect(importType('   foo', context)).to.equal('unknown');
   });
 
-  it("should return 'builtin' for additional core modules", function() {
+  it("should return 'builtin' for additional core modules", function () {
     // without extra config, should be marked external
     expect(importType('electron', context)).to.equal('external');
     expect(importType('@org/foobar', context)).to.equal('external');
@@ -114,7 +114,7 @@ describe('importType(name)', function () {
     expect(importType('@org/foobar', scopedContext)).to.equal('builtin');
   });
 
-  it("should return 'builtin' for resources inside additional core modules", function() {
+  it("should return 'builtin' for resources inside additional core modules", function () {
     const electronContext = testContext({ 'import/core-modules': ['electron'] });
     expect(importType('electron/some/path/to/resource.json', electronContext)).to.equal('builtin');
 
@@ -122,31 +122,31 @@ describe('importType(name)', function () {
     expect(importType('@org/foobar/some/path/to/resource.json', scopedContext)).to.equal('builtin');
   });
 
-  it("should return 'external' for module from 'node_modules' with default config", function() {
+  it("should return 'external' for module from 'node_modules' with default config", function () {
     expect(importType('resolve', context)).to.equal('external');
   });
 
-  it("should return 'internal' for module from 'node_modules' if 'node_modules' missed in 'external-module-folders'", function() {
+  it("should return 'internal' for module from 'node_modules' if 'node_modules' missed in 'external-module-folders'", function () {
     const foldersContext = testContext({ 'import/external-module-folders': [] });
     expect(importType('chai', foldersContext)).to.equal('internal');
   });
 
-  it("should return 'internal' for module from 'node_modules' if its name matched 'internal-regex'", function() {
+  it("should return 'internal' for module from 'node_modules' if its name matched 'internal-regex'", function () {
     const foldersContext = testContext({ 'import/internal-regex': '^@org' });
     expect(importType('@org/foobar', foldersContext)).to.equal('internal');
   });
 
-  it("should return 'external' for module from 'node_modules' if its name did not match 'internal-regex'", function() {
+  it("should return 'external' for module from 'node_modules' if its name did not match 'internal-regex'", function () {
     const foldersContext = testContext({ 'import/internal-regex': '^@bar' });
     expect(importType('@org/foobar', foldersContext)).to.equal('external');
   });
 
-  it("should return 'external' for module from 'node_modules' if 'node_modules' contained in 'external-module-folders'", function() {
+  it("should return 'external' for module from 'node_modules' if 'node_modules' contained in 'external-module-folders'", function () {
     const foldersContext = testContext({ 'import/external-module-folders': ['node_modules'] });
     expect(importType('resolve', foldersContext)).to.equal('external');
   });
 
-  it('returns "external" for a scoped symlinked module', function() {
+  it('returns "external" for a scoped symlinked module', function () {
     const foldersContext = testContext({
       'import/resolver': 'node',
       'import/external-module-folders': ['node_modules'],
@@ -157,7 +157,7 @@ describe('importType(name)', function () {
   // We're using Webpack resolver here since it resolves all symlinks, which means that
   // directory path will not contain node_modules/<package-name> but will point to the
   // actual directory inside 'files' instead
-  it('returns "external" for a scoped module from a symlinked directory which name is contained in "external-module-folders" (webpack resolver)', function() {
+  it('returns "external" for a scoped module from a symlinked directory which name is contained in "external-module-folders" (webpack resolver)', function () {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['symlinked-module'],
@@ -165,7 +165,7 @@ describe('importType(name)', function () {
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
   });
 
-  it('returns "internal" for a scoped module from a symlinked directory which incomplete name is contained in "external-module-folders" (webpack resolver)', function() {
+  it('returns "internal" for a scoped module from a symlinked directory which incomplete name is contained in "external-module-folders" (webpack resolver)', function () {
     const foldersContext_1 = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['symlinked-mod'],
@@ -179,7 +179,7 @@ describe('importType(name)', function () {
     expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal');
   });
 
-  it('returns "external" for a scoped module from a symlinked directory which partial path is contained in "external-module-folders" (webpack resolver)', function() {
+  it('returns "external" for a scoped module from a symlinked directory which partial path is contained in "external-module-folders" (webpack resolver)', function () {
     const originalFoldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': [],
@@ -193,7 +193,7 @@ describe('importType(name)', function () {
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
   });
 
-  it('returns "internal" for a scoped module from a symlinked directory which partial path w/ incomplete segment is contained in "external-module-folders" (webpack resolver)', function() {
+  it('returns "internal" for a scoped module from a symlinked directory which partial path w/ incomplete segment is contained in "external-module-folders" (webpack resolver)', function () {
     const foldersContext_1 = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['files/symlinked-mod'],
@@ -207,7 +207,7 @@ describe('importType(name)', function () {
     expect(importType('@test-scope/some-module', foldersContext_2)).to.equal('internal');
   });
 
-  it('returns "external" for a scoped module from a symlinked directory which partial path ending w/ slash is contained in "external-module-folders" (webpack resolver)', function() {
+  it('returns "external" for a scoped module from a symlinked directory which partial path ending w/ slash is contained in "external-module-folders" (webpack resolver)', function () {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['symlinked-module/'],
@@ -215,7 +215,7 @@ describe('importType(name)', function () {
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
   });
 
-  it('returns "internal" for a scoped module from a symlinked directory when "external-module-folders" contains an absolute path resembling directory‘s relative path (webpack resolver)', function() {
+  it('returns "internal" for a scoped module from a symlinked directory when "external-module-folders" contains an absolute path resembling directory‘s relative path (webpack resolver)', function () {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': ['/symlinked-module'],
@@ -223,7 +223,7 @@ describe('importType(name)', function () {
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('internal');
   });
 
-  it('returns "external" for a scoped module from a symlinked directory which absolute path is contained in "external-module-folders" (webpack resolver)', function() {
+  it('returns "external" for a scoped module from a symlinked directory which absolute path is contained in "external-module-folders" (webpack resolver)', function () {
     const foldersContext = testContext({
       'import/resolver': 'webpack',
       'import/external-module-folders': [testFilePath('symlinked-module')],
@@ -231,7 +231,7 @@ describe('importType(name)', function () {
     expect(importType('@test-scope/some-module', foldersContext)).to.equal('external');
   });
 
-  it('`isExternalModule` works with windows directory separator', function() {
+  it('`isExternalModule` works with windows directory separator', function () {
     const context = testContext();
     expect(isExternalModule('foo', {}, 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
     expect(isExternalModule('foo', {
diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index a9c9ba5849..7344d94f20 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -30,7 +30,7 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
     const parseSpy = sinon.spy();
     const parserOptions = { ecmaFeatures: { jsx: true } };
     parseStubParser.parse = parseSpy;
-    parse(path, content, { settings: {}, parserPath: parseStubParserPath, parserOptions: parserOptions });
+    parse(path, content, { settings: {}, parserPath: parseStubParserPath, parserOptions });
     expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
     expect(parseSpy.args[0][0], 'custom parser to get content as its first argument').to.equal(content);
     expect(parseSpy.args[0][1], 'custom parser to get an object as its second argument').to.be.an('object');
@@ -66,7 +66,7 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
     const parseSpy = sinon.spy();
     const parserOptions = { ecmaFeatures: { jsx: true } };
     parseStubParser.parse = parseSpy;
-    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, parserOptions: parserOptions })).not.to.throw(Error);
+    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, parserOptions })).not.to.throw(Error);
     expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
   });
 
diff --git a/tests/src/core/parseStubParser.js b/tests/src/core/parseStubParser.js
index 9d17f0b041..4ed17d9dd3 100644
--- a/tests/src/core/parseStubParser.js
+++ b/tests/src/core/parseStubParser.js
@@ -1,4 +1,4 @@
 // this stub must be in a separate file to require from parse via moduleRequire
 module.exports = {
-  parse: function () {},
+  parse() {},
 };
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index ccfe5f6c27..f9e9a10347 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -23,15 +23,15 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' });
 
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(utils.testFilePath('./bar.jsx'));
 
     expect(resolve( '../files/exception'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('exception.js'); } }),
     )).to.equal(undefined);
 
     expect(resolve( '../files/not-found'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('not-found.js'); } }),
     )).to.equal(undefined);
   });
 
@@ -39,15 +39,15 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' });
 
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(utils.testFilePath('./bar.jsx'));
 
     expect(resolve( '../files/exception'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('exception.js'); } }),
     )).to.equal(undefined);
 
     expect(resolve( '../files/not-found'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('not-found.js'); } }),
     )).to.equal(undefined);
   });
 
@@ -59,12 +59,12 @@ describe('resolve', function () {
     };
 
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(utils.testFilePath('./bar.jsx'));
 
     testContextReports.length = 0;
     expect(resolve( '../files/exception'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('exception.js'); } }),
     )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>');
@@ -72,7 +72,7 @@ describe('resolve', function () {
 
     testContextReports.length = 0;
     expect(resolve( '../files/not-found'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('not-found.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('not-found.js'); } }),
     )).to.equal(undefined);
     expect(testContextReports.length).to.equal(0);
   });
@@ -81,7 +81,7 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
 
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
@@ -89,7 +89,7 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } });
 
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
@@ -97,7 +97,7 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
 
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
@@ -105,7 +105,7 @@ describe('resolve', function () {
     const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } });
 
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
@@ -118,7 +118,7 @@ describe('resolve', function () {
 
     testContextReports.length = 0;
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config');
@@ -134,7 +134,7 @@ describe('resolve', function () {
     };
     testContextReports.length = 0;
     expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('foo.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
     )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`);
@@ -157,7 +157,7 @@ describe('resolve', function () {
     };
 
     expect(resolve( '../files/exception'
-      , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js'); } }),
+      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('exception.js'); } }),
     )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>');
@@ -174,15 +174,15 @@ describe('resolve', function () {
       const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' });
 
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(utils.testFilePath('./bar.jsx'));
 
       expect(resolve( '../files/exception'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('exception.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } }),
       )).to.equal(undefined);
 
       expect(resolve( '../files/not-found'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('not-found.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } }),
       )).to.equal(undefined);
     });
 
@@ -190,15 +190,15 @@ describe('resolve', function () {
       const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' });
 
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(utils.testFilePath('./bar.jsx'));
 
       expect(resolve( '../files/exception'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('exception.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } }),
       )).to.equal(undefined);
 
       expect(resolve( '../files/not-found'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('not-found.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } }),
       )).to.equal(undefined);
     });
 
@@ -210,12 +210,12 @@ describe('resolve', function () {
       };
 
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(utils.testFilePath('./bar.jsx'));
 
       testContextReports.length = 0;
       expect(resolve( '../files/exception'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('exception.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } }),
       )).to.equal(undefined);
       expect(testContextReports[0]).to.be.an('object');
       expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>');
@@ -223,7 +223,7 @@ describe('resolve', function () {
 
       testContextReports.length = 0;
       expect(resolve( '../files/not-found'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('not-found.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } }),
       )).to.equal(undefined);
       expect(testContextReports.length).to.equal(0);
     });
@@ -232,7 +232,7 @@ describe('resolve', function () {
       const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
 
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(utils.testFilePath('./bar.jsx'));
     });
 
@@ -240,7 +240,7 @@ describe('resolve', function () {
       const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } });
 
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(utils.testFilePath('./bar.jsx'));
     });
 
@@ -248,7 +248,7 @@ describe('resolve', function () {
       const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
 
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(utils.testFilePath('./bar.jsx'));
     });
 
@@ -256,7 +256,7 @@ describe('resolve', function () {
       const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } });
 
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(utils.testFilePath('./bar.jsx'));
     });
 
@@ -269,7 +269,7 @@ describe('resolve', function () {
 
       testContextReports.length = 0;
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(undefined);
       expect(testContextReports[0]).to.be.an('object');
       expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config');
@@ -285,7 +285,7 @@ describe('resolve', function () {
       };
       testContextReports.length = 0;
       expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('foo.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
       )).to.equal(undefined);
       expect(testContextReports[0]).to.be.an('object');
       expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`);
@@ -308,7 +308,7 @@ describe('resolve', function () {
       };
 
       expect(resolve( '../files/exception'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename: function () { return utils.getFilename('exception.js'); } }),
+        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } }),
       )).to.equal(undefined);
       expect(testContextReports[0]).to.be.an('object');
       expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>');
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index a861fff76f..15101fc0cd 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -160,7 +160,7 @@ context('TypeScript', function () {
       valid: [
         test({
           code: `import foobar from "./typescript-default"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -168,7 +168,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import foobar from "./typescript-export-assign-default"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -176,7 +176,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import foobar from "./typescript-export-assign-function"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -184,7 +184,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import foobar from "./typescript-export-assign-mixed"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -192,7 +192,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import foobar from "./typescript-export-assign-default-reexport"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -200,7 +200,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import React from "./typescript-export-assign-default-namespace"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -211,7 +211,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import Foo from "./typescript-export-as-default-namespace"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -222,7 +222,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import Foo from "./typescript-export-react-test-renderer"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -233,7 +233,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import foobar from "./typescript-export-assign-property"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -244,7 +244,7 @@ context('TypeScript', function () {
       invalid: [
         test({
           code: `import foobar from "./typescript"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -253,7 +253,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import React from "./typescript-export-assign-default-namespace"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -262,7 +262,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import FooBar from "./typescript-export-as-default-namespace"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -271,7 +271,7 @@ context('TypeScript', function () {
         }),
         test({
           code: `import Foo from "./typescript-export-as-default-namespace"`,
-          parser: parser,
+          parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index d997b949b6..efc6e402ff 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -129,7 +129,7 @@ ruleTester.run('export', rule, {
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -218,7 +218,7 @@ context('TypeScript', function () {
               export * as A from './named-export-collision/a';
               export * as B from './named-export-collision/b';
             `,
-            parser: parser,
+            parser,
           }),
         ]),
 
diff --git a/tests/src/rules/max-dependencies.js b/tests/src/rules/max-dependencies.js
index 1251af97e8..fc3b541f50 100644
--- a/tests/src/rules/max-dependencies.js
+++ b/tests/src/rules/max-dependencies.js
@@ -97,7 +97,7 @@ context('TypeScript', { skip: semver.satisfies(eslintPkg.version, '>5.0.0') }, (
       valid: [    
         test({
           code: 'import type { x } from \'./foo\'; import { y } from \'./bar\';',
-          parser: parser,
+          parser,
           options: [{
             max: 1,
             ignoreTypeImports: true,
@@ -107,7 +107,7 @@ context('TypeScript', { skip: semver.satisfies(eslintPkg.version, '>5.0.0') }, (
       invalid: [    
         test({
           code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'',
-          parser: parser,
+          parser,
           options: [{
             max: 1,
           }],
@@ -118,7 +118,7 @@ context('TypeScript', { skip: semver.satisfies(eslintPkg.version, '>5.0.0') }, (
     
         test({
           code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'; import type { z } from \'./baz\'',
-          parser: parser,
+          parser,
           options: [{
             max: 2,
             ignoreTypeImports: false,
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 56babfa509..992baa0fd0 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -362,8 +362,8 @@ context('TypeScript', function () {
       test({
         code: `import {a} from './export-star-3/b';`,
         filename: testFilePath('./export-star-3/a.js'),
-        parser: parser,
-        settings: settings,
+        parser,
+        settings,
       }),
     ];
 
@@ -376,52 +376,52 @@ context('TypeScript', function () {
       valid.push(
         test({
           code: `import { MyType } from "./${source}"`,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
         }),
         test({
           code: `import { Foo } from "./${source}"`,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
         }),
         test({
           code: `import { Bar } from "./${source}"`,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
         }),
         test({
           code: `import { getFoo } from "./${source}"`,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
         }),
         test({
           code: `import { MyEnum } from "./${source}"`,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
         }),
         test({
           code: `
               import { MyModule } from "./${source}"
               MyModule.ModuleFunction()
             `,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
         }),
         test({
           code: `
               import { MyNamespace } from "./${source}"
               MyNamespace.NSModule.NSModuleFunction()
             `,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
         }),
       );
 
       invalid.push(
         test({
           code: `import { MissingType } from "./${source}"`,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
           errors: [{
             message: `MissingType not found in './${source}'`,
             type: 'Identifier',
@@ -429,8 +429,8 @@ context('TypeScript', function () {
         }),
         test({
           code: `import { NotExported } from "./${source}"`,
-          parser: parser,
-          settings: settings,
+          parser,
+          settings,
           errors: [{
             message: `NotExported not found in './${source}'`,
             type: 'Identifier',
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 802d5b440b..826637b970 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -128,7 +128,7 @@ const valid = [
         import * as foo from "./typescript-declare-nested"
         foo.bar.MyFunction()
       `,
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -137,7 +137,7 @@ const valid = [
 
     test({
       code: `import { foobar } from "./typescript-declare-interface"`,
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -146,7 +146,7 @@ const valid = [
 
     test({
       code: 'export * from "typescript/lib/typescript.d"',
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -155,7 +155,7 @@ const valid = [
 
     test({
       code: 'export = function name() {}',
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 39f4c42914..a00e86900f 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -184,7 +184,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
           import { ExecaReturnValue } from 'execa';
           import execa = require('execa');
         `,
-        parser: parser,
+        parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
       {
@@ -192,7 +192,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
           import execa = require('execa');
           import { ExecaReturnValue } from 'execa';
         `,
-        parser: parser,
+        parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
       {
@@ -201,7 +201,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
           import execa = require('execa');
           import { ExecbReturnValue } from 'execb';
         `,
-        parser: parser,
+        parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
       {
@@ -210,14 +210,14 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
           import { ExecaReturnValue } from 'execa';
           import execb = require('execb');
         `,
-        parser: parser,
+        parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
       {
         code: `
           export import a = obj;\nf(a);
         `,
-        parser: parser,
+        parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
       {
@@ -228,7 +228,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
               export import a2 = a;
               f(a);
           }`,
-        parser: parser,
+        parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
       {
@@ -239,7 +239,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
               stub
           }
         `,
-        parser: parser,
+        parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
     ]),
diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index aa2aebedc6..290946735f 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -201,7 +201,7 @@ ruleTester.run('no-deprecated: hoisting', rule, {
 describe('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index faf096acec..e550b63ce7 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -415,7 +415,7 @@ import {x,y} from './foo'
   ],
 });
 
-context('TypeScript', function() {
+context('TypeScript', function () {
   getNonDefaultParsers()
     .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
     .forEach((parser) => {
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 370cce7e39..c6abcd6e4a 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -384,7 +384,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
 describe('TypeScript', { skip: semver.satisfies(eslintPkg.version, '^4') }, function () {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js
index 2bad32c460..2fee9f4502 100644
--- a/tests/src/rules/no-internal-modules.js
+++ b/tests/src/rules/no-internal-modules.js
@@ -139,7 +139,7 @@ ruleTester.run('no-internal-modules', rule, {
             }
           }
         `,
-        parser: parser,
+        parser,
       }),
     ]),
     test({
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 17e52b411b..837f7e5758 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -963,31 +963,31 @@ context('TypeScript', function () {
           const a2: c = {};
           const a3: d = {};
           `,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
         }),
         test({
           options: unusedExportsTypescriptOptions,
           code: `export const b = 2;`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'),
         }),
         test({
           options: unusedExportsTypescriptOptions,
           code: `export interface c {};`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'),
         }),
         test({
           options: unusedExportsTypescriptOptions,
           code: `export type d = {};`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'),
         }),
         test({
           options: unusedExportsTypescriptOptions,
           code: `export enum e { f };`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-e.ts'),
         }),
         test({
@@ -1003,31 +1003,31 @@ context('TypeScript', function () {
           const a3: d = {};
           const a4: typeof e = undefined;
           `,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-a-import-type.ts'),
         }),
         test({
           options: unusedExportsTypescriptOptions,
           code: `export const b = 2;`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-b-used-as-type.ts'),
         }),
         test({
           options: unusedExportsTypescriptOptions,
           code: `export interface c {};`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-c-used-as-type.ts'),
         }),
         test({
           options: unusedExportsTypescriptOptions,
           code: `export type d = {};`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-d-used-as-type.ts'),
         }),
         test({
           options: unusedExportsTypescriptOptions,
           code: `export enum e { f };`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-e-used-as-type.ts'),
         }),
         // Should also be valid when the exporting files are linted before the importing ones
@@ -1060,7 +1060,7 @@ context('TypeScript', function () {
         test({
           options: unusedExportsTypescriptOptions,
           code: `export const b = 2;`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-b-unused.ts'),
           errors: [
             error(`exported declaration 'b' not used within other modules`),
@@ -1069,7 +1069,7 @@ context('TypeScript', function () {
         test({
           options: unusedExportsTypescriptOptions,
           code: `export interface c {};`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-c-unused.ts'),
           errors: [
             error(`exported declaration 'c' not used within other modules`),
@@ -1078,7 +1078,7 @@ context('TypeScript', function () {
         test({
           options: unusedExportsTypescriptOptions,
           code: `export type d = {};`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-d-unused.ts'),
           errors: [
             error(`exported declaration 'd' not used within other modules`),
@@ -1087,7 +1087,7 @@ context('TypeScript', function () {
         test({
           options: unusedExportsTypescriptOptions,
           code: `export enum e { f };`,
-          parser: parser,
+          parser,
           filename: testFilePath('./no-unused-modules/typescript/file-ts-e-unused.ts'),
           errors: [
             error(`exported declaration 'e' not used within other modules`),
diff --git a/tests/src/rules/no-webpack-loader-syntax.js b/tests/src/rules/no-webpack-loader-syntax.js
index 5ec848bc65..a8aa0dd2b0 100644
--- a/tests/src/rules/no-webpack-loader-syntax.js
+++ b/tests/src/rules/no-webpack-loader-syntax.js
@@ -76,7 +76,7 @@ ruleTester.run('no-webpack-loader-syntax', rule, {
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
-      parser: parser,
+      parser,
       settings: {
         'import/parsers': { [parser]: ['.ts'] },
         'import/resolver': { 'eslint-import-resolver-typescript': true },
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 34323fe53d..36205b1935 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -148,7 +148,7 @@ ruleTester.run('prefer-default-export', rule, {
   ],
 });
 
-context('TypeScript', function() {
+context('TypeScript', function () {
   getNonDefaultParsers().forEach((parser) => {
     const parserConfig = {
       parser,
diff --git a/tests/src/utils.js b/tests/src/utils.js
index e805e9545d..4d23af7551 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -46,7 +46,7 @@ export function test(t) {
 }
 
 export function testContext(settings) {
-  return { getFilename: function () { return FILENAME; },
+  return { getFilename() { return FILENAME; },
     settings: settings || {} };
 }
 

From 397b6c5f4787e06f73dd4f6a120f79e59644cef1 Mon Sep 17 00:00:00 2001
From: Filipp Riabchun <filipp.riabchun@jetbrains.com>
Date: Mon, 30 Aug 2021 20:05:53 +0200
Subject: [PATCH 364/767] [Tests] run pretest on CI

Extracted from #2212 / #1660.
---
 .github/workflows/node-4+.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index b13e3b88cf..d4035d2674 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -81,6 +81,7 @@ jobs:
           node-version: ${{ matrix.node-version }}
           after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh
           skip-ls-check: true
+      - run: npm run pretest
       - run: npm run tests-only
       - run: npm run coveralls
 

From 2a0d207704ee8cb919242fb073b9cd132e088f57 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 30 Aug 2021 12:55:52 -0700
Subject: [PATCH 365/767] [Tests] coveralls -> codecov

---
 .github/workflows/node-4+.yml  |  2 +-
 .github/workflows/packages.yml |  1 +
 .nycrc                         |  2 +-
 .travis.yml                    |  2 +-
 appveyor.yml                   | 47 ++++++++++++++++++++++++----------
 package.json                   |  6 ++---
 resolvers/node/package.json    |  4 +--
 resolvers/webpack/package.json |  5 +---
 tests/dep-time-travel.sh       |  2 +-
 9 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index d4035d2674..f2498807cc 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -83,7 +83,7 @@ jobs:
           skip-ls-check: true
       - run: npm run pretest
       - run: npm run tests-only
-      - run: npm run coveralls
+      - uses: codecov/codecov-action@v1
 
   node:
     name: 'node 4+'
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index 79bd1ce464..e7302faea4 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -43,6 +43,7 @@ jobs:
           after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh && cd ${{ matrix.package }} && npm install
           skip-ls-check: true
       - run: cd ${{ matrix.package }} && npm run tests-only
+      - uses: codecov/codecov-action@v1
 
   packages:
     name: 'packages: all tests'
diff --git a/.nycrc b/.nycrc
index 8147f38718..20bcfca222 100644
--- a/.nycrc
+++ b/.nycrc
@@ -1,7 +1,7 @@
 {
 	"all": true,
 	"check-coverage": false,
-	"reporter": ["text-summary", "text", "html", "json"],
+	"reporter": ["text-summary", "lcov", "text", "html", "json"],
 	"require": [
 		"babel-register"
 	],
diff --git a/.travis.yml b/.travis.yml
index 583a411972..c289a39e46 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -36,4 +36,4 @@ script:
   - npm run tests-only
 
 after_success:
-  - npm run coveralls
+  - bash <(curl -s https://codecov.io/bash)
diff --git a/appveyor.yml b/appveyor.yml
index de79234eb4..c728414d44 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,28 +5,31 @@ configuration:
 # Test against this version of Node.js
 environment:
   matrix:
+    - nodejs_version: "16"
     - nodejs_version: "14"
     - nodejs_version: "12"
     - nodejs_version: "10"
     - nodejs_version: "8"
-  # - nodejs_version: "6"
-  # - nodejs_version: "4"
+    # - nodejs_version: "6"
+    # - nodejs_version: "4"
 
 image: Visual Studio 2019
 matrix:
   fast_finish: false
   exclude:
-    - configuration: WSL
-      nodejs_version: "10"
     - configuration: WSL
       nodejs_version: "8"
+    - configuration: WSL
+      nodejs_version: "6"
+    - configuration: WSL
+      nodejs_version: "4"
 
-  # allow_failures:
-  #   - nodejs_version: "4" # for eslint 5
+  allow_failures:
+    - nodejs_version: "4" # for eslint 5
 
-# platform:
-#   - x86
-#   - x64
+platform:
+  - x86
+  - x64
 
 # Initialization scripts. (runs before repo cloning)
 init:
@@ -35,14 +38,26 @@ init:
       if ($env:nodejs_version -eq "4") {
         $env:NPM_VERSION="3"
       }
-      if ($env:nodejs_version -in @("8", "10", "12")) {
-        $env:NPM_VERSION="6.14.5"
+      if ($env:nodejs_version -in @("8")) {
+        $env:NPM_VERSION="6"
+      }
+      if ($env:nodejs_version -in @("10", "12", "14", "16")) {
+        $env:NPM_VERSION="6" # TODO: use npm 7
+        $env:NPM_CONFIG_LEGACY_PEER_DEPS="true"
       }
   - ps: >-
+      $env:ESLINT_VERSION="7";
       if ([int]$env:nodejs_version -le 8) {
         $env:ESLINT_VERSION="6"
       }
+      if ([int]$env:nodejs_version -le 7) {
+        $env:ESLINT_VERSION="5"
+      }
+      if ([int]$env:nodejs_version -le 6) {
+        $env:ESLINT_VERSION="4"
+      }
   - ps: $env:WINDOWS_NYC_VERSION = "15.0.1"
+  - ps: $env:TRAVIS_NODE_VERSION = $env:nodejs_version
 
   # Add `ci`-command to `PATH` for running commands either using cmd or wsl depending on the configuration
   - ps: $env:PATH += ";$(Join-Path $(pwd) "scripts")"
@@ -54,6 +69,8 @@ before_build:
 
   # Install dependencies
   - ci npm install
+  - ci npm run copy-metafiles
+  - bash ./tests/dep-time-travel.sh 2>&1
 
   # fix symlinks
   - git config core.symlinks true
@@ -99,9 +116,6 @@ test_script:
       $env:RESOLVERS = [string]::Join(";", $resolvers);
   - FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm test & popd )
 
-on_success:
-  - ci npm run coveralls
-
 # Configuration-specific steps
 for:
   - matrix:
@@ -127,6 +141,9 @@ for:
             }
           $env:RESOLVERS = [string]::Join(";", $resolvers);
       - IF DEFINED RESOLVERS FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm install --no-save nyc@%WINDOWS_NYC_VERSION% & popd )
+    # TODO: enable codecov for native windows builds
+    # on_success:
+      # - codecov
   - matrix:
       only:
         - configuration: WSL
@@ -136,5 +153,7 @@ for:
       - ps: $env:WSLENV += ":nodejs_version"
       - ps: wsl curl -sL 'https://deb.nodesource.com/setup_${nodejs_version}.x' `| sudo APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 -E bash -
       - wsl sudo DEBIAN_FRONTEND=noninteractive apt install -y nodejs
+    on_success:
+      - ci bash <(curl -s https://codecov.io/bash)
 
 build: on
diff --git a/package.json b/package.json
index dd7cbcb350..7537df99aa 100644
--- a/package.json
+++ b/package.json
@@ -25,14 +25,13 @@
     "watch": "npm run tests-only -- -- --watch",
     "pretest": "linklocal",
     "posttest": "eslint .",
-    "mocha": "cross-env BABEL_ENV=test nyc -s mocha",
+    "mocha": "cross-env BABEL_ENV=test nyc mocha",
     "tests-only": "npm run mocha tests/src",
     "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
     "test-all": "node --require babel-register ./scripts/testAll",
     "prepublishOnly": "safe-publish-latest && npm run build",
-    "prepublish": "not-in-publish || npm run prepublishOnly",
-    "coveralls": "nyc report --reporter lcovonly && coveralls < ./coverage/lcov.info"
+    "prepublish": "not-in-publish || npm run prepublishOnly"
   },
   "repository": {
     "type": "git",
@@ -69,7 +68,6 @@
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
     "chai": "^4.3.4",
-    "coveralls": "^3.1.1",
     "cross-env": "^4.0.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0",
     "eslint-import-resolver-node": "file:./resolvers/node",
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 5e7e9dea75..51a7d49cc8 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -9,8 +9,7 @@
   "scripts": {
     "prepublishOnly": "cp ../../{LICENSE,.npmrc} ./",
     "tests-only": "nyc mocha",
-    "test": "npm run tests-only",
-    "coveralls": "nyc report --reporter lcovonly && cd ../.. && coveralls < ./resolvers/node/coverage/lcov.info"
+    "test": "npm run tests-only"
   },
   "repository": {
     "type": "git",
@@ -35,7 +34,6 @@
   },
   "devDependencies": {
     "chai": "^3.5.0",
-    "coveralls": "^3.1.0",
     "mocha": "^3.5.3",
     "nyc": "^11.9.0"
   }
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index fd805af8b7..bd6269e2ff 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -6,9 +6,7 @@
   "scripts": {
     "prepublishOnly": "cp ../../{LICENSE,.npmrc} ./",
     "tests-only": "nyc mocha -t 5s",
-    "test": "npm run tests-only",
-    "report": "nyc report --reporter=html",
-    "coveralls": "nyc report --reporter lcovonly && cd ../.. && coveralls < ./resolvers/webpack/coverage/lcov.info"
+    "test": "npm run tests-only"
   },
   "files": [
     "index.js",
@@ -53,7 +51,6 @@
     "babel-preset-es2015-argon": "latest",
     "babel-register": "^6.26.0",
     "chai": "^3.5.0",
-    "coveralls": "^3.1.0",
     "mocha": "^3.5.3",
     "nyc": "^11.9.0",
     "webpack": "https://gist.github.com/ljharb/9cdb687f3806f8e6cb8a365d0b7840eb"
diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index d6f5aedfc2..2e24595761 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -2,7 +2,7 @@
 
 # expected: ESLINT_VERSION numeric env var
 
-echo "installing ${ESLINT_VERSION}..."
+echo "installing ${ESLINT_VERSION} in node ${TRAVIS_NODE_VERSION} with TS parser ${TS_PARSER:-default}..."
 
 export NPM_CONFIG_LEGACY_PEER_DEPS=true
 

From a032b8345a0910de804dde0c10ce3de85b3b0978 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 31 Aug 2021 19:09:09 -0700
Subject: [PATCH 366/767] [Tests] run `npm run pretest` in travis

---
 .travis.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.travis.yml b/.travis.yml
index c289a39e46..a4b5f2b195 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,6 +31,7 @@ before_install:
 install:
   - 'npm install'
   - 'if [ -n "${ESLINT_VERSION}" ]; then ./tests/dep-time-travel.sh; fi'
+  - 'npm run pretest'
 
 script:
   - npm run tests-only

From bb8eab92fb1fbd324e9b7d7c1ad4436f1cc5ac35 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 6 Sep 2021 09:59:47 -0700
Subject: [PATCH 367/767] [eslint] enable `keyword-spacing`

---
 .eslintrc                  | 11 ++++++++++-
 resolvers/webpack/index.js |  2 +-
 src/core/importType.js     |  2 +-
 utils/module-require.js    |  4 ++--
 utils/resolve.js           |  2 +-
 5 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 923b8fd088..4064c571d8 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -25,6 +25,15 @@
         "eqeqeq": [2, "allow-null"],
         "func-call-spacing": 2,
         "indent": [2, 2],
+        "keyword-spacing": ["error", {
+          before: true,
+          after: true,
+          overrides: {
+            return: { after: true },
+            throw: { after: true },
+            case: { after: true }
+          }
+        }],
         "max-len": [1, 99, 2],
         "no-cond-assign": [2, "always"],
         "no-return-assign": [2, "always"],
@@ -47,7 +56,7 @@
             "named": "never",
             "asyncArrow": "always",
         }],
-  
+
         "eslint-plugin/consistent-output": [
             "error",
             "always",
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 3411eb75e5..690c3b52a1 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -84,7 +84,7 @@ exports.resolve = function (source, file, settings) {
     if (configPath) {
       try {
         webpackConfig = require(configPath);
-      } catch(e) {
+      } catch (e) {
         console.log('Error resolving webpackConfig', e);
         throw e;
       }
diff --git a/src/core/importType.js b/src/core/importType.js
index 8457c78535..6e4ac9a4da 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -75,7 +75,7 @@ export function isScopedMain(name) {
 }
 
 function isRelativeToParent(name) {
-  return/^\.\.$|^\.\.[\\/]/.test(name);
+  return /^\.\.$|^\.\.[\\/]/.test(name);
 }
 
 const indexFiles = ['.', './', './index', './index.js'];
diff --git a/utils/module-require.js b/utils/module-require.js
index 70e5510621..c03671ce5a 100644
--- a/utils/module-require.js
+++ b/utils/module-require.js
@@ -18,12 +18,12 @@ exports.default = function moduleRequire(p) {
     const eslintPath = require.resolve('eslint');
     const eslintModule = createModule(eslintPath);
     return require(Module._resolveFilename(p, eslintModule));
-  } catch(err) { /* ignore */ }
+  } catch (err) { /* ignore */ }
 
   try {
     // try relative to entry point
     return require.main.require(p);
-  } catch(err) { /* ignore */ }
+  } catch (err) { /* ignore */ }
 
   // finally, try from here
   return require(p);
diff --git a/utils/resolve.js b/utils/resolve.js
index f488ea798f..8039103321 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -42,7 +42,7 @@ function tryRequire(target, sourceFile) {
     } else {
       resolved = require.resolve(target);
     }
-  } catch(e) {
+  } catch (e) {
     // If the target does not exist then just return undefined
     return undefined;
   }

From 7784948fc5024476f0861b7b8bb20603f28cf809 Mon Sep 17 00:00:00 2001
From: stropho <3704482+stropho@users.noreply.github.com>
Date: Mon, 6 Sep 2021 13:22:12 +0200
Subject: [PATCH 368/767] [New] `no-restricted-paths`: add/restore glob pattern
 support

Fixes #2123.
---
 CHANGELOG.md                           |  2 +
 docs/rules/no-restricted-paths.md      | 50 ++++++++++++++-
 package.json                           |  1 +
 src/rules/no-restricted-paths.js       | 88 ++++++++++++++++++++------
 tests/src/rules/no-restricted-paths.js | 72 ++++++++++++++++++++-
 5 files changed, 192 insertions(+), 21 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc7dca9593..1985515830 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Added
 - [`no-unused-modules`]: add eslint v8 support ([#2194], thanks [@coderaiser])
+- [`no-restricted-paths`]: add/restore glob pattern support ([#2219], thanks [@stropho])
 
 ## [2.24.2] - 2021-08-24
 
@@ -903,6 +904,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2219]: https://github.com/import-js/eslint-plugin-import/pull/2219
 [#2196]: https://github.com/import-js/eslint-plugin-import/pull/2196
 [#2194]: https://github.com/import-js/eslint-plugin-import/pull/2194
 [#2184]: https://github.com/import-js/eslint-plugin-import/pull/2184
diff --git a/docs/rules/no-restricted-paths.md b/docs/rules/no-restricted-paths.md
index bfcb9af237..c9390754e3 100644
--- a/docs/rules/no-restricted-paths.md
+++ b/docs/rules/no-restricted-paths.md
@@ -9,8 +9,18 @@ In order to prevent such scenarios this rule allows you to define restricted zon
 
 This rule has one option. The option is an object containing the definition of all restricted `zones` and the optional `basePath` which is used to resolve relative paths within.
 The default value for `basePath` is the current working directory.
-Each zone consists of the `target` path and a `from` path. The `target` is the path where the restricted imports should be applied. The `from` path defines the folder that is not allowed to be used in an import. An optional `except` may be defined for a zone, allowing exception paths that would otherwise violate the related `from`. Note that `except` is relative to `from` and cannot backtrack to a parent directory.
-You may also specify an optional `message` for a zone, which will be displayed in case of the rule violation.
+
+Each zone consists of the `target` path, a `from` path, and an optional `except` and `message` attribute.
+- `target` is the path where the restricted imports should be applied. It can be expressed by
+    - directory string path that matches all its containing files
+    - glob pattern matching all the targeted files
+- `from` path defines the folder that is not allowed to be used in an import.  It can be expressed by
+    - directory string path that matches all its containing files
+    - glob pattern matching all the files restricted to be imported
+- `except` may be defined for a zone, allowing exception paths that would otherwise violate the related `from`. Note that it does not alter the behaviour of `target` in any way.
+    - in case `from` is a glob pattern, `except` must be an array of glob patterns as well
+    - in case `from` is a directory path, `except` is relative to `from` and cannot backtrack to a parent directory.
+- `message` - will be displayed in case of the rule violation.
 
 ### Examples
 
@@ -77,4 +87,40 @@ The following pattern is not considered a problem:
 
 ```js
 import b from './b'
+
+```
+
+---------------
+
+Given the following folder structure:
+
+```
+my-project
+├── client
+    └── foo.js
+    └── sub-module
+        └── bar.js
+        └── baz.js
+
+```
+
+and the current configuration is set to:
+
+```
+{ "zones": [ {
+    "target": "./tests/files/restricted-paths/client/!(sub-module)/**/*",
+    "from": "./tests/files/restricted-paths/client/sub-module/**/*",
+} ] }
+```
+
+The following import is considered a problem in `my-project/client/foo.js`:
+
+```js
+import a from './sub-module/baz'
+```
+
+The following import is not considered a problem in `my-project/client/sub-module/bar.js`:
+
+```js
+import b from './baz'
 ```
diff --git a/package.json b/package.json
index 7537df99aa..b845b609d2 100644
--- a/package.json
+++ b/package.json
@@ -107,6 +107,7 @@
     "find-up": "^2.0.0",
     "has": "^1.0.3",
     "is-core-module": "^2.6.0",
+    "is-glob": "^4.0.1",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.4",
     "pkg-up": "^2.0.0",
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 058aa43ea8..e5bc6bc850 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -2,6 +2,8 @@ import path from 'path';
 
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
+import isGlob from 'is-glob';
+import { Minimatch, default as minimatch } from 'minimatch';
 import docsUrl from '../docsUrl';
 import importType from '../core/importType';
 
@@ -56,6 +58,10 @@ module.exports = {
     const matchingZones = restrictedPaths.filter((zone) => {
       const targetPath = path.resolve(basePath, zone.target);
 
+      if (isGlob(targetPath)) {
+        return minimatch(currentFilename, targetPath);
+      }
+
       return containsPath(currentFilename, targetPath);
     });
 
@@ -72,18 +78,59 @@ module.exports = {
       });
     }
 
-    const zoneExceptions = matchingZones.map((zone) => {
-      const exceptionPaths = zone.except || [];
-      const absoluteFrom = path.resolve(basePath, zone.from);
-      const absoluteExceptionPaths = exceptionPaths.map((exceptionPath) => path.resolve(absoluteFrom, exceptionPath));
-      const hasValidExceptionPaths = absoluteExceptionPaths
-        .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
+    function reportInvalidExceptionGlob(node) {
+      context.report({
+        node,
+        message: 'Restricted path exceptions must be glob patterns when`from` is a glob pattern',
+      });
+    }
+
+    const makePathValidator = (zoneFrom, zoneExcept = []) => {
+      const absoluteFrom = path.resolve(basePath, zoneFrom);
+      const isGlobPattern = isGlob(zoneFrom);
+      let isPathRestricted;
+      let hasValidExceptions;
+      let isPathException;
+      let reportInvalidException;
+
+      if (isGlobPattern) {
+        const mm = new Minimatch(absoluteFrom);
+        isPathRestricted = (absoluteImportPath) => mm.match(absoluteImportPath);
+
+        hasValidExceptions = zoneExcept.every(isGlob);
+
+        if (hasValidExceptions) {
+          const exceptionsMm = zoneExcept.map((except) => new Minimatch(except));
+          isPathException = (absoluteImportPath) => exceptionsMm.some((mm) => mm.match(absoluteImportPath));
+        }
+
+        reportInvalidException = reportInvalidExceptionGlob;
+      } else {
+        isPathRestricted = (absoluteImportPath) => containsPath(absoluteImportPath, absoluteFrom);
+
+        const absoluteExceptionPaths = zoneExcept
+          .map((exceptionPath) => path.resolve(absoluteFrom, exceptionPath));
+        hasValidExceptions = absoluteExceptionPaths
+          .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
+
+        if (hasValidExceptions) {
+          isPathException = (absoluteImportPath) => absoluteExceptionPaths.some(
+            (absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath),
+          );
+        }
+
+        reportInvalidException = reportInvalidExceptionPath;
+      }
 
       return {
-        absoluteExceptionPaths,
-        hasValidExceptionPaths,
+        isPathRestricted,
+        hasValidExceptions,
+        isPathException,
+        reportInvalidException,
       };
-    });
+    };
+
+    const validators = [];
 
     function checkForRestrictedImportPath(importPath, node) {
       const absoluteImportPath = resolve(importPath, context);
@@ -93,22 +140,27 @@ module.exports = {
       }
 
       matchingZones.forEach((zone, index) => {
-        const absoluteFrom = path.resolve(basePath, zone.from);
-
-        if (!containsPath(absoluteImportPath, absoluteFrom)) {
-          return;
+        if (!validators[index]) {
+          validators[index] = makePathValidator(zone.from, zone.except);
         }
 
-        const { hasValidExceptionPaths, absoluteExceptionPaths } = zoneExceptions[index];
+        const {
+          isPathRestricted,
+          hasValidExceptions,
+          isPathException,
+          reportInvalidException,
+        } = validators[index];
 
-        if (!hasValidExceptionPaths) {
-          reportInvalidExceptionPath(node);
+        if (!isPathRestricted(absoluteImportPath)) {
           return;
         }
 
-        const pathIsExcepted = absoluteExceptionPaths
-          .some((absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath));
+        if (!hasValidExceptions) {
+          reportInvalidException(node);
+          return;
+        }
 
+        const pathIsExcepted = isPathException(absoluteImportPath);
         if (pathIsExcepted) {
           return;
         }
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index 3ee728c5c7..11934599ee 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -14,6 +14,23 @@ ruleTester.run('no-restricted-paths', rule, {
         zones: [ { target: './tests/files/restricted-paths/server', from: './tests/files/restricted-paths/other' } ],
       } ],
     }),
+    test({
+      code: 'import a from "../client/a.js"',
+      filename: testFilePath('./restricted-paths/server/b.js'),
+      options: [ {
+        zones: [ { target: '**/*', from: './tests/files/restricted-paths/other' } ],
+      } ],
+    }),
+    test({
+      code: 'import a from "../client/a.js"',
+      filename: testFilePath('./restricted-paths/client/b.js'),
+      options: [ {
+        zones: [ {
+          target: './tests/files/restricted-paths/!(client)/**/*',
+          from: './tests/files/restricted-paths/client/**/*',
+        } ],
+      } ],
+    }),
     test({
       code: 'const a = require("../client/a.js")',
       filename: testFilePath('./restricted-paths/server/b.js'),
@@ -61,7 +78,17 @@ ruleTester.run('no-restricted-paths', rule, {
         } ],
       } ],
     }),
-
+    test({
+      code: 'import A from "../two/a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [ {
+        zones: [ {
+          target: '**/*',
+          from: './tests/files/restricted-paths/server/**/*',
+          except: ['**/a.js'],
+        } ],
+      } ],
+    }),
 
     // irrelevant function calls
     test({ code: 'notrequire("../server/b.js")' }),
@@ -93,6 +120,18 @@ ruleTester.run('no-restricted-paths', rule, {
         column: 15,
       } ],
     }),
+    test({
+      code: 'import b from "../server/b.js"',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [ {
+        zones: [ { target: './tests/files/restricted-paths/client/**/*', from: './tests/files/restricted-paths/server' } ],
+      } ],
+      errors: [ {
+        message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+        line: 1,
+        column: 15,
+      } ],
+    }),
     test({
       code: 'import a from "../client/a"\nimport c from "./c"',
       filename: testFilePath('./restricted-paths/server/b.js'),
@@ -190,5 +229,36 @@ ruleTester.run('no-restricted-paths', rule, {
         column: 15,
       } ],
     }),
+    test({
+      code: 'import A from "../two/a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [ {
+        zones: [ {
+          target: '**/*',
+          from: './tests/files/restricted-paths/server/**/*',
+        } ],
+      } ],
+      errors: [ {
+        message: 'Unexpected path "../two/a.js" imported in restricted zone.',
+        line: 1,
+        column: 15,
+      } ],
+    }),
+    test({
+      code: 'import A from "../two/a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [ {
+        zones: [ {
+          target: '**/*',
+          from: './tests/files/restricted-paths/server/**/*',
+          except: ['a.js'],
+        } ],
+      } ],
+      errors: [ {
+        message: 'Restricted path exceptions must be glob patterns when`from` is a glob pattern',
+        line: 1,
+        column: 15,
+      } ],
+    }),
   ],
 });

From 2a8891ff63f1f0e01551eac1d379c88f4464a0cb Mon Sep 17 00:00:00 2001
From: Sergei Startsev <ai@programist.ru>
Date: Mon, 23 Aug 2021 21:28:57 +0200
Subject: [PATCH 369/767] [utils] [New] `fileExistsWithCaseSync`: add `strict`
 argument

See #1262.
---
 tests/src/core/resolve.js | 16 ++++++++++++----
 utils/CHANGELOG.md        |  5 +++++
 utils/resolve.js          |  6 +++---
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index f9e9a10347..360d4a2e70 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -3,7 +3,6 @@ import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
 import resolve, { CASE_SENSITIVE_FS, fileExistsWithCaseSync } from 'eslint-module-utils/resolve';
-import ModuleCache from 'eslint-module-utils/ModuleCache';
 
 import * as path from 'path';
 import * as fs from 'fs';
@@ -319,7 +318,11 @@ describe('resolve', function () {
   const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip);
   caseDescribe('case sensitivity', function () {
     let file;
-    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] } });
+    const testContext = utils.testContext({
+      'import/resolve': { 'extensions': ['.jsx'] },
+      'import/cache': { lifetime: 0 },
+    });
+    const testSettings = testContext.settings;
     before('resolve', function () {
       file = resolve(
       // Note the case difference 'MyUncoolComponent' vs 'MyUnCoolComponent'
@@ -329,14 +332,19 @@ describe('resolve', function () {
       expect(file, 'path to ./jsx/MyUncoolComponent').to.exist;
     });
     it('detects case does not match FS', function () {
-      expect(fileExistsWithCaseSync(file, ModuleCache.getSettings(testContext)))
+      expect(fileExistsWithCaseSync(file, testSettings))
         .to.be.false;
     });
     it('detecting case does not include parent folder path (issue #720)', function () {
       const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx');
-      expect(fileExistsWithCaseSync(f, ModuleCache.getSettings(testContext), true))
+      expect(fileExistsWithCaseSync(f, testSettings))
         .to.be.true;
     });
+    it('detecting case should include parent folder path', function () {
+      const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx');
+      expect(fileExistsWithCaseSync(f, testSettings, true))
+        .to.be.false;
+    });
   });
 
   describe('rename cache correctness', function () {
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 9160055145..f33001b6f9 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Added
+- `fileExistsWithCaseSync`: add `strict` argument ([#1262], thanks [@sergei-startsev])
+
 ## v2.6.2 - 2021-08-08
 
 ### Fixed
@@ -102,6 +105,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [#1409]: https://github.com/import-js/eslint-plugin-import/pull/1409
 [#1356]: https://github.com/import-js/eslint-plugin-import/pull/1356
 [#1290]: https://github.com/import-js/eslint-plugin-import/pull/1290
+[#1262]: https://github.com/import-js/eslint-plugin-import/pull/1262
 [#1218]: https://github.com/import-js/eslint-plugin-import/pull/1218
 [#1166]: https://github.com/import-js/eslint-plugin-import/issues/1166
 [#1160]: https://github.com/import-js/eslint-plugin-import/pull/1160
@@ -119,6 +123,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@kaiyoma]: https://github.com/kaiyoma
 [@manuth]: https://github.com/manuth
 [@pmcelhaney]: https://github.com/pmcelhaney
+[@sergei-startsev]: https://github.com/sergei-startsev
 [@sompylasar]: https://github.com/sompylasar
 [@timkraut]: https://github.com/timkraut
 [@vikr01]: https://github.com/vikr01
\ No newline at end of file
diff --git a/utils/resolve.js b/utils/resolve.js
index 8039103321..27d5dcc1e1 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -52,13 +52,13 @@ function tryRequire(target, sourceFile) {
 }
 
 // http://stackoverflow.com/a/27382838
-exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings) {
+exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings, strict) {
   // don't care if the FS is case-sensitive
   if (CASE_SENSITIVE_FS) return true;
 
   // null means it resolved to a builtin
   if (filepath === null) return true;
-  if (filepath.toLowerCase() === process.cwd().toLowerCase()) return true;
+  if (filepath.toLowerCase() === process.cwd().toLowerCase() && !strict) return true;
   const parsedPath = path.parse(filepath);
   const dir = parsedPath.dir;
 
@@ -73,7 +73,7 @@ exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cache
     if (filenames.indexOf(parsedPath.base) === -1) {
       result = false;
     } else {
-      result = fileExistsWithCaseSync(dir, cacheSettings);
+      result = fileExistsWithCaseSync(dir, cacheSettings, strict);
     }
   }
   fileExistsCache.set(filepath, result);

From 35bd9773f6c2c4fafac25d184ae0a29b40b3caf3 Mon Sep 17 00:00:00 2001
From: Sergei Startsev <ai@programist.ru>
Date: Mon, 23 Aug 2021 21:28:57 +0200
Subject: [PATCH 370/767] [New] `no-unresolved`: add `caseSensitiveStrict`
 option

Fixes #1259.
---
 CHANGELOG.md                     |  2 ++
 docs/rules/no-unresolved.md      | 19 +++++++++++++++++--
 src/rules/no-unresolved.js       | 13 ++++++++-----
 tests/src/rules/no-unresolved.js | 29 ++++++++++++++++++++++++++++-
 4 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1985515830..426b1114a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 
 ### Added
+- [`no-unresolved`]: add `caseSensitiveStrict` option ([#1262], thanks [@sergei-startsev])
 - [`no-unused-modules`]: add eslint v8 support ([#2194], thanks [@coderaiser])
 - [`no-restricted-paths`]: add/restore glob pattern support ([#2219], thanks [@stropho])
 
@@ -1053,6 +1054,7 @@ for info on changes for earlier releases.
 [#1294]: https://github.com/import-js/eslint-plugin-import/pull/1294
 [#1290]: https://github.com/import-js/eslint-plugin-import/pull/1290
 [#1277]: https://github.com/import-js/eslint-plugin-import/pull/1277
+[#1262]: https://github.com/import-js/eslint-plugin-import/pull/1262
 [#1257]: https://github.com/import-js/eslint-plugin-import/pull/1257
 [#1253]: https://github.com/import-js/eslint-plugin-import/pull/1253
 [#1248]: https://github.com/import-js/eslint-plugin-import/pull/1248
diff --git a/docs/rules/no-unresolved.md b/docs/rules/no-unresolved.md
index ae6177dfd9..89d00b9301 100644
--- a/docs/rules/no-unresolved.md
+++ b/docs/rules/no-unresolved.md
@@ -76,10 +76,25 @@ By default, this rule will report paths whose case do not match the underlying f
 const { default: x } = require('./foo') // reported if './foo' is actually './Foo' and caseSensitive: true
 ```
 
+#### `caseSensitiveStrict`
+
+The `caseSensitive` option does not detect case for the current working directory. The `caseSensitiveStrict` option allows checking `cwd` in resolved path. By default, the option is disabled.
+
+
+```js
+/*eslint import/no-unresolved: [2, { caseSensitiveStrict: true }]*/
+
+// Absolute paths
+import Foo from `/Users/fOo/bar/file.js` // reported, /Users/foo/bar/file.js
+import Foo from `d:/fOo/bar/file.js` // reported, d:/foo/bar/file.js
+
+// Relative paths, cwd is Users/foo/
+import Foo from `./../fOo/bar/file.js` // reported
+```
+
 ## When Not To Use It
 
-If you're using a module bundler other than Node or Webpack, you may end up with
-a lot of false positive reports of missing dependencies.
+If you're using a module bundler other than Node or Webpack, you may end up with a lot of false positive reports of missing dependencies.
 
 ## Further Reading
 
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index 236692b6e1..d7212560c4 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -18,14 +18,17 @@ module.exports = {
     schema: [
       makeOptionsSchema({
         caseSensitive: { type: 'boolean', default: true },
+        caseSensitiveStrict: { type: 'boolean', default: false },
       }),
     ],
   },
 
   create(context) {
+    const options = context.options[0] || {};
+
     function checkSourceValue(source) {
-      const shouldCheckCase = !CASE_SENSITIVE_FS
-        && (!context.options[0] || context.options[0].caseSensitive !== false);
+      const caseSensitive = !CASE_SENSITIVE_FS && options.caseSensitive !== false;
+      const caseSensitiveStrict = !CASE_SENSITIVE_FS && options.caseSensitiveStrict;
 
       const resolvedPath = resolve(source.value, context);
 
@@ -34,9 +37,9 @@ module.exports = {
           source,
           `Unable to resolve path to module '${source.value}'.`
         );
-      } else if (shouldCheckCase) {
+      } else if (caseSensitive || caseSensitiveStrict) {
         const cacheSettings = ModuleCache.getSettings(context.settings);
-        if (!fileExistsWithCaseSync(resolvedPath, cacheSettings)) {
+        if (!fileExistsWithCaseSync(resolvedPath, cacheSettings, caseSensitiveStrict)) {
           context.report(
             source,
             `Casing of ${source.value} does not match the underlying filesystem.`
@@ -45,6 +48,6 @@ module.exports = {
       }
     }
 
-    return moduleVisitor(checkSourceValue, context.options[0]);
+    return moduleVisitor(checkSourceValue, options);
   },
 };
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index d21ee2fd8c..19203074e1 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -15,7 +15,7 @@ function runResolverTests(resolver) {
   function rest(specs) {
     specs.settings = Object.assign({},
       specs.settings,
-      { 'import/resolver': resolver },
+      { 'import/resolver': resolver, 'import/cache': { lifetime: 0 } },
     );
 
     return test(specs);
@@ -227,6 +227,10 @@ function runResolverTests(resolver) {
   });
 
   if (!CASE_SENSITIVE_FS) {
+    const relativePath = './tests/files/jsx/MyUnCoolComponent.jsx';
+    const cwd = process.cwd();
+    const mismatchedPath = path.join(cwd.toUpperCase(), relativePath).replace(/\\/g, '/');
+
     ruleTester.run('case sensitivity', rule, {
       valid: [
         rest({ // test with explicit flag
@@ -247,6 +251,29 @@ function runResolverTests(resolver) {
         }),
       ],
     });
+
+    ruleTester.run('case sensitivity strict', rule, {
+      valid: [
+        // #1259 issue
+        rest({ // caseSensitiveStrict is disabled by default
+          code: `import foo from "${mismatchedPath}"`,
+        }),
+      ],
+
+      invalid: [
+        // #1259 issue
+        rest({ // test with enabled caseSensitiveStrict option
+          code: `import foo from "${mismatchedPath}"`,
+          options: [{ caseSensitiveStrict: true }],
+          errors: [`Casing of ${mismatchedPath} does not match the underlying filesystem.`],
+        }),
+        rest({ // test with enabled caseSensitiveStrict option and disabled caseSensitive
+          code: `import foo from "${mismatchedPath}"`,
+          options: [{ caseSensitiveStrict: true, caseSensitive: false }],
+          errors: [`Casing of ${mismatchedPath} does not match the underlying filesystem.`],
+        }),
+      ],
+    });
   }
 
 }

From 7579748b21f9cbdca84e917e65eb41b3794ed2d9 Mon Sep 17 00:00:00 2001
From: Max Komarychev <maxkomarychev@gmail.com>
Date: Sat, 20 Jun 2020 15:10:40 +0300
Subject: [PATCH 371/767] [utils] [new] add `visit`, to support dynamic imports
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

See #1660, #2212.

Co-authored-by: Max Komarychev <maxkomarychev@gmail.com>
Co-authored-by: Filipp Riabchun <filipp.riabchun@jetbrains.com>
Co-authored-by: 薛定谔的猫 <weiran.zsd@outlook.com>
---
 tests/src/core/getExports.js |  7 ++---
 tests/src/core/parse.js      |  1 -
 utils/CHANGELOG.md           |  8 ++++-
 utils/parse.js               | 57 +++++++++++++++++++++++++++++++++---
 utils/unambiguous.js         |  5 ++--
 utils/visit.js               | 24 +++++++++++++++
 6 files changed, 88 insertions(+), 14 deletions(-)
 create mode 100644 utils/visit.js

diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 2c9f70d5ba..604ae5cf28 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -8,7 +8,7 @@ import ExportMap from '../../../src/ExportMap';
 import * as fs from 'fs';
 
 import { getFilename } from '../utils';
-import * as unambiguous from 'eslint-module-utils/unambiguous';
+import { test as testUnambiguous } from 'eslint-module-utils/unambiguous';
 
 describe('ExportMap', function () {
   const fakeContext = Object.assign(
@@ -438,7 +438,6 @@ describe('ExportMap', function () {
 
   // todo: move to utils
   describe('unambiguous regex', function () {
-
     const testFiles = [
       ['deep/b.js', true],
       ['bar.js', true],
@@ -449,10 +448,8 @@ describe('ExportMap', function () {
     for (const [testFile, expectedRegexResult] of testFiles) {
       it(`works for ${testFile} (${expectedRegexResult})`, function () {
         const content = fs.readFileSync('./tests/files/' + testFile, 'utf8');
-        expect(unambiguous.test(content)).to.equal(expectedRegexResult);
+        expect(testUnambiguous(content)).to.equal(expectedRegexResult);
       });
     }
-
   });
-
 });
diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index 7344d94f20..407070aa2f 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -69,5 +69,4 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
     expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, parserOptions })).not.to.throw(Error);
     expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
   });
-
 });
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index f33001b6f9..241a205b47 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Added
 - `fileExistsWithCaseSync`: add `strict` argument ([#1262], thanks [@sergei-startsev])
+- add `visit`, to support dynamic imports ([#1660], [#2212], thanks [@maxkomarychev], [@aladdin-add], [@Hypnosphi])
 
 ## v2.6.2 - 2021-08-08
 
@@ -93,10 +94,12 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
 [#2026]: https://github.com/import-js/eslint-plugin-import/pull/2026
 [#1786]: https://github.com/import-js/eslint-plugin-import/pull/1786
 [#1671]: https://github.com/import-js/eslint-plugin-import/pull/1671
+[#1660]: https://github.com/import-js/eslint-plugin-import/pull/1660
 [#1606]: https://github.com/import-js/eslint-plugin-import/pull/1606
 [#1602]: https://github.com/import-js/eslint-plugin-import/pull/1602
 [#1591]: https://github.com/import-js/eslint-plugin-import/pull/1591
@@ -126,4 +129,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@sergei-startsev]: https://github.com/sergei-startsev
 [@sompylasar]: https://github.com/sompylasar
 [@timkraut]: https://github.com/timkraut
-[@vikr01]: https://github.com/vikr01
\ No newline at end of file
+[@vikr01]: https://github.com/vikr01
+[@maxkomarychev]: https://github.com/maxkomarychev
+[@aladdin-add]: https://github.com/aladdin-add
+[@Hypnosphi]: https://github.com/Hypnosphi
\ No newline at end of file
diff --git a/utils/parse.js b/utils/parse.js
index 3b2ac028f0..d1dd4ef03b 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -3,9 +3,42 @@ exports.__esModule = true;
 
 const moduleRequire = require('./module-require').default;
 const extname = require('path').extname;
+const fs = require('fs');
 
 const log = require('debug')('eslint-plugin-import:parse');
 
+function getBabelVisitorKeys(parserPath) {
+  if (parserPath.endsWith('index.js')) {
+    const hypotheticalLocation = parserPath.replace('index.js', 'visitor-keys.js');
+    if (fs.existsSync(hypotheticalLocation)) {
+      const keys = moduleRequire(hypotheticalLocation);
+      return keys.default || keys;
+    }
+  } else if (parserPath.endsWith('index.cjs')) {
+    const hypotheticalLocation = parserPath.replace('index.cjs', 'worker/ast-info.cjs');
+    if (fs.existsSync(hypotheticalLocation)) {
+      const astInfo = moduleRequire(hypotheticalLocation);
+      return astInfo.getVisitorKeys();
+    }
+  }
+  return null;
+}
+
+function keysFromParser(parserPath, parserInstance, parsedResult) {
+  if (/.*espree.*/.test(parserPath)) {
+    return parserInstance.VisitorKeys;
+  }
+  if (/.*(babel-eslint|@babel\/eslint-parser).*/.test(parserPath)) {
+    return getBabelVisitorKeys(parserPath);
+  }
+  if (/.*@typescript-eslint\/parser/.test(parserPath)) {
+    if (parsedResult) {
+      return parsedResult.visitorKeys;
+    }
+  }
+  return null;
+}
+
 exports.default = function parse(path, content, context) {
 
   if (context == null) throw new Error('need context to parse properly');
@@ -45,20 +78,36 @@ exports.default = function parse(path, content, context) {
   if (typeof parser.parseForESLint === 'function') {
     let ast;
     try {
-      ast = parser.parseForESLint(content, parserOptions).ast;
+      const parserRaw = parser.parseForESLint(content, parserOptions);
+      ast = parserRaw.ast;
+      return {
+        ast,
+        visitorKeys: keysFromParser(parserPath, parser, parserRaw),
+      };
     } catch (e) {
       console.warn();
       console.warn('Error while parsing ' + parserOptions.filePath);
       console.warn('Line ' + e.lineNumber + ', column ' + e.column + ': ' + e.message);
     }
     if (!ast || typeof ast !== 'object') {
-      console.warn('`parseForESLint` from parser `' + parserPath + '` is invalid and will just be ignored');
+      console.warn(
+        '`parseForESLint` from parser `' +
+          parserPath +
+          '` is invalid and will just be ignored',
+      );
     } else {
-      return ast;
+      return {
+        ast,
+        visitorKeys: keysFromParser(parserPath, parser, undefined),
+      };
     }
   }
 
-  return parser.parse(content, parserOptions);
+  const keys = keysFromParser(parserPath, parser, undefined);
+  return {
+    ast: parser.parse(content, parserOptions),
+    visitorKeys: keys,
+  };
 };
 
 function getParserPath(path, context) {
diff --git a/utils/unambiguous.js b/utils/unambiguous.js
index 1446632f39..75f21693b7 100644
--- a/utils/unambiguous.js
+++ b/utils/unambiguous.js
@@ -1,8 +1,7 @@
 'use strict';
 exports.__esModule = true;
 
-
-const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))/m;
+const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))|import\(/m;
 /**
  * detect possible imports/exports without a full parse.
  *
@@ -26,5 +25,5 @@ const unambiguousNodeType = /^(?:(?:Exp|Imp)ort.*Declaration|TSExportAssignment)
  * @return {Boolean}
  */
 exports.isModule = function isUnambiguousModule(ast) {
-  return ast.body.some(node => unambiguousNodeType.test(node.type));
+  return ast.body && ast.body.some(node => unambiguousNodeType.test(node.type));
 };
diff --git a/utils/visit.js b/utils/visit.js
new file mode 100644
index 0000000000..77b09850ae
--- /dev/null
+++ b/utils/visit.js
@@ -0,0 +1,24 @@
+'use strict';
+exports.__esModule = true;
+
+exports.default = function visit(node, keys, visitorSpec) {
+  if (!node || !keys) {
+    return;
+  }
+  const type = node.type;
+  if (typeof visitorSpec[type] === 'function') {
+    visitorSpec[type](node);
+  }
+  const childFields = keys[type];
+  if (!childFields) {
+    return;
+  }
+  childFields.forEach((fieldName) => {
+    [].concat(node[fieldName]).forEach((item) => {
+      visit(item, keys, visitorSpec);
+    });
+  });
+  if (typeof visitorSpec[`${type}:Exit`] === 'function') {
+    visitorSpec[`${type}:Exit`](node);
+  }
+};

From 7c382f02a6cafe676ee754a896092040dad8daf6 Mon Sep 17 00:00:00 2001
From: Max Komarychev <maxkomarychev@gmail.com>
Date: Sat, 20 Jun 2020 15:10:40 +0300
Subject: [PATCH 372/767] [New] `no-unused-modules`: support dynamic imports
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

All occurences of `import('...')` are treated as namespace imports
(`import * as X from '...'`)

See #1660, #2212.

Co-authored-by: Max Komarychev <maxkomarychev@gmail.com>
Co-authored-by: Filipp Riabchun <filipp.riabchun@jetbrains.com>
Co-authored-by: 薛定谔的猫 <weiran.zsd@outlook.com>
---
 CHANGELOG.md                                  |  4 +
 docs/rules/no-unused-modules.md               |  2 +-
 src/ExportMap.js                              | 49 +++++++++++-
 src/rules/no-unused-modules.js                | 36 ++++++++-
 .../no-unused-modules/dynamic-import-js-2.js  | 13 ++++
 .../no-unused-modules/dynamic-import-js.js    |  5 ++
 .../exports-for-dynamic-js-2.js               |  5 ++
 .../exports-for-dynamic-js.js                 |  5 ++
 .../typescript/dynamic-import-ts.ts           |  6 ++
 .../typescript/exports-for-dynamic-ts.ts      |  5 ++
 tests/src/rules/no-unused-modules.js          | 75 ++++++++++++++++++-
 11 files changed, 198 insertions(+), 7 deletions(-)
 create mode 100644 tests/files/no-unused-modules/dynamic-import-js-2.js
 create mode 100644 tests/files/no-unused-modules/dynamic-import-js.js
 create mode 100644 tests/files/no-unused-modules/exports-for-dynamic-js-2.js
 create mode 100644 tests/files/no-unused-modules/exports-for-dynamic-js.js
 create mode 100644 tests/files/no-unused-modules/typescript/dynamic-import-ts.ts
 create mode 100644 tests/files/no-unused-modules/typescript/exports-for-dynamic-ts.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 426b1114a3..9203739fd3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`no-unresolved`]: add `caseSensitiveStrict` option ([#1262], thanks [@sergei-startsev])
 - [`no-unused-modules`]: add eslint v8 support ([#2194], thanks [@coderaiser])
 - [`no-restricted-paths`]: add/restore glob pattern support ([#2219], thanks [@stropho])
+- [`no-unused-modules`]: support dynamic imports ([#1660], [#2212], thanks [@maxkomarychev], [@aladdin-add], [@Hypnosphi])
 
 ## [2.24.2] - 2021-08-24
 
@@ -906,6 +907,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2219]: https://github.com/import-js/eslint-plugin-import/pull/2219
+[#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
 [#2196]: https://github.com/import-js/eslint-plugin-import/pull/2196
 [#2194]: https://github.com/import-js/eslint-plugin-import/pull/2194
 [#2184]: https://github.com/import-js/eslint-plugin-import/pull/2184
@@ -983,6 +985,7 @@ for info on changes for earlier releases.
 [#1676]: https://github.com/import-js/eslint-plugin-import/pull/1676
 [#1666]: https://github.com/import-js/eslint-plugin-import/pull/1666
 [#1664]: https://github.com/import-js/eslint-plugin-import/pull/1664
+[#1660]: https://github.com/import-js/eslint-plugin-import/pull/1660
 [#1658]: https://github.com/import-js/eslint-plugin-import/pull/1658
 [#1651]: https://github.com/import-js/eslint-plugin-import/pull/1651
 [#1626]: https://github.com/import-js/eslint-plugin-import/pull/1626
@@ -1487,6 +1490,7 @@ for info on changes for earlier releases.
 [@MatthiasKunnen]: https://github.com/MatthiasKunnen
 [@mattijsbliek]: https://github.com/mattijsbliek
 [@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
+[@maxkomarychev]: https://github.com/maxkomarychev
 [@maxmalov]: https://github.com/maxmalov
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@mplewis]: https://github.com/mplewis
diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index 01c13557cf..0bd805612b 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -3,8 +3,8 @@
 Reports:
   - modules without any exports
   - individual exports not being statically `import`ed or `require`ed from other modules in the same project
+  - dynamic imports are supported if argument is a literal string
 
-Note: dynamic imports are currently not supported.
 
 ## Rule Details
 
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 5bda83dd35..53091e4668 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -7,6 +7,7 @@ import debug from 'debug';
 import { SourceCode } from 'eslint';
 
 import parse from 'eslint-module-utils/parse';
+import visit from 'eslint-module-utils/visit';
 import resolve from 'eslint-module-utils/resolve';
 import isIgnored, { hasValidExtension } from 'eslint-module-utils/ignore';
 
@@ -354,15 +355,57 @@ ExportMap.parse = function (path, content, context) {
   const isEsModuleInteropTrue = isEsModuleInterop();
 
   let ast;
+  let visitorKeys;
   try {
-    ast = parse(path, content, context);
+    const result = parse(path, content, context);
+    ast = result.ast;
+    visitorKeys = result.visitorKeys;
   } catch (err) {
-    log('parse error:', path, err);
     m.errors.push(err);
     return m; // can't continue
   }
 
-  if (!unambiguous.isModule(ast)) return null;
+  m.visitorKeys = visitorKeys;
+
+  let hasDynamicImports = false;
+
+  function processDynamicImport(source) {
+    hasDynamicImports = true;
+    if (source.type !== 'Literal') {
+      return null;
+    }
+    const p = remotePath(source.value);
+    if (p == null) {
+      return null;
+    }
+    const importedSpecifiers = new Set();
+    importedSpecifiers.add('ImportNamespaceSpecifier');
+    const getter = thunkFor(p, context);
+    m.imports.set(p, {
+      getter,
+      declarations: new Set([{
+        source: {
+        // capturing actual node reference holds full AST in memory!
+          value: source.value,
+          loc: source.loc,
+        },
+        importedSpecifiers,
+      }]),
+    });
+  }
+
+  visit(ast, visitorKeys, {
+    ImportExpression(node) {
+      processDynamicImport(node.source);
+    },
+    CallExpression(node) {
+      if (node.callee.type === 'Import') {
+        processDynamicImport(node.arguments[0]);
+      }
+    },
+  });
+
+  if (!unambiguous.isModule(ast) && !hasDynamicImports) return null;
 
   const docstyle = (context.settings && context.settings['import/docstyle']) || ['jsdoc'];
   const docStyleParsers = {};
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index ae6646f875..ab347bd8ce 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -7,6 +7,7 @@
 import Exports, { recursivePatternCapture } from '../ExportMap';
 import { getFileExtensions } from 'eslint-module-utils/ignore';
 import resolve from 'eslint-module-utils/resolve';
+import visit from 'eslint-module-utils/visit';
 import docsUrl from '../docsUrl';
 import { dirname, join } from 'path';
 import readPkgUp from 'read-pkg-up';
@@ -154,6 +155,8 @@ const importList = new Map();
  */
 const exportList = new Map();
 
+const visitorKeyMap = new Map();
+
 const ignoredFiles = new Set();
 const filesOutsideSrc = new Set();
 
@@ -193,8 +196,15 @@ const prepareImportsAndExports = (srcFiles, context) => {
     const imports = new Map();
     const currentExports = Exports.get(file, context);
     if (currentExports) {
-      const { dependencies, reexports, imports: localImportList, namespace  } = currentExports;
-
+      const {
+        dependencies,
+        reexports,
+        imports: localImportList,
+        namespace,
+        visitorKeys,
+      } = currentExports;
+
+      visitorKeyMap.set(file, visitorKeys);
       // dependencies === export * from
       const currentExportAll = new Set();
       dependencies.forEach(getDependency => {
@@ -675,6 +685,28 @@ module.exports = {
         });
       });
 
+      function processDynamicImport(source) {
+        if (source.type !== 'Literal') {
+          return null;
+        }
+        const p = resolve(source.value, context);
+        if (p == null) {
+          return null;
+        }
+        newNamespaceImports.add(p);
+      }
+
+      visit(node, visitorKeyMap.get(file), {
+        ImportExpression(child) {
+          processDynamicImport(child.source);
+        },
+        CallExpression(child) {
+          if (child.callee.type === 'Import') {
+            processDynamicImport(child.arguments[0]);
+          }
+        },
+      });
+
       node.body.forEach(astNode => {
         let resolvedPath;
 
diff --git a/tests/files/no-unused-modules/dynamic-import-js-2.js b/tests/files/no-unused-modules/dynamic-import-js-2.js
new file mode 100644
index 0000000000..3de28a65d5
--- /dev/null
+++ b/tests/files/no-unused-modules/dynamic-import-js-2.js
@@ -0,0 +1,13 @@
+const importPath = './exports-for-dynamic-js';
+class A {
+    method() {
+        const c = import(importPath)
+    }
+}
+
+
+class B {
+    method() {
+        const c = import('i-do-not-exist')
+    }
+}
diff --git a/tests/files/no-unused-modules/dynamic-import-js.js b/tests/files/no-unused-modules/dynamic-import-js.js
new file mode 100644
index 0000000000..36bf5c313c
--- /dev/null
+++ b/tests/files/no-unused-modules/dynamic-import-js.js
@@ -0,0 +1,5 @@
+class A {
+    method() {
+        const c = import('./exports-for-dynamic-js')
+    }
+}
diff --git a/tests/files/no-unused-modules/exports-for-dynamic-js-2.js b/tests/files/no-unused-modules/exports-for-dynamic-js-2.js
new file mode 100644
index 0000000000..19082862fc
--- /dev/null
+++ b/tests/files/no-unused-modules/exports-for-dynamic-js-2.js
@@ -0,0 +1,5 @@
+export const a = 10;
+export const b = 20;
+export const c = 30;
+const d = 40;
+export default d;
diff --git a/tests/files/no-unused-modules/exports-for-dynamic-js.js b/tests/files/no-unused-modules/exports-for-dynamic-js.js
new file mode 100644
index 0000000000..06d938e40b
--- /dev/null
+++ b/tests/files/no-unused-modules/exports-for-dynamic-js.js
@@ -0,0 +1,5 @@
+export const a = 10
+export const b = 20
+export const c = 30
+const d = 40
+export default d
diff --git a/tests/files/no-unused-modules/typescript/dynamic-import-ts.ts b/tests/files/no-unused-modules/typescript/dynamic-import-ts.ts
new file mode 100644
index 0000000000..10a17c3b19
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/dynamic-import-ts.ts
@@ -0,0 +1,6 @@
+class A {
+    method() {
+        const c = import('./exports-for-dynamic-ts')
+    }
+}
+
diff --git a/tests/files/no-unused-modules/typescript/exports-for-dynamic-ts.ts b/tests/files/no-unused-modules/typescript/exports-for-dynamic-ts.ts
new file mode 100644
index 0000000000..566eb7c7d4
--- /dev/null
+++ b/tests/files/no-unused-modules/typescript/exports-for-dynamic-ts.ts
@@ -0,0 +1,5 @@
+export const ts_a = 10
+export const ts_b = 20
+export const ts_c = 30
+const ts_d = 40
+export default ts_d
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 837f7e5758..6f87058c4a 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -112,41 +112,49 @@ ruleTester.run('no-unused-modules', rule, {
       options: unusedExportsOptions,
       code: 'import { o2 } from "./file-o";export default () => 12',
       filename: testFilePath('./no-unused-modules/file-a.js'),
+      parser: require.resolve('babel-eslint'),
     }),
     test({
       options: unusedExportsOptions,
       code: 'export const b = 2',
       filename: testFilePath('./no-unused-modules/file-b.js'),
+      parser: require.resolve('babel-eslint'),
     }),
     test({
       options: unusedExportsOptions,
       code: 'const c1 = 3; function c2() { return 3 }; export { c1, c2 }',
       filename: testFilePath('./no-unused-modules/file-c.js'),
+      parser: require.resolve('babel-eslint'),
     }),
     test({
       options: unusedExportsOptions,
       code: 'export function d() { return 4 }',
       filename: testFilePath('./no-unused-modules/file-d.js'),
+      parser: require.resolve('babel-eslint'),
     }),
     test({
       options: unusedExportsOptions,
       code: 'export class q { q0() {} }',
       filename: testFilePath('./no-unused-modules/file-q.js'),
+      parser: require.resolve('babel-eslint'),
     }),
     test({
       options: unusedExportsOptions,
       code: 'const e0 = 5; export { e0 as e }',
       filename: testFilePath('./no-unused-modules/file-e.js'),
+      parser: require.resolve('babel-eslint'),
     }),
     test({
       options: unusedExportsOptions,
       code: 'const l0 = 5; const l = 10; export { l0 as l1, l }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-l.js'),
+      parser: require.resolve('babel-eslint'),
     }),
     test({
       options: unusedExportsOptions,
       code: 'const o0 = 0; const o1 = 1; export { o0, o1 as o2 }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-o.js'),
+      parser: require.resolve('babel-eslint'),
     }),
   ],
   invalid: [
@@ -234,7 +242,72 @@ ruleTester.run('no-unused-modules', rule, {
   ],
 });
 
-// test for export from
+
+describe('dynamic imports', () => {
+  if (semver.satisfies(eslintPkg.version, '< 6')) {
+    beforeEach(function () {
+      this.skip();
+    });
+    return;
+  }
+
+  // test for unused exports with `import()`
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsOptions,
+        code: `
+            export const a = 10
+            export const b = 20
+            export const c = 30
+            const d = 40
+            export default d
+            `,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/exports-for-dynamic-js.js'),
+      }),
+    ],
+    invalid: [
+      test({
+        options: unusedExportsOptions,
+        code: `
+        export const a = 10
+        export const b = 20
+        export const c = 30
+        const d = 40
+        export default d
+        `,
+        parser: require.resolve('babel-eslint'),
+        filename: testFilePath('./no-unused-modules/exports-for-dynamic-js-2.js'),
+        errors: [
+          error(`exported declaration 'a' not used within other modules`),
+          error(`exported declaration 'b' not used within other modules`),
+          error(`exported declaration 'c' not used within other modules`),
+          error(`exported declaration 'default' not used within other modules`),
+        ] }),
+    ],
+  });
+  typescriptRuleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsTypescriptOptions,
+        code: `
+            export const ts_a = 10
+            export const ts_b = 20
+            export const ts_c = 30
+            const ts_d = 40
+            export default ts_d
+            `,
+        parser: require.resolve('@typescript-eslint/parser'),
+        filename: testFilePath('./no-unused-modules/typescript/exports-for-dynamic-ts.ts'),
+      }),
+    ],
+    invalid: [
+    ],
+  });
+});
+
+// // test for export from
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({

From 1571913aa1dd5e2eba2b3892e16a60d6197f02eb Mon Sep 17 00:00:00 2001
From: Greg Walker <michael.walker@gsa.gov>
Date: Thu, 6 May 2021 14:55:00 -0500
Subject: [PATCH 373/767] [utils] [new] create internal replacement for
 `pkg-up` and `read-pkg-up`

---
 utils/CHANGELOG.md |  8 ++++---
 utils/package.json |  1 +
 utils/pkgUp.js     |  8 +++++++
 utils/readPkgUp.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 66 insertions(+), 3 deletions(-)
 create mode 100644 utils/pkgUp.js
 create mode 100644 utils/readPkgUp.js

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 241a205b47..7d08f1963e 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Added
 - `fileExistsWithCaseSync`: add `strict` argument ([#1262], thanks [@sergei-startsev])
 - add `visit`, to support dynamic imports ([#1660], [#2212], thanks [@maxkomarychev], [@aladdin-add], [@Hypnosphi])
+- create internal replacement for `pkg-up` and `read-pkg-up` ([#2047], [@mgwalker])
 
 ## v2.6.2 - 2021-08-08
 
@@ -96,6 +97,7 @@ Yanked due to critical issue with cache key resulting from #839.
 
 [#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
+[#2047]: https://github.com/import-js/eslint-plugin-import/pull/2047
 [#2026]: https://github.com/import-js/eslint-plugin-import/pull/2026
 [#1786]: https://github.com/import-js/eslint-plugin-import/pull/1786
 [#1671]: https://github.com/import-js/eslint-plugin-import/pull/1671
@@ -121,15 +123,15 @@ Yanked due to critical issue with cache key resulting from #839.
 [@brettz9]: https://github.com/brettz9
 [@christophercurrie]: https://github.com/christophercurrie
 [@hulkish]: https://github.com/hulkish
+[@Hypnosphi]: https://github.com/Hypnosphi
 [@iamnapo]: https://github.com/iamnapo
 [@JounQin]: https://github.com/JounQin
 [@kaiyoma]: https://github.com/kaiyoma
 [@manuth]: https://github.com/manuth
+[@maxkomarychev]: https://github.com/maxkomarychev
+[@mgwalker]: https://github.com/mgwalker
 [@pmcelhaney]: https://github.com/pmcelhaney
 [@sergei-startsev]: https://github.com/sergei-startsev
 [@sompylasar]: https://github.com/sompylasar
 [@timkraut]: https://github.com/timkraut
 [@vikr01]: https://github.com/vikr01
-[@maxkomarychev]: https://github.com/maxkomarychev
-[@aladdin-add]: https://github.com/aladdin-add
-[@Hypnosphi]: https://github.com/Hypnosphi
\ No newline at end of file
diff --git a/utils/package.json b/utils/package.json
index f726b79585..787ce83a75 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -27,6 +27,7 @@
   "homepage": "https://github.com/import-js/eslint-plugin-import#readme",
   "dependencies": {
     "debug": "^3.2.7",
+    "find-up": "^2.1.0",
     "pkg-dir": "^2.0.0"
   }
 }
diff --git a/utils/pkgUp.js b/utils/pkgUp.js
new file mode 100644
index 0000000000..f73e3f7b25
--- /dev/null
+++ b/utils/pkgUp.js
@@ -0,0 +1,8 @@
+'use strict';
+exports.__esModule = true;
+
+const findUp = require('find-up');
+
+exports.default = function pkgUp(opts) {
+  return findUp.sync('package.json', opts);
+};
diff --git a/utils/readPkgUp.js b/utils/readPkgUp.js
new file mode 100644
index 0000000000..245afde681
--- /dev/null
+++ b/utils/readPkgUp.js
@@ -0,0 +1,52 @@
+'use strict';
+exports.__esModule = true;
+
+const fs = require('fs');
+const pkgUp = require('./pkgUp').default;
+
+function stripBOM(str) {
+  return str.replace(/^\uFEFF/, '');
+}
+
+/**
+ * Derived significantly from read-pkg-up@2.0.0. See license below.
+ * 
+ * @copyright Sindre Sorhus
+ * MIT License
+ *
+ * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+exports.default = function readPkgUp(opts) {
+  const fp = pkgUp(opts.cwd);
+
+  if (!fp) {
+    return {};
+  }
+
+  try {
+    return {
+      pkg: JSON.parse(stripBOM(fs.readFileSync(fp, { encoding: 'utf-8' }))),
+      path: fp,
+    };
+  } catch (e) {
+    return {};
+  }
+};

From 9ccdcb758f37ae5efe464699a5442d98cf1f73f3 Mon Sep 17 00:00:00 2001
From: Greg Walker <michael.walker@gsa.gov>
Date: Thu, 6 May 2021 14:55:00 -0500
Subject: [PATCH 374/767] [Refactor] switch to an internal replacement for
 `pkg-up` and `read-pkg-up`

---
 CHANGELOG.md                            | 9 +++++++--
 package.json                            | 3 ---
 src/core/packagePath.js                 | 8 ++++----
 src/rules/no-extraneous-dependencies.js | 4 ++--
 src/rules/no-import-module-exports.js   | 4 ++--
 src/rules/no-relative-packages.js       | 4 ++--
 src/rules/no-unused-modules.js          | 4 ++--
 tests/files/package.json                | 2 +-
 utils/readPkgUp.js                      | 2 +-
 9 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9203739fd3..26a6e76fba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Changed
+- [Refactor] switch to an internal replacement for `pkg-up` and `read-pkg-up` ([#2047], [@mgwalker])
+
 ### Added
 - [`no-unresolved`]: add `caseSensitiveStrict` option ([#1262], thanks [@sergei-startsev])
 - [`no-unused-modules`]: add eslint v8 support ([#2194], thanks [@coderaiser])
@@ -915,7 +918,7 @@ for info on changes for earlier releases.
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
 [#2158]: https://github.com/import-js/eslint-plugin-import/pull/2158
 [#2156]: https://github.com/import-js/eslint-plugin-import/pull/2156
-[#2149]: https://github.com/benmosher/eslint-plugin-import/pull/2149
+[#2149]: https://github.com/import-js/eslint-plugin-import/pull/2149
 [#2146]: https://github.com/import-js/eslint-plugin-import/pull/2146
 [#2140]: https://github.com/import-js/eslint-plugin-import/pull/2140
 [#2138]: https://github.com/import-js/eslint-plugin-import/pull/2138
@@ -928,6 +931,7 @@ for info on changes for earlier releases.
 [#2083]: https://github.com/import-js/eslint-plugin-import/pull/2083
 [#2075]: https://github.com/import-js/eslint-plugin-import/pull/2075
 [#2071]: https://github.com/import-js/eslint-plugin-import/pull/2071
+[#2047]: https://github.com/import-js/eslint-plugin-import/pull/2047
 [#2034]: https://github.com/import-js/eslint-plugin-import/pull/2034
 [#2028]: https://github.com/import-js/eslint-plugin-import/pull/2028
 [#2026]: https://github.com/import-js/eslint-plugin-import/pull/2026
@@ -1172,8 +1176,8 @@ for info on changes for earlier releases.
 [#2161]: https://github.com/import-js/eslint-plugin-import/issues/2161
 [#2118]: https://github.com/import-js/eslint-plugin-import/issues/2118
 [#2067]: https://github.com/import-js/eslint-plugin-import/issues/2067
-[#2056]: https://github.com/import-js/eslint-plugin-import/issues/2056
 [#2063]: https://github.com/import-js/eslint-plugin-import/issues/2063
+[#2056]: https://github.com/import-js/eslint-plugin-import/issues/2056
 [#1998]: https://github.com/import-js/eslint-plugin-import/issues/1998
 [#1965]: https://github.com/import-js/eslint-plugin-import/issues/1965
 [#1924]: https://github.com/import-js/eslint-plugin-import/issues/1924
@@ -1492,6 +1496,7 @@ for info on changes for earlier releases.
 [@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
 [@maxkomarychev]: https://github.com/maxkomarychev
 [@maxmalov]: https://github.com/maxmalov
+[@mgwalker]: https://github.com/mgwalker
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@mplewis]: https://github.com/mplewis
 [@nickofthyme]: https://github.com/nickofthyme
diff --git a/package.json b/package.json
index b845b609d2..08d5699f63 100644
--- a/package.json
+++ b/package.json
@@ -104,14 +104,11 @@
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
     "eslint-module-utils": "^2.6.2",
-    "find-up": "^2.0.0",
     "has": "^1.0.3",
     "is-core-module": "^2.6.0",
     "is-glob": "^4.0.1",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.4",
-    "pkg-up": "^2.0.0",
-    "read-pkg-up": "^3.0.0",
     "resolve": "^1.20.0",
     "tsconfig-paths": "^3.11.0"
   }
diff --git a/src/core/packagePath.js b/src/core/packagePath.js
index a8c3c67632..2b5a2d41ef 100644
--- a/src/core/packagePath.js
+++ b/src/core/packagePath.js
@@ -1,6 +1,6 @@
 import { dirname } from 'path';
-import findUp from 'find-up';
-import readPkgUp from 'read-pkg-up';
+import pkgUp from 'eslint-module-utils/pkgUp';
+import readPkgUp from 'eslint-module-utils/readPkgUp';
 
 
 export function getContextPackagePath(context) {
@@ -8,12 +8,12 @@ export function getContextPackagePath(context) {
 }
 
 export function getFilePackagePath(filePath) {
-  const fp = findUp.sync('package.json', { cwd: filePath });
+  const fp = pkgUp({ cwd: filePath });
   return dirname(fp);
 }
 
 export function getFilePackageName(filePath) {
-  const { pkg, path } = readPkgUp.sync({ cwd: filePath, normalize: false });
+  const { pkg, path } = readPkgUp({ cwd: filePath, normalize: false });
   if (pkg) {
     // recursion in case of intermediate esm package.json without name found
     return pkg.name || getFilePackageName(dirname(dirname(path)));
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 8d2e294ccb..06a724a09f 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -1,6 +1,6 @@
 import path from 'path';
 import fs from 'fs';
-import readPkgUp from 'read-pkg-up';
+import readPkgUp from 'eslint-module-utils/readPkgUp';
 import minimatch from 'minimatch';
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
@@ -69,7 +69,7 @@ function getDependencies(context, packageDir) {
       Object.assign(
         packageContent,
         extractDepFields(
-          readPkgUp.sync({ cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), normalize: false }).pkg
+          readPkgUp({ cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), normalize: false }).pkg
         )
       );
     }
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index 50ba212c87..45710929ce 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -1,9 +1,9 @@
 import minimatch from 'minimatch';
 import path from 'path';
-import pkgUp from 'pkg-up';
+import pkgUp from 'eslint-module-utils/pkgUp';
 
 function getEntryPoint(context) {
-  const pkgPath = pkgUp.sync(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
+  const pkgPath = pkgUp({ cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename() });
   try {
     return require.resolve(path.dirname(pkgPath));
   } catch (error) {
diff --git a/src/rules/no-relative-packages.js b/src/rules/no-relative-packages.js
index 90c1ecc701..714eb3f5e3 100644
--- a/src/rules/no-relative-packages.js
+++ b/src/rules/no-relative-packages.js
@@ -1,5 +1,5 @@
 import path from 'path';
-import readPkgUp from 'read-pkg-up';
+import readPkgUp from 'eslint-module-utils/readPkgUp';
 
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
@@ -7,7 +7,7 @@ import importType from '../core/importType';
 import docsUrl from '../docsUrl';
 
 function findNamedPackage(filePath) {
-  const found = readPkgUp.sync({ cwd: filePath, normalize: false });
+  const found = readPkgUp({ cwd: filePath });
   if (found.pkg && !found.pkg.name) {
     return findNamedPackage(path.join(found.path, '../..'));
   }
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index ab347bd8ce..068eb911c3 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -10,7 +10,7 @@ import resolve from 'eslint-module-utils/resolve';
 import visit from 'eslint-module-utils/visit';
 import docsUrl from '../docsUrl';
 import { dirname, join } from 'path';
-import readPkgUp from 'read-pkg-up';
+import readPkgUp from 'eslint-module-utils/readPkgUp';
 import values from 'object.values';
 import includes from 'array-includes';
 
@@ -352,7 +352,7 @@ const newDefaultImportExists = specifiers =>
   specifiers.some(({ type }) => type === IMPORT_DEFAULT_SPECIFIER);
 
 const fileIsInPkg = file => {
-  const { path, pkg } = readPkgUp.sync({ cwd: file, normalize: false });
+  const { path, pkg } = readPkgUp({ cwd: file });
   const basePath = dirname(path);
 
   const checkPkgFieldString = pkgField => {
diff --git a/tests/files/package.json b/tests/files/package.json
index de1d802753..365f02b6e0 100644
--- a/tests/files/package.json
+++ b/tests/files/package.json
@@ -12,7 +12,7 @@
     "esm-package": "^1.0.0",
     "jquery": "^3.1.0",
     "lodash.cond": "^4.3.0",
-    "pkg-up": "^1.0.0",
+    "find-up": "^1.0.0",
     "rxjs": "^1.0.0"
   },
   "optionalDependencies": {
diff --git a/utils/readPkgUp.js b/utils/readPkgUp.js
index 245afde681..6a6a1eea3e 100644
--- a/utils/readPkgUp.js
+++ b/utils/readPkgUp.js
@@ -35,7 +35,7 @@ function stripBOM(str) {
  * THE SOFTWARE.
  */
 exports.default = function readPkgUp(opts) {
-  const fp = pkgUp(opts.cwd);
+  const fp = pkgUp(opts);
 
   if (!fp) {
     return {};

From 4d15e268b694e9e9946ea16d9e1b94de1b850d7c Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Fri, 3 Sep 2021 15:45:36 -0700
Subject: [PATCH 375/767] [patch] TypeScript config: remove `.d.ts` from
 `import/parsers` setting and `import/extensions` setting

---
 CHANGELOG.md         | 7 +++++--
 config/typescript.js | 7 +++++--
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26a6e76fba..c430385c36 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 
 ### Changed
-- [Refactor] switch to an internal replacement for `pkg-up` and `read-pkg-up` ([#2047], [@mgwalker])
+- [Refactor] switch to an internal replacement for `pkg-up` and `read-pkg-up` ([#2047], thanks [@mgwalker])
+- [patch] TypeScript config: remove `.d.ts` from [`import/parsers` setting] and [`import/extensions` setting] ([#2220], thanks [@jablko])
 
 ### Added
 - [`no-unresolved`]: add `caseSensitiveStrict` option ([#1262], thanks [@sergei-startsev])
@@ -230,7 +231,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`order`]: add option pathGroupsExcludedImportTypes to allow ordering of external import types ([#1565], thanks [@Mairu])
 
 ### Fixed
-- [`no-unused-modules`]: fix usage of `import/extensions` settings ([#1560], thanks [@stekycz])
+- [`no-unused-modules`]: fix usage of [`import/extensions` setting] ([#1560], thanks [@stekycz])
 - [`extensions`]: ignore non-main modules ([#1563], thanks [@saschanaz])
 - TypeScript config: lookup for external modules in @types folder ([#1526], thanks [@joaovieira])
 - [`no-extraneous-dependencies`]: ensure `node.source` is truthy ([#1589], thanks [@ljharb])
@@ -909,6 +910,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2220]: https://github.com/import-js/eslint-plugin-import/pull/2220
 [#2219]: https://github.com/import-js/eslint-plugin-import/pull/2219
 [#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
 [#2196]: https://github.com/import-js/eslint-plugin-import/pull/2196
@@ -1444,6 +1446,7 @@ for info on changes for earlier releases.
 [@isiahmeadows]: https://github.com/isiahmeadows
 [@IvanGoncharov]: https://github.com/IvanGoncharov
 [@ivo-stefchev]: https://github.com/ivo-stefchev
+[@jablko]: https://github.com/jablko
 [@jakubsta]: https://github.com/jakubsta
 [@jeffshaver]: https://github.com/jeffshaver
 [@jf248]: https://github.com/jf248
diff --git a/config/typescript.js b/config/typescript.js
index 01b59f06b9..ed03fb3f6c 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -2,7 +2,10 @@
  * Adds `.jsx`, `.ts` and `.tsx` as an extension, and enables JSX/TSX parsing.
  */
 
-const allExtensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx'];
+// Omit `.d.ts` because 1) TypeScript compilation already confirms that
+// types are resolved, and 2) it would mask an unresolved
+// `.ts`/`.tsx`/`.js`/`.jsx` implementation.
+const allExtensions = ['.ts', '.tsx', '.js', '.jsx'];
 
 module.exports = {
 
@@ -10,7 +13,7 @@ module.exports = {
     'import/extensions': allExtensions,
     'import/external-module-folders': ['node_modules', 'node_modules/@types'],
     'import/parsers': {
-      '@typescript-eslint/parser': ['.ts', '.tsx', '.d.ts'],
+      '@typescript-eslint/parser': ['.ts', '.tsx'],
     },
     'import/resolver': {
       'node': {

From 4ed78671abf9768af2aec4ca61c377fed2e93f5f Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Sat, 11 Sep 2021 07:36:41 -0700
Subject: [PATCH 376/767] [Fix] `no-unresolved`: ignore type-only imports

---
 CHANGELOG.md                     | 11 +++++++----
 src/rules/no-unresolved.js       |  5 +++++
 tests/src/rules/no-unresolved.js | 22 +++++++++++++++++++++-
 3 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c430385c36..dbb9ecb828 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,16 +6,19 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
-### Changed
-- [Refactor] switch to an internal replacement for `pkg-up` and `read-pkg-up` ([#2047], thanks [@mgwalker])
-- [patch] TypeScript config: remove `.d.ts` from [`import/parsers` setting] and [`import/extensions` setting] ([#2220], thanks [@jablko])
-
 ### Added
 - [`no-unresolved`]: add `caseSensitiveStrict` option ([#1262], thanks [@sergei-startsev])
 - [`no-unused-modules`]: add eslint v8 support ([#2194], thanks [@coderaiser])
 - [`no-restricted-paths`]: add/restore glob pattern support ([#2219], thanks [@stropho])
 - [`no-unused-modules`]: support dynamic imports ([#1660], [#2212], thanks [@maxkomarychev], [@aladdin-add], [@Hypnosphi])
 
+### Fixed
+- [`no-unresolved`]: ignore type-only imports ([#2220], thanks [@jablko])
+
+### Changed
+- [Refactor] switch to an internal replacement for `pkg-up` and `read-pkg-up` ([#2047], thanks [@mgwalker])
+- [patch] TypeScript config: remove `.d.ts` from [`import/parsers` setting] and [`import/extensions` setting] ([#2220], thanks [@jablko])
+
 ## [2.24.2] - 2021-08-24
 
 ### Fixed
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index d7212560c4..408b6ff5e6 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -27,6 +27,11 @@ module.exports = {
     const options = context.options[0] || {};
 
     function checkSourceValue(source) {
+      // ignore type-only imports
+      if (source.parent && source.parent.importKind === 'type') {
+        return;
+      }
+
       const caseSensitive = !CASE_SENSITIVE_FS && options.caseSensitive !== false;
       const caseSensitiveStrict = !CASE_SENSITIVE_FS && options.caseSensitiveStrict;
 
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 19203074e1..9e6db8c04b 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -1,6 +1,6 @@
 import * as path from 'path';
 
-import { test, SYNTAX_CASES, testVersion } from '../utils';
+import { getTSParsers, test, SYNTAX_CASES, testVersion } from '../utils';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
@@ -441,3 +441,23 @@ ruleTester.run('import() with built-in parser', rule, {
     })) || [],
   ),
 });
+
+context('TypeScript', () => {
+  getTSParsers().filter(x => x !== require.resolve('typescript-eslint-parser')).forEach((parser) => {
+    ruleTester.run(`${parser}: no-unresolved ignore type-only`, rule, {
+      valid: [
+        test({
+          code: 'import type { JSONSchema7Type } from "@types/json-schema";',
+          parser,
+        }),
+      ],
+      invalid: [
+        test({
+          code: 'import { JSONSchema7Type } from "@types/json-schema";',
+          errors: [ "Unable to resolve path to module '@types/json-schema'." ],
+          parser,
+        }),
+      ],
+    });
+  });
+});

From 47ea669d2c68b2e6e67ed20d93b71d42147dbccd Mon Sep 17 00:00:00 2001
From: Remco Haszing <remcohaszing@gmail.com>
Date: Sun, 12 Sep 2021 16:08:21 +0200
Subject: [PATCH 377/767] [Fix] `order`: Fix import ordering in TypeScript
 module declarations

Without this, `import/order` checks if all imports in a file are sorted. The
autofix would then move all imports to the type of the file, breaking TypeScript
module declarations.

Closes #2217
---
 CHANGELOG.md             |  3 +++
 src/rules/order.js       | 47 ++++++++++++++++++++++++-------------
 tests/src/rules/order.js | 50 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dbb9ecb828..803333d08c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`no-unresolved`]: ignore type-only imports ([#2220], thanks [@jablko])
+- [`order`]: fix sorting imports inside TypeScript module declarations ([#2226], thanks [@remcohaszing])
 
 ### Changed
 - [Refactor] switch to an internal replacement for `pkg-up` and `read-pkg-up` ([#2047], thanks [@mgwalker])
@@ -913,6 +914,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2226]: https://github.com/import-js/eslint-plugin-import/pull/2226
 [#2220]: https://github.com/import-js/eslint-plugin-import/pull/2220
 [#2219]: https://github.com/import-js/eslint-plugin-import/pull/2219
 [#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
@@ -1520,6 +1522,7 @@ for info on changes for earlier releases.
 [@ramasilveyra]: https://github.com/ramasilveyra
 [@randallreedjr]: https://github.com/randallreedjr
 [@redbugz]: https://github.com/redbugz
+[@remcohaszing]: https://github.com/remcohaszing
 [@rfermann]: https://github.com/rfermann
 [@rhettlivingston]: https://github.com/rhettlivingston
 [@rhys-vdw]: https://github.com/rhys-vdw
diff --git a/src/rules/order.js b/src/rules/order.js
index 2f4ef08b70..194a3fd536 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -336,7 +336,7 @@ function registerNode(context, importEntry, ranks, imported, excludedImportTypes
   }
 }
 
-function isModuleLevelRequire(node) {
+function getRequireBlock(node) {
   let n = node;
   // Handle cases like `const baz = require('foo').bar.baz`
   // and `const foo = require('foo')()`
@@ -346,11 +346,13 @@ function isModuleLevelRequire(node) {
   ) {
     n = n.parent;
   }
-  return (
+  if (
     n.parent.type === 'VariableDeclarator' &&
     n.parent.parent.type === 'VariableDeclaration' &&
     n.parent.parent.parent.type === 'Program'
-  );
+  ) {
+    return n.parent.parent.parent;
+  }
 }
 
 const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object', 'type'];
@@ -605,7 +607,14 @@ module.exports = {
         },
       };
     }
-    let imported = [];
+    const importMap = new Map();
+
+    function getBlockImports(node) {
+      if (!importMap.has(node)) {
+        importMap.set(node, []);
+      }
+      return importMap.get(node);
+    }
 
     return {
       ImportDeclaration: function handleImports(node) {
@@ -621,7 +630,7 @@ module.exports = {
               type: 'import',
             },
             ranks,
-            imported,
+            getBlockImports(node.parent),
             pathGroupsExcludedImportTypes
           );
         }
@@ -652,12 +661,16 @@ module.exports = {
             type,
           },
           ranks,
-          imported,
+          getBlockImports(node.parent),
           pathGroupsExcludedImportTypes
         );
       },
       CallExpression: function handleRequires(node) {
-        if (!isStaticRequire(node) || !isModuleLevelRequire(node)) {
+        if (!isStaticRequire(node)) {
+          return;
+        }
+        const block = getRequireBlock(node);
+        if (!block) {
           return;
         }
         const name = node.arguments[0].value;
@@ -670,22 +683,24 @@ module.exports = {
             type: 'require',
           },
           ranks,
-          imported,
+          getBlockImports(block),
           pathGroupsExcludedImportTypes
         );
       },
       'Program:exit': function reportAndReset() {
-        if (newlinesBetweenImports !== 'ignore') {
-          makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
-        }
+        importMap.forEach((imported) => {
+          if (newlinesBetweenImports !== 'ignore') {
+            makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
+          }
 
-        if (alphabetize.order !== 'ignore') {
-          mutateRanksToAlphabetize(imported, alphabetize);
-        }
+          if (alphabetize.order !== 'ignore') {
+            mutateRanksToAlphabetize(imported, alphabetize);
+          }
 
-        makeOutOfOrderReport(context, imported);
+          makeOutOfOrderReport(context, imported);
+        });
 
-        imported = [];
+        importMap.clear();
       },
     };
   },
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 61bf1bb70f..146306259f 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2462,6 +2462,24 @@ context('TypeScript', function () {
               },
             ],
           }),
+          // Imports inside module declaration
+          test({
+            code: `
+              import type { CopyOptions } from 'fs';
+              import type { ParsedPath } from 'path';
+
+              declare module 'my-module' {
+                import type { CopyOptions } from 'fs';
+                import type { ParsedPath } from 'path';
+              }
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+              },
+            ],
+          }),
         ],
         invalid: [
           // Option alphabetize: {order: 'asc'}
@@ -2655,6 +2673,38 @@ context('TypeScript', function () {
             }],
             options: [{ warnOnUnassignedImports: true }],
           }),
+          // Imports inside module declaration
+          test({
+            code: `
+              import type { ParsedPath } from 'path';
+              import type { CopyOptions } from 'fs';
+
+              declare module 'my-module' {
+                import type { ParsedPath } from 'path';
+                import type { CopyOptions } from 'fs';
+              }
+            `,
+            output: `
+              import type { CopyOptions } from 'fs';
+              import type { ParsedPath } from 'path';
+
+              declare module 'my-module' {
+                import type { CopyOptions } from 'fs';
+                import type { ParsedPath } from 'path';
+              }
+            `,
+            errors: [{
+              message: '`fs` import should occur before import of `path`',
+            },{
+              message: '`fs` import should occur before import of `path`',
+            }],
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+              },
+            ],
+          }),
         ],
       });
     });

From 58fe766e1295ce0532cb44ddd81b661625a0941d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 18 Sep 2021 09:11:57 -0700
Subject: [PATCH 378/767] [Tests] ignore resolver tests, scripts, and unused
 memo-parser

---
 .nycrc | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/.nycrc b/.nycrc
index 20bcfca222..a19f5b8b1c 100644
--- a/.nycrc
+++ b/.nycrc
@@ -10,6 +10,9 @@
 	"exclude": [
 		"coverage",
 		"test",
-		"tests"
+		"tests",
+		"resolvers/*/test",
+		"scripts",
+		"memo-parser"
 	]
 }

From 64423e98dee4ea7185e16796a981ec53537f2913 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 18 Sep 2021 17:01:24 -0700
Subject: [PATCH 379/767] [Tests] add passing test for export-star

Closes #2093
---
 tests/files/export-star-4/module/feature.jsx |  3 +++
 tests/files/export-star-4/module/index.ts    |  1 +
 tests/src/rules/export.js                    | 12 ++++++++++++
 3 files changed, 16 insertions(+)
 create mode 100644 tests/files/export-star-4/module/feature.jsx
 create mode 100644 tests/files/export-star-4/module/index.ts

diff --git a/tests/files/export-star-4/module/feature.jsx b/tests/files/export-star-4/module/feature.jsx
new file mode 100644
index 0000000000..82fab1e505
--- /dev/null
+++ b/tests/files/export-star-4/module/feature.jsx
@@ -0,0 +1,3 @@
+export function func() {
+    console.log('Hello world');
+}
diff --git a/tests/files/export-star-4/module/index.ts b/tests/files/export-star-4/module/index.ts
new file mode 100644
index 0000000000..42a9f556aa
--- /dev/null
+++ b/tests/files/export-star-4/module/index.ts
@@ -0,0 +1 @@
+export * from './feature';
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index efc6e402ff..c4e3e8e606 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -245,6 +245,18 @@ context('TypeScript', function () {
             export {Bar as default};
           `,
         }, parserConfig)),
+
+        test({
+          ...parserConfig,
+          code: `
+            export * from './module';
+          `,
+          filename: testFilePath('export-star-4/index.js'),
+          settings: {
+            ...parserConfig.settings,
+            'import/extensions': ['.js', '.ts', '.jsx'],
+          },
+        }),
       ],
       invalid: [
         // type/value name clash

From fd85369fc219c40862d2afcfb11ad053387ba967 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 18 Sep 2021 22:50:22 -0700
Subject: [PATCH 380/767] [Tests] skip failing test on eslint < 6 + node < 8

---
 tests/src/rules/export.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index c4e3e8e606..29fae41015 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -246,7 +246,7 @@ context('TypeScript', function () {
           `,
         }, parserConfig)),
 
-        test({
+        ...(semver.satisfies(process.version, '< 8') && semver.satisfies(eslintPkg.version, '< 6') ? [] : test({
           ...parserConfig,
           code: `
             export * from './module';
@@ -256,7 +256,7 @@ context('TypeScript', function () {
             ...parserConfig.settings,
             'import/extensions': ['.js', '.ts', '.jsx'],
           },
-        }),
+        })),
       ],
       invalid: [
         // type/value name clash

From 471790f9ff05c65279d2da8a280c6c57d8b14f65 Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Sun, 19 Sep 2021 16:23:41 -0700
Subject: [PATCH 381/767] [Tests] fix skip usage

---
 tests/src/rules/max-dependencies.js           | 2 +-
 tests/src/rules/no-extraneous-dependencies.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/src/rules/max-dependencies.js b/tests/src/rules/max-dependencies.js
index fc3b541f50..bab38496e0 100644
--- a/tests/src/rules/max-dependencies.js
+++ b/tests/src/rules/max-dependencies.js
@@ -91,7 +91,7 @@ ruleTester.run('max-dependencies', rule, {
   ],
 });
 
-context('TypeScript', { skip: semver.satisfies(eslintPkg.version, '>5.0.0') }, () => {
+(semver.satisfies(eslintPkg.version, '>5.0.0') ? describe.skip : describe)('TypeScript', () => {
   getTSParsers().forEach((parser) => {
     ruleTester.run(`max-dependencies (${parser.replace(process.cwd(), '.')})`, rule, {
       valid: [    
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index c6abcd6e4a..af139d7b6b 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -381,7 +381,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
 });
 
 // TODO: figure out why these tests fail in eslint 4
-describe('TypeScript', { skip: semver.satisfies(eslintPkg.version, '^4') }, function () {
+(semver.satisfies(eslintPkg.version, '^4') ? describe.skip : describe)('TypeScript', () => {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
       parser,

From 28669b97cea32e01f873fc62a524e48e4d99feb0 Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Sun, 19 Sep 2021 16:57:29 -0700
Subject: [PATCH 382/767] [Tests] `no-extraneous-dependencies` ignores
 unresolved imports

---
 .../with-typescript-dev-dependencies/package.json  |  2 +-
 tests/src/rules/no-extraneous-dependencies.js      | 14 +++++++-------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/tests/files/with-typescript-dev-dependencies/package.json b/tests/files/with-typescript-dev-dependencies/package.json
index e17fbd9777..f859f50850 100644
--- a/tests/files/with-typescript-dev-dependencies/package.json
+++ b/tests/files/with-typescript-dev-dependencies/package.json
@@ -1,5 +1,5 @@
 {
   "devDependencies": {
-    "@types/json-schema": "*"
+    "a": "*"
   }
 }
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index af139d7b6b..29604af170 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -395,16 +395,16 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       ruleTester.run('no-extraneous-dependencies', rule, {
         valid: [
           test(Object.assign({
-            code: 'import type { JSONSchema7Type } from "@types/json-schema";',
+            code: 'import type T from "a";',
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
           }, parserConfig)),
         ],
         invalid: [
           test(Object.assign({
-            code: 'import { JSONSchema7Type } from "@types/json-schema";',
+            code: 'import T from "a";',
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             errors: [{
-              message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+              message: "'a' should be listed in the project's dependencies, not devDependencies.",
             }],
           }, parserConfig)),
         ],
@@ -414,17 +414,17 @@ ruleTester.run('no-extraneous-dependencies', rule, {
         valid: [],
         invalid: [
           test(Object.assign({
-            code: 'import { JSONSchema7Type } from "@types/json-schema"; /* typescript-eslint-parser */',
+            code: 'import T from "a"; /* typescript-eslint-parser */',
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             errors: [{
-              message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+              message: "'a' should be listed in the project's dependencies, not devDependencies.",
             }],
           }, parserConfig)),
           test(Object.assign({
-            code: 'import type { JSONSchema7Type } from "@types/json-schema"; /* typescript-eslint-parser */',
+            code: 'import type T from "a"; /* typescript-eslint-parser */',
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             errors: [{
-              message: "'@types/json-schema' should be listed in the project's dependencies, not devDependencies.",
+              message: "'a' should be listed in the project's dependencies, not devDependencies.",
             }],
           }, parserConfig)),
         ],

From 47e9c89aa7e4e565b166d1b00f01484c3c911582 Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Mon, 20 Sep 2021 11:52:43 -0700
Subject: [PATCH 383/767] [Tests] type-only imports were added in TypeScript
 ESTree 2.23.0

---
 tests/src/rules/first.js                      |  1 -
 tests/src/rules/max-dependencies.js           | 81 +++++++++---------
 tests/src/rules/no-duplicates.js              |  1 +
 tests/src/rules/no-extraneous-dependencies.js | 82 +++++++------------
 tests/src/rules/no-unresolved.js              |  1 +
 tests/src/rules/order.js                      |  1 +
 6 files changed, 73 insertions(+), 94 deletions(-)

diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index 9d27870677..05328e51e9 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -80,7 +80,6 @@ ruleTester.run('first', rule, {
 
 context('TypeScript', function () {
   getTSParsers()
-    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
     .forEach((parser) => {
       const parserConfig = {
         parser,
diff --git a/tests/src/rules/max-dependencies.js b/tests/src/rules/max-dependencies.js
index bab38496e0..6d80bbf046 100644
--- a/tests/src/rules/max-dependencies.js
+++ b/tests/src/rules/max-dependencies.js
@@ -1,8 +1,6 @@
 import { test, getTSParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
-import eslintPkg from 'eslint/package.json';
-import semver from 'semver';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/max-dependencies');
@@ -91,43 +89,46 @@ ruleTester.run('max-dependencies', rule, {
   ],
 });
 
-(semver.satisfies(eslintPkg.version, '>5.0.0') ? describe.skip : describe)('TypeScript', () => {
-  getTSParsers().forEach((parser) => {
-    ruleTester.run(`max-dependencies (${parser.replace(process.cwd(), '.')})`, rule, {
-      valid: [    
-        test({
-          code: 'import type { x } from \'./foo\'; import { y } from \'./bar\';',
-          parser,
-          options: [{
-            max: 1,
-            ignoreTypeImports: true,
-          }],
-        }),
-      ],
-      invalid: [    
-        test({
-          code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'',
-          parser,
-          options: [{
-            max: 1,
-          }],
-          errors: [
-            'Maximum number of dependencies (1) exceeded.',
-          ],
-        }),
-    
-        test({
-          code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'; import type { z } from \'./baz\'',
-          parser,
-          options: [{
-            max: 2,
-            ignoreTypeImports: false,
-          }],
-          errors: [
-            'Maximum number of dependencies (2) exceeded.',
-          ],
-        }),
-      ],
+describe('TypeScript', () => {
+  getTSParsers()
+    // Type-only imports were added in TypeScript ESTree 2.23.0
+    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .forEach((parser) => {
+      ruleTester.run(`max-dependencies (${parser.replace(process.cwd(), '.')})`, rule, {
+        valid: [
+          test({
+            code: 'import type { x } from \'./foo\'; import { y } from \'./bar\';',
+            parser,
+            options: [{
+              max: 1,
+              ignoreTypeImports: true,
+            }],
+          }),
+        ],
+        invalid: [
+          test({
+            code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'',
+            parser,
+            options: [{
+              max: 1,
+            }],
+            errors: [
+              'Maximum number of dependencies (1) exceeded.',
+            ],
+          }),
+
+          test({
+            code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'; import type { z } from \'./baz\'',
+            parser,
+            options: [{
+              max: 2,
+              ignoreTypeImports: false,
+            }],
+            errors: [
+              'Maximum number of dependencies (2) exceeded.',
+            ],
+          }),
+        ],
+      });
     });
-  });
 });
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index e550b63ce7..ad39543f81 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -417,6 +417,7 @@ import {x,y} from './foo'
 
 context('TypeScript', function () {
   getNonDefaultParsers()
+    // Type-only imports were added in TypeScript ESTree 2.23.0
     .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
     .forEach((parser) => {
       const parserConfig = {
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 29604af170..852dbdf4e7 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -2,8 +2,6 @@ import { getTSParsers, test, testFilePath } from '../utils';
 import typescriptConfig from '../../../config/typescript';
 import path from 'path';
 import fs from 'fs';
-import semver from 'semver';
-import eslintPkg from 'eslint/package.json';
 
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
@@ -380,18 +378,19 @@ ruleTester.run('no-extraneous-dependencies', rule, {
   ],
 });
 
-// TODO: figure out why these tests fail in eslint 4
-(semver.satisfies(eslintPkg.version, '^4') ? describe.skip : describe)('TypeScript', () => {
-  getTSParsers().forEach((parser) => {
-    const parserConfig = {
-      parser,
-      settings: {
-        'import/parsers': { [parser]: ['.ts'] },
-        'import/resolver': { 'eslint-import-resolver-typescript': true },
-      },
-    };
+describe('TypeScript', () => {
+  getTSParsers()
+    // Type-only imports were added in TypeScript ESTree 2.23.0
+    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .forEach((parser) => {
+      const parserConfig = {
+        parser,
+        settings: {
+          'import/parsers': { [parser]: ['.ts'] },
+          'import/resolver': { 'eslint-import-resolver-typescript': true },
+        },
+      };
 
-    if (parser !== require.resolve('typescript-eslint-parser')) {
       ruleTester.run('no-extraneous-dependencies', rule, {
         valid: [
           test(Object.assign({
@@ -409,45 +408,22 @@ ruleTester.run('no-extraneous-dependencies', rule, {
           }, parserConfig)),
         ],
       });
-    } else {
-      ruleTester.run('no-extraneous-dependencies', rule, {
-        valid: [],
-        invalid: [
-          test(Object.assign({
-            code: 'import T from "a"; /* typescript-eslint-parser */',
-            options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
-            errors: [{
-              message: "'a' should be listed in the project's dependencies, not devDependencies.",
-            }],
-          }, parserConfig)),
-          test(Object.assign({
-            code: 'import type T from "a"; /* typescript-eslint-parser */',
-            options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
-            errors: [{
-              message: "'a' should be listed in the project's dependencies, not devDependencies.",
-            }],
-          }, parserConfig)),
-        ],
-      });
-    }
-  });
+    });
 });
 
-if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-  typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', rule, {
-    valid: [
-      test({
-        code: 'import type MyType from "not-a-dependency";',
-        filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
-        parser: require.resolve('babel-eslint'),
-      }),
-      test({
-        code: 'import type { MyType } from "not-a-dependency";',
-        filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
-        parser: require.resolve('babel-eslint'),
-      }),
-    ],
-    invalid: [
-    ],
-  });
-}
+typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', rule, {
+  valid: [
+    test({
+      code: 'import type MyType from "not-a-dependency";',
+      filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      parser: require.resolve('babel-eslint'),
+    }),
+    test({
+      code: 'import type { MyType } from "not-a-dependency";',
+      filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      parser: require.resolve('babel-eslint'),
+    }),
+  ],
+  invalid: [
+  ],
+});
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 9e6db8c04b..a5ff6da5d1 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -443,6 +443,7 @@ ruleTester.run('import() with built-in parser', rule, {
 });
 
 context('TypeScript', () => {
+  // Type-only imports were added in TypeScript ESTree 2.23.0
   getTSParsers().filter(x => x !== require.resolve('typescript-eslint-parser')).forEach((parser) => {
     ruleTester.run(`${parser}: no-unresolved ignore type-only`, rule, {
       valid: [
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 146306259f..4b15cec898 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2283,6 +2283,7 @@ ruleTester.run('order', rule, {
 
 context('TypeScript', function () {
   getNonDefaultParsers()
+    // Type-only imports were added in TypeScript ESTree 2.23.0
     .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
     .forEach((parser) => {
       const parserConfig = {

From 430d16c9b9937c8695781f871ff87c3d63cda2d3 Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Mon, 20 Sep 2021 17:38:42 -0700
Subject: [PATCH 384/767] [Tests] eslint-import-resolver-typescript@1.0.2
 doesn't resolve .js

---
 tests/src/rules/no-extraneous-dependencies.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 852dbdf4e7..131604ad95 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -387,7 +387,7 @@ describe('TypeScript', () => {
         parser,
         settings: {
           'import/parsers': { [parser]: ['.ts'] },
-          'import/resolver': { 'eslint-import-resolver-typescript': true },
+          'import/resolver': ['node', 'typescript'],
         },
       };
 

From 4f0f560544b4d6dcd2d1b7d5880bd5238099f979 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 21 Sep 2021 08:59:37 -0700
Subject: [PATCH 385/767] [Docs] `no-namespace`: fix a typo

See https://github.com/import-js/eslint-plugin-import/pull/2112#issuecomment-923994768
---
 docs/rules/no-namespace.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/rules/no-namespace.md b/docs/rules/no-namespace.md
index e987260513..854f65d6f9 100644
--- a/docs/rules/no-namespace.md
+++ b/docs/rules/no-namespace.md
@@ -22,7 +22,7 @@ import defaultExport, { a, b }  from './foobar'
 ```
 
 ```js
-/* eslint import/no-namespace: ["error", {ignore: ['*.ext']] */
+/* eslint import/no-namespace: ["error", {ignore: ['*.ext']}] */
 import * as bar from './ignored-module.ext';
 ```
 

From dd814245b7f769a84235f2ffb7204287d47001ba Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Tue, 21 Sep 2021 08:40:32 -0700
Subject: [PATCH 386/767] [Refactor] `no-unresolved`,
 `no-extraneous-dependencies`: moduleVisitor usage

---
 CHANGELOG.md                            | 2 ++
 src/rules/no-extraneous-dependencies.js | 1 -
 src/rules/no-unresolved.js              | 4 ++--
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 803333d08c..6b0f95e286 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - [Refactor] switch to an internal replacement for `pkg-up` and `read-pkg-up` ([#2047], thanks [@mgwalker])
 - [patch] TypeScript config: remove `.d.ts` from [`import/parsers` setting] and [`import/extensions` setting] ([#2220], thanks [@jablko])
+- [Refactor] [`no-unresolved`], [`no-extraneous-dependencies`]: moduleVisitor usage ([#2233], thanks [@jablko])
 
 ## [2.24.2] - 2021-08-24
 
@@ -914,6 +915,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2233]: https://github.com/import-js/eslint-plugin-import/pull/2233
 [#2226]: https://github.com/import-js/eslint-plugin-import/pull/2226
 [#2220]: https://github.com/import-js/eslint-plugin-import/pull/2220
 [#2219]: https://github.com/import-js/eslint-plugin-import/pull/2219
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 06a724a09f..25a91aef51 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -162,7 +162,6 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types
   if (
     node.importKind === 'type' ||
-    (node.parent && node.parent.importKind === 'type') ||
     node.importKind === 'typeof'
   ) {
     return;
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index 408b6ff5e6..5491018976 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -26,9 +26,9 @@ module.exports = {
   create(context) {
     const options = context.options[0] || {};
 
-    function checkSourceValue(source) {
+    function checkSourceValue(source, node) {
       // ignore type-only imports
-      if (source.parent && source.parent.importKind === 'type') {
+      if (node.importKind === 'type') {
         return;
       }
 

From 9a744f7385dc12cb3d0376ab7268fed3940e46a4 Mon Sep 17 00:00:00 2001
From: Brody McKee <mrmckeb@gmail.com>
Date: Tue, 28 Sep 2021 12:40:32 +0300
Subject: [PATCH 387/767] [Fix] `default`, `ExportMap`: Resolve extended
 TypeScript configuration files

Fixes #1908.
---
 CHANGELOG.md                                  |  3 +++
 src/ExportMap.js                              | 22 +++++++++++--------
 .../typescript-extended-config/index.d.ts     |  3 +++
 .../tsconfig.base.json                        |  5 +++++
 .../typescript-extended-config/tsconfig.json  |  4 ++++
 tests/src/rules/default.js                    | 11 ++++++++++
 6 files changed, 39 insertions(+), 9 deletions(-)
 create mode 100644 tests/files/typescript-extended-config/index.d.ts
 create mode 100644 tests/files/typescript-extended-config/tsconfig.base.json
 create mode 100644 tests/files/typescript-extended-config/tsconfig.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b0f95e286..264b20c734 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`no-unresolved`]: ignore type-only imports ([#2220], thanks [@jablko])
 - [`order`]: fix sorting imports inside TypeScript module declarations ([#2226], thanks [@remcohaszing])
+- [`default`], `ExportMap`: Resolve extended TypeScript configuration files ([#2240], thanks [@mrmckeb])
 
 ### Changed
 - [Refactor] switch to an internal replacement for `pkg-up` and `read-pkg-up` ([#2047], thanks [@mgwalker])
@@ -915,6 +916,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2240]: https://github.com/import-js/eslint-plugin-import/pull/2240
 [#2233]: https://github.com/import-js/eslint-plugin-import/pull/2233
 [#2226]: https://github.com/import-js/eslint-plugin-import/pull/2226
 [#2220]: https://github.com/import-js/eslint-plugin-import/pull/2220
@@ -1509,6 +1511,7 @@ for info on changes for earlier releases.
 [@mgwalker]: https://github.com/mgwalker
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@mplewis]: https://github.com/mplewis
+[@mrmckeb]: https://github.com/mrmckeb
 [@nickofthyme]: https://github.com/nickofthyme
 [@nicolashenry]: https://github.com/nicolashenry
 [@noelebrun]: https://github.com/noelebrun
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 53091e4668..d818fa6ca8 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -1,4 +1,5 @@
 import fs from 'fs';
+import { dirname } from 'path';
 
 import doctrine from 'doctrine';
 
@@ -18,7 +19,7 @@ import { tsConfigLoader } from 'tsconfig-paths/lib/tsconfig-loader';
 
 import includes from 'array-includes';
 
-let parseConfigFileTextToJson;
+let ts;
 
 const log = debug('eslint-plugin-import:ExportMap');
 
@@ -525,12 +526,15 @@ ExportMap.parse = function (path, content, context) {
     });
     try {
       if (tsConfigInfo.tsConfigPath !== undefined) {
-        const jsonText = fs.readFileSync(tsConfigInfo.tsConfigPath).toString();
-        if (!parseConfigFileTextToJson) {
-          // this is because projects not using TypeScript won't have typescript installed
-          ({ parseConfigFileTextToJson } = require('typescript'));
-        }
-        return parseConfigFileTextToJson(tsConfigInfo.tsConfigPath, jsonText).config;
+        // Projects not using TypeScript won't have `typescript` installed.
+        if (!ts) { ts = require('typescript'); }
+  
+        const configFile = ts.readConfigFile(tsConfigInfo.tsConfigPath, ts.sys.readFile);
+        return ts.parseJsonConfigFileContent(
+          configFile.config,
+          ts.sys,
+          dirname(tsConfigInfo.tsConfigPath),
+        );
       }
     } catch (e) {
       // Catch any errors
@@ -545,11 +549,11 @@ ExportMap.parse = function (path, content, context) {
     }).digest('hex');
     let tsConfig = tsConfigCache.get(cacheKey);
     if (typeof tsConfig === 'undefined') {
-      tsConfig = readTsConfig();
+      tsConfig = readTsConfig(context);
       tsConfigCache.set(cacheKey, tsConfig);
     }
 
-    return tsConfig && tsConfig.compilerOptions ? tsConfig.compilerOptions.esModuleInterop : false;
+    return tsConfig && tsConfig.options ? tsConfig.options.esModuleInterop : false;
   }
 
   ast.body.forEach(function (n) {
diff --git a/tests/files/typescript-extended-config/index.d.ts b/tests/files/typescript-extended-config/index.d.ts
new file mode 100644
index 0000000000..2ad4822f7c
--- /dev/null
+++ b/tests/files/typescript-extended-config/index.d.ts
@@ -0,0 +1,3 @@
+export = FooBar;
+
+declare namespace FooBar {}
diff --git a/tests/files/typescript-extended-config/tsconfig.base.json b/tests/files/typescript-extended-config/tsconfig.base.json
new file mode 100644
index 0000000000..2f98042715
--- /dev/null
+++ b/tests/files/typescript-extended-config/tsconfig.base.json
@@ -0,0 +1,5 @@
+{
+  "compilerOptions": {
+    "esModuleInterop": true
+  }
+}
diff --git a/tests/files/typescript-extended-config/tsconfig.json b/tests/files/typescript-extended-config/tsconfig.json
new file mode 100644
index 0000000000..97a3309607
--- /dev/null
+++ b/tests/files/typescript-extended-config/tsconfig.json
@@ -0,0 +1,4 @@
+{
+  "extends": "./tsconfig.base.json",
+  "compilerOptions": {}
+}
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index 15101fc0cd..0274e43745 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -231,6 +231,17 @@ context('TypeScript', function () {
             tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-react-test-renderer/'),
           },
         }),
+        test({
+          code: `import Foo from "./typescript-extended-config"`,
+          parser,
+          settings: {
+            'import/parsers': { [parser]: ['.ts'] },
+            'import/resolver': { 'eslint-import-resolver-typescript': true },
+          },
+          parserOptions: {
+            tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-extended-config/'),
+          },
+        }),
         test({
           code: `import foobar from "./typescript-export-assign-property"`,
           parser,

From 62e2d883f6a6c57a71aa6594a79ea11ad4a5939a Mon Sep 17 00:00:00 2001
From: yosuke ota <otameshiyo23@gmail.com>
Date: Mon, 16 Aug 2021 12:48:15 +0900
Subject: [PATCH 388/767] [New] Support `eslint` v8

---
 .github/workflows/node-4+.yml | 21 +++++++++++++++++++++
 .nycrc                        |  3 ++-
 CHANGELOG.md                  |  3 +++
 package.json                  |  5 +++--
 tests/dep-time-travel.sh      |  8 ++++++++
 tests/src/cli.js              |  2 +-
 6 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index f2498807cc..aaa11f3a08 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -26,6 +26,7 @@ jobs:
       matrix:
         node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
         eslint:
+          - 8
           - 7
           - 6
           - 5
@@ -44,24 +45,44 @@ jobs:
             env:
               TS_PARSER: 2
         exclude:
+          - node-version: 15
+            eslint: 8
+          - node-version: 13
+            eslint: 8
+          - node-version: 11
+            eslint: 8
+          - node-version: 10
+            eslint: 8
+          - node-version: 9
+            eslint: 8
           - node-version: 9
             eslint: 7
+          - node-version: 8
+            eslint: 8
           - node-version: 8
             eslint: 7
+          - node-version: 7
+            eslint: 8
           - node-version: 7
             eslint: 7
           - node-version: 7
             eslint: 6
+          - node-version: 6
+            eslint: 8
           - node-version: 6
             eslint: 7
           - node-version: 6
             eslint: 6
+          - node-version: 5
+            eslint: 8
           - node-version: 5
             eslint: 7
           - node-version: 5
             eslint: 6
           - node-version: 5
             eslint: 5
+          - node-version: 4
+            eslint: 8
           - node-version: 4
             eslint: 7
           - node-version: 4
diff --git a/.nycrc b/.nycrc
index a19f5b8b1c..5d75e2157c 100644
--- a/.nycrc
+++ b/.nycrc
@@ -13,6 +13,7 @@
 		"tests",
 		"resolvers/*/test",
 		"scripts",
-		"memo-parser"
+		"memo-parser",
+		"lib"
 	]
 }
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 264b20c734..b7dc919a42 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 
 ### Added
+- Support `eslint` v8 ([#2191], thanks [@ota-meshi])
 - [`no-unresolved`]: add `caseSensitiveStrict` option ([#1262], thanks [@sergei-startsev])
 - [`no-unused-modules`]: add eslint v8 support ([#2194], thanks [@coderaiser])
 - [`no-restricted-paths`]: add/restore glob pattern support ([#2219], thanks [@stropho])
@@ -924,6 +925,7 @@ for info on changes for earlier releases.
 [#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
 [#2196]: https://github.com/import-js/eslint-plugin-import/pull/2196
 [#2194]: https://github.com/import-js/eslint-plugin-import/pull/2194
+[#2191]: https://github.com/import-js/eslint-plugin-import/pull/2191
 [#2184]: https://github.com/import-js/eslint-plugin-import/pull/2184
 [#2179]: https://github.com/import-js/eslint-plugin-import/pull/2179
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
@@ -1517,6 +1519,7 @@ for info on changes for earlier releases.
 [@noelebrun]: https://github.com/noelebrun
 [@ntdb]: https://github.com/ntdb
 [@nwalters512]: https://github.com/nwalters512
+[@ota-meshi]: https://github.com/ota-meshi
 [@panrafal]: https://github.com/panrafal
 [@paztis]: https://github.com/paztis
 [@pcorpet]: https://github.com/pcorpet
diff --git a/package.json b/package.json
index 08d5699f63..31d54e2013 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,8 @@
     "babylon": "^6.18.0",
     "chai": "^4.3.4",
     "cross-env": "^4.0.0",
-    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0",
+    "escope": "^3.6.0",
+    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8",
     "eslint-import-resolver-node": "file:./resolvers/node",
     "eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
@@ -95,7 +96,7 @@
     "typescript-eslint-parser": "^15 || ^22.0.0"
   },
   "peerDependencies": {
-    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0"
+    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
   },
   "dependencies": {
     "array-includes": "^3.1.3",
diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index 2e24595761..116a4bfd4f 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -34,3 +34,11 @@ if [[ "$TRAVIS_NODE_VERSION" -lt "8" ]]; then
   echo "Downgrading eslint-import-resolver-typescript..."
   npm i --no-save eslint-import-resolver-typescript@1.0.2
 fi
+
+if [ "${ESLINT_VERSION}" = '8' ]; then
+  # This is a workaround for the crash in the initial processing of the ESLint class.
+  echo "Installing self"
+  npm i --no-save eslint-plugin-import@'.' -f
+  echo "Build self"
+  npm run build
+fi
diff --git a/tests/src/cli.js b/tests/src/cli.js
index 9867e04985..5b7e705b0e 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -97,7 +97,7 @@ describe('CLI regression tests', function () {
                   },
                 ],
                 errorCount: 1,
-                ...(semver.satisfies(eslintPkg.version, '>= 7.32 || ^8.0.0-0') && {
+                ...(semver.satisfies(eslintPkg.version, '>= 7.32 || ^8.0.0') && {
                   fatalErrorCount: 0,
                 }),
                 warningCount: 0,

From 0e857b69f860d60d7486462101d5378783e5f079 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 11 Oct 2021 09:30:13 -0700
Subject: [PATCH 389/767] [Deps] update `array-includes`,
 `array.prototype.flat`, `is-core-module`, `is-glob`, `object.values`

---
 package.json | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index 31d54e2013..9d04b7aff7 100644
--- a/package.json
+++ b/package.json
@@ -99,17 +99,17 @@
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
   },
   "dependencies": {
-    "array-includes": "^3.1.3",
-    "array.prototype.flat": "^1.2.4",
+    "array-includes": "^3.1.4",
+    "array.prototype.flat": "^1.2.5",
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
     "eslint-module-utils": "^2.6.2",
     "has": "^1.0.3",
-    "is-core-module": "^2.6.0",
-    "is-glob": "^4.0.1",
+    "is-core-module": "^2.7.0",
+    "is-glob": "^4.0.3",
     "minimatch": "^3.0.4",
-    "object.values": "^1.1.4",
+    "object.values": "^1.1.5",
     "resolve": "^1.20.0",
     "tsconfig-paths": "^3.11.0"
   }

From c117be532152af7f55675607a92339361fe0968b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 11 Oct 2021 09:37:01 -0700
Subject: [PATCH 390/767] [Dev Deps] update `array.prototype.flatmap`, `glob`;
 remove `babel-preset-es2015-argon`

---
 package.json                   | 5 ++---
 resolvers/webpack/package.json | 1 -
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 9d04b7aff7..f7b7305139 100644
--- a/package.json
+++ b/package.json
@@ -56,14 +56,13 @@
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3",
-    "array.prototype.flatmap": "^1.2.4",
+    "array.prototype.flatmap": "^1.2.5",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
     "babel-eslint": "=8.0.3 || ^8.2.6",
     "babel-plugin-istanbul": "^4.1.6",
     "babel-plugin-module-resolver": "^2.7.1",
     "babel-preset-airbnb": "^2.6.0",
-    "babel-preset-es2015-argon": "latest",
     "babel-preset-flow": "^6.23.0",
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
@@ -80,7 +79,7 @@
     "eslint-plugin-import": "2.x",
     "eslint-plugin-json": "^2.1.2",
     "fs-copy-file-sync": "^1.1.1",
-    "glob": "^7.1.7",
+    "glob": "^7.2.0",
     "in-publish": "^2.0.1",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index bd6269e2ff..2afc84e148 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -48,7 +48,6 @@
   },
   "devDependencies": {
     "babel-plugin-istanbul": "^4.1.6",
-    "babel-preset-es2015-argon": "latest",
     "babel-register": "^6.26.0",
     "chai": "^3.5.0",
     "mocha": "^3.5.3",

From 900ac9a1856c4222756ba95c1b25d7292ec718a4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 11 Oct 2021 10:27:24 -0700
Subject: [PATCH 391/767] [resolvers/webpack] [deps] update `is-core-module`

---
 resolvers/webpack/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 2afc84e148..0fceac5915 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -36,7 +36,7 @@
     "find-root": "^1.1.0",
     "has": "^1.0.3",
     "interpret": "^1.4.0",
-    "is-core-module": "^2.6.0",
+    "is-core-module": "^2.7.0",
     "is-regex": "^1.1.4",
     "lodash": "^4.17.21",
     "resolve": "^1.20.0",

From 7463de2aa3389ffb40dee465b1ec763bc4382361 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 11 Oct 2021 10:52:39 -0700
Subject: [PATCH 392/767] utils: v2.7.0

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 7d08f1963e..fe7e35a3d3 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v2.7.0 - 2021-10-11
+
 ### Added
 - `fileExistsWithCaseSync`: add `strict` argument ([#1262], thanks [@sergei-startsev])
 - add `visit`, to support dynamic imports ([#1660], [#2212], thanks [@maxkomarychev], [@aladdin-add], [@Hypnosphi])
diff --git a/utils/package.json b/utils/package.json
index 787ce83a75..523f2d8d10 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.6.2",
+  "version": "2.7.0",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From b0131d2757bb28e8e1eb3f34670a2c59a3d7b9ff Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 11 Oct 2021 13:32:21 -0700
Subject: [PATCH 393/767] Bump to v2.25.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7dc919a42..0d1283d3bd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.25.0] - 2021-10-11
+
 ### Added
 - Support `eslint` v8 ([#2191], thanks [@ota-meshi])
 - [`no-unresolved`]: add `caseSensitiveStrict` option ([#1262], thanks [@sergei-startsev])
@@ -1295,7 +1297,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.2...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.0...HEAD
+[2.25.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.2...v2.25.0
 [2.24.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.1...v2.24.2
 [2.24.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.0...v2.24.1
 [2.24.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.4...v2.24.0
diff --git a/package.json b/package.json
index f7b7305139..9b09a70de4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.24.2",
+  "version": "2.25.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 6bdab3189da146c635573946ad650f4e738a3469 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 11 Oct 2021 22:00:54 -0700
Subject: [PATCH 394/767] [Deps] update `eslint-module-utils`

---
 CHANGELOG.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d1283d3bd..111f81ce20 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [Deps] update `eslint-module-utils`
+
 ## [2.25.0] - 2021-10-11
 
 ### Added

From 9cc1654b05459929018bcdec6d7e7e7eae7851cd Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 11 Oct 2021 22:01:20 -0700
Subject: [PATCH 395/767] Bump to v2.25.1

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 111f81ce20..5ae26b4544 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.25.1] - 2021-10-11
+
 ### Fixed
 - [Deps] update `eslint-module-utils`
 
@@ -1300,7 +1302,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.0...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.1...HEAD
+[2.25.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.0...v2.25.1
 [2.25.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.2...v2.25.0
 [2.24.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.1...v2.24.2
 [2.24.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.0...v2.24.1
diff --git a/package.json b/package.json
index 9b09a70de4..b12d422452 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.25.0",
+  "version": "2.25.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 85739db0614b7b7935d359a8f3054f4b5622fd50 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 12 Oct 2021 08:17:24 -0700
Subject: [PATCH 396/767] [Deps] update `eslint-module-utils`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index b12d422452..918a06896c 100644
--- a/package.json
+++ b/package.json
@@ -103,7 +103,7 @@
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
-    "eslint-module-utils": "^2.6.2",
+    "eslint-module-utils": "^2.7.0",
     "has": "^1.0.3",
     "is-core-module": "^2.7.0",
     "is-glob": "^4.0.3",

From 67103e698dcaa02a95f95145d2db6a04f1a573f8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 12 Oct 2021 15:51:35 -0700
Subject: [PATCH 397/767] Bump to v2.25.2

---
 CHANGELOG.md | 9 ++++++++-
 package.json | 2 +-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ae26b4544..46a250c108 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+## [2.25.2] - 2021-10-12
+
+### Fixed
+- [Deps] update `eslint-module-utils` for real this time ([#2255])
+
 ## [2.25.1] - 2021-10-11
 
 ### Fixed
@@ -1191,6 +1196,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2255]: https://github.com/import-js/eslint-plugin-import/issues/2255
 [#2201]: https://github.com/import-js/eslint-plugin-import/issues/2201
 [#2199]: https://github.com/import-js/eslint-plugin-import/issues/2199
 [#2161]: https://github.com/import-js/eslint-plugin-import/issues/2161
@@ -1302,7 +1308,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.1...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.2...HEAD
+[2.25.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.1...v2.25.2
 [2.25.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.0...v2.25.1
 [2.25.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.2...v2.25.0
 [2.24.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.1...v2.24.2
diff --git a/package.json b/package.json
index 918a06896c..aebbc30810 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.25.1",
+  "version": "2.25.2",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 02a15aa85a5bfa3f668c58da3cff944a494fce56 Mon Sep 17 00:00:00 2001
From: Stefan Nitsche <stefan.nitsche@syracom.de>
Date: Wed, 13 Oct 2021 10:57:50 +0200
Subject: [PATCH 398/767] [utils] [fix] fixed SyntaxError in node <= 6:
 Unexpected token ) in parse.js

---
 utils/.eslintrc     | 10 ++++++++++
 utils/.eslintrc.yml |  3 ---
 utils/CHANGELOG.md  |  5 +++++
 utils/parse.js      |  2 +-
 4 files changed, 16 insertions(+), 4 deletions(-)
 delete mode 100644 utils/.eslintrc.yml

diff --git a/utils/.eslintrc b/utils/.eslintrc
index 3fd3f5e647..fa000aa724 100644
--- a/utils/.eslintrc
+++ b/utils/.eslintrc
@@ -2,4 +2,14 @@
   "parserOptions": {
     "ecmaVersion": 6,
   },
+  "rules": {
+    "comma-dangle": ["error", {
+      "arrays": "always-multiline",
+      "objects": "always-multiline",
+      "imports": "always-multiline",
+      "exports": "always-multiline",
+      "functions": "never"
+    }],
+    "no-console": 1,
+  }
 }
diff --git a/utils/.eslintrc.yml b/utils/.eslintrc.yml
deleted file mode 100644
index d30c264659..0000000000
--- a/utils/.eslintrc.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-rules:
-  no-console: 1
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index fe7e35a3d3..d4048cc494 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+### Fixed
+ - fixed SyntaxError in node <= 6: Unexpected token ) in parse.js ([#2261], thanks [@VitusFW])
+
 ## v2.7.0 - 2021-10-11
 
 ### Added
@@ -97,6 +100,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2261]: https://github.com/import-js/eslint-plugin-import/pull/2261
 [#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
 [#2047]: https://github.com/import-js/eslint-plugin-import/pull/2047
@@ -137,3 +141,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@sompylasar]: https://github.com/sompylasar
 [@timkraut]: https://github.com/timkraut
 [@vikr01]: https://github.com/vikr01
+[@VitusFW]: https://github.com/VitusFW
\ No newline at end of file
diff --git a/utils/parse.js b/utils/parse.js
index d1dd4ef03b..a771544ea7 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -93,7 +93,7 @@ exports.default = function parse(path, content, context) {
       console.warn(
         '`parseForESLint` from parser `' +
           parserPath +
-          '` is invalid and will just be ignored',
+          '` is invalid and will just be ignored'
       );
     } else {
       return {

From 661876f14a7a34f94615aa744fa7899a2668c28b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 13 Oct 2021 11:57:11 -0700
Subject: [PATCH 399/767] utils: v2.7.1

---
 .github/workflows/node-4+.yml  | 2 +-
 .github/workflows/packages.yml | 2 +-
 utils/CHANGELOG.md             | 4 +++-
 utils/package.json             | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index aaa11f3a08..427edc6cc0 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -104,7 +104,7 @@ jobs:
           skip-ls-check: true
       - run: npm run pretest
       - run: npm run tests-only
-      - uses: codecov/codecov-action@v1
+      - uses: codecov/codecov-action@v2
 
   node:
     name: 'node 4+'
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index e7302faea4..e2389f5efa 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -43,7 +43,7 @@ jobs:
           after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh && cd ${{ matrix.package }} && npm install
           skip-ls-check: true
       - run: cd ${{ matrix.package }} && npm run tests-only
-      - uses: codecov/codecov-action@v1
+      - uses: codecov/codecov-action@v2
 
   packages:
     name: 'packages: all tests'
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index d4048cc494..bfa7e8036c 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## v2.7.1 - 2021-10-13
+
 ### Fixed
  - fixed SyntaxError in node <= 6: Unexpected token ) in parse.js ([#2261], thanks [@VitusFW])
 
@@ -141,4 +143,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@sompylasar]: https://github.com/sompylasar
 [@timkraut]: https://github.com/timkraut
 [@vikr01]: https://github.com/vikr01
-[@VitusFW]: https://github.com/VitusFW
\ No newline at end of file
+[@VitusFW]: https://github.com/VitusFW
diff --git a/utils/package.json b/utils/package.json
index 523f2d8d10..2c4c53bd47 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.7.0",
+  "version": "2.7.1",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From 3a4493106e3adf5eb8b6e688c18e5d0c8f2b7734 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 13 Oct 2021 15:56:40 -0700
Subject: [PATCH 400/767] [Tests] use new codecov uploader

---
 .travis.yml  |  2 +-
 appveyor.yml | 11 ++++++++---
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index a4b5f2b195..0a5e87bd32 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -37,4 +37,4 @@ script:
   - npm run tests-only
 
 after_success:
-  - bash <(curl -s https://codecov.io/bash)
+  - bash <(curl -Os https://uploader.codecov.io/latest/linux/codecov)
diff --git a/appveyor.yml b/appveyor.yml
index c728414d44..dbeb0132d6 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -142,8 +142,11 @@ for:
           $env:RESOLVERS = [string]::Join(";", $resolvers);
       - IF DEFINED RESOLVERS FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm install --no-save nyc@%WINDOWS_NYC_VERSION% & popd )
     # TODO: enable codecov for native windows builds
-    # on_success:
-      # - codecov
+    #on_success:
+    #- ci $ProgressPreference = 'SilentlyContinue'
+    #- ci Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe
+    #- ci -Outfile codecov.exe
+    #- ci .\codecov.exe
   - matrix:
       only:
         - configuration: WSL
@@ -154,6 +157,8 @@ for:
       - ps: wsl curl -sL 'https://deb.nodesource.com/setup_${nodejs_version}.x' `| sudo APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 -E bash -
       - wsl sudo DEBIAN_FRONTEND=noninteractive apt install -y nodejs
     on_success:
-      - ci bash <(curl -s https://codecov.io/bash)
+      - ci curl -Os https://uploader.codecov.io/latest/linux/codecov
+      - ci chmod +x codecov
+      - ci ./codecov
 
 build: on

From ce702dc320d0e9a06a9ccca66d190aa0e19a608d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 20 Oct 2021 00:03:18 -0700
Subject: [PATCH 401/767] [resolvers/webpack] [meta] expand `engines.node` to
 include node 17

Fixes #2268
---
 resolvers/webpack/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 0fceac5915..75c4248271 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -55,6 +55,6 @@
     "webpack": "https://gist.github.com/ljharb/9cdb687f3806f8e6cb8a365d0b7840eb"
   },
   "engines": {
-    "node": "^16 || ^15 || ^14 || ^13 || ^12 || ^11 || ^10 || ^9 || ^8 || ^7 || ^6"
+    "node": ">= 6"
   }
 }

From c3633c6dc1906b2d7c0f208dc56897f63233875a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 20 Oct 2021 00:04:56 -0700
Subject: [PATCH 402/767] [resolvers/webpack] v0.13.2

---
 resolvers/webpack/CHANGELOG.md | 8 +++++++-
 resolvers/webpack/package.json | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index f8ec4c47c2..212f77b0d0 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## Unreleased
 
+## 0.13.2 - 2021-10-20
+
+### Changed
+ - [meta] expand `engines.node` to include node 17 ([#2268], thanks [@ljharb])
+
 ## 0.13.1 - 2021-05-13
 
 ### Added
@@ -176,6 +181,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [#181]: https://github.com/import-js/eslint-plugin-import/pull/181
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 
+[#2268]: https://github.com/import-js/eslint-plugin-import/issues/2268
 [#1219]: https://github.com/import-js/eslint-plugin-import/issues/1219
 [#788]: https://github.com/import-js/eslint-plugin-import/issues/788
 [#767]: https://github.com/import-js/eslint-plugin-import/issues/767
@@ -211,4 +217,4 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [@opichals]: https://github.com/opichals
 [@andersk]: https://github.com/andersk
 [@ogonkov]: https://github.com/ogonkov
-[@jet2jet]: https://github.com/jet2jet
\ No newline at end of file
+[@jet2jet]: https://github.com/jet2jet
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 75c4248271..693950d23a 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.1",
+  "version": "0.13.2",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 46c4709bc2ac7e9e775527f6f9355848d4409d49 Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Sat, 23 Oct 2021 08:58:35 -0700
Subject: [PATCH 403/767] [Fix] `extensions`: ignore type-only imports

---
 CHANGELOG.md                  |  4 ++++
 src/rules/extensions.js       |  7 ++++++-
 tests/src/rules/extensions.js | 33 ++++++++++++++++++++++++++++++++-
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 46a250c108..c2bf1b922b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Fixed
+- [`extensions`]: ignore type-only imports ([#2270], [@jablko])
+
 ## [2.25.2] - 2021-10-12
 
 ### Fixed
@@ -929,6 +932,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2270]: https://github.com/import-js/eslint-plugin-import/pull/2270
 [#2240]: https://github.com/import-js/eslint-plugin-import/pull/2240
 [#2233]: https://github.com/import-js/eslint-plugin-import/pull/2233
 [#2226]: https://github.com/import-js/eslint-plugin-import/pull/2226
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index e116d2f866..74f478b66d 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -135,7 +135,12 @@ module.exports = {
       return false;
     }
 
-    function checkFileExtension(source) {
+    function checkFileExtension(source, node) {
+      // ignore type-only imports
+      if (node.importKind === 'type') {
+        return;
+      }
+
       // bail if the declaration doesn't have a source, e.g. "export { foo };", or if it's only partially typed like in an editor
       if (!source || !source.value) return;
       
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 0134334558..50f690395f 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -1,6 +1,6 @@
 import { RuleTester } from 'eslint';
 import rule from 'rules/extensions';
-import { test, testFilePath } from '../utils';
+import { getTSParsers, test, testFilePath } from '../utils';
 
 const ruleTester = new RuleTester();
 
@@ -597,3 +597,34 @@ ruleTester.run('extensions', rule, {
     }),
   ],
 });
+
+describe('TypeScript', () => {
+  getTSParsers()
+    // Type-only imports were added in TypeScript ESTree 2.23.0
+    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .forEach((parser) => {
+      ruleTester.run(`${parser}: extensions ignore type-only`, rule, {
+        valid: [
+          test({
+            code: 'import type { T } from "./typescript-declare";',
+            options: [
+              'always',
+              { ts: 'never', tsx: 'never', js: 'never', jsx: 'never' },
+            ],
+            parser,
+          }),
+        ],
+        invalid: [
+          test({
+            code: 'import { T } from "./typescript-declare";',
+            errors: ['Missing file extension for "./typescript-declare"'],
+            options: [
+              'always',
+              { ts: 'never', tsx: 'never', js: 'never', jsx: 'never' },
+            ],
+            parser,
+          }),
+        ],
+      });
+    });
+});

From 0481dcfc6acf4e7af8c56328606c49794a780fe4 Mon Sep 17 00:00:00 2001
From: Jack Bates <jack@nottheoilrig.com>
Date: Mon, 25 Oct 2021 11:03:52 -0700
Subject: [PATCH 404/767] [Fix] `extensions`: ignore unresolvable type-only
 imports

---
 CHANGELOG.md                  | 3 ++-
 src/rules/extensions.js       | 7 ++-----
 tests/src/rules/extensions.js | 4 ++--
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2bf1b922b..d533a20cb1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ## [Unreleased]
 
 ### Fixed
-- [`extensions`]: ignore type-only imports ([#2270], [@jablko])
+- [`extensions`]: ignore unresolveable type-only imports ([#2270], [#2271], [@jablko])
 
 ## [2.25.2] - 2021-10-12
 
@@ -932,6 +932,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2271]: https://github.com/import-js/eslint-plugin-import/pull/2271
 [#2270]: https://github.com/import-js/eslint-plugin-import/pull/2270
 [#2240]: https://github.com/import-js/eslint-plugin-import/pull/2240
 [#2233]: https://github.com/import-js/eslint-plugin-import/pull/2233
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 74f478b66d..c22d1f87bf 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -136,11 +136,6 @@ module.exports = {
     }
 
     function checkFileExtension(source, node) {
-      // ignore type-only imports
-      if (node.importKind === 'type') {
-        return;
-      }
-
       // bail if the declaration doesn't have a source, e.g. "export { foo };", or if it's only partially typed like in an editor
       if (!source || !source.value) return;
       
@@ -170,6 +165,8 @@ module.exports = {
       ) || isScoped(importPath);
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
+        // ignore type-only imports
+        if (node.importKind === 'type') return;
         const extensionRequired = isUseOfExtensionRequired(extension, isPackage);
         const extensionForbidden = isUseOfExtensionForbidden(extension);
         if (extensionRequired && !extensionForbidden) {
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 50f690395f..93ebc28f8e 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -606,7 +606,7 @@ describe('TypeScript', () => {
       ruleTester.run(`${parser}: extensions ignore type-only`, rule, {
         valid: [
           test({
-            code: 'import type { T } from "./typescript-declare";',
+            code: 'import type T from "./typescript-declare";',
             options: [
               'always',
               { ts: 'never', tsx: 'never', js: 'never', jsx: 'never' },
@@ -616,7 +616,7 @@ describe('TypeScript', () => {
         ],
         invalid: [
           test({
-            code: 'import { T } from "./typescript-declare";',
+            code: 'import T from "./typescript-declare";',
             errors: ['Missing file extension for "./typescript-declare"'],
             options: [
               'always',

From ccb69d9a41e484802ecbfb88c5320defbf803902 Mon Sep 17 00:00:00 2001
From: Nicolas Charpentier <nicolas.charpentier079@gmail.com>
Date: Mon, 25 Oct 2021 15:51:11 -0400
Subject: [PATCH 405/767] [Docs] order: add type to the default groups

---
 CHANGELOG.md        | 5 +++++
 docs/rules/order.md | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d533a20cb1..c5eb6d76b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Fixed
 - [`extensions`]: ignore unresolveable type-only imports ([#2270], [#2271], [@jablko])
 
+### Changed
+- [Docs] order: add type to the default groups ([#2272], [@charpeni])
+
 ## [2.25.2] - 2021-10-12
 
 ### Fixed
@@ -932,6 +935,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2272]: https://github.com/import-js/eslint-plugin-import/pull/2272
 [#2271]: https://github.com/import-js/eslint-plugin-import/pull/2271
 [#2270]: https://github.com/import-js/eslint-plugin-import/pull/2270
 [#2240]: https://github.com/import-js/eslint-plugin-import/pull/2240
@@ -1430,6 +1434,7 @@ for info on changes for earlier releases.
 [@brendo]: https://github.com/brendo
 [@brettz9]: https://github.com/brettz9
 [@charlessuh]: https://github.com/charlessuh
+[@charpeni]: https://github.com/charpeni
 [@cherryblossom000]: https://github.com/cherryblossom000
 [@chrislloyd]: https://github.com/chrislloyd
 [@christianvuerings]: https://github.com/christianvuerings
diff --git a/docs/rules/order.md b/docs/rules/order.md
index e320ee0c87..a1bae0b16c 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -3,7 +3,7 @@
 Enforce a convention in the order of `require()` / `import` statements.
 +(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule.
 
-With the [`groups`](#groups-array) option set to `["builtin", "external", "internal", "parent", "sibling", "index", "object"]` the order is as shown in the following example:
+With the [`groups`](#groups-array) option set to `["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"]` the order is as shown in the following example:
 
 ```js
 // 1. node "builtin" modules

From 651a4d759442b7eb1c6c257da8c90fe0b94f4b8b Mon Sep 17 00:00:00 2001
From: johnthagen <johnthagen@users.noreply.github.com>
Date: Fri, 29 Oct 2021 09:10:34 -0400
Subject: [PATCH 406/767] [readme] Add note to TypeScript docs to install
 appropriate resolver

---
 CHANGELOG.md | 4 +++-
 README.md    | 3 +++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5eb6d76b0..f5ca12a1b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [`extensions`]: ignore unresolveable type-only imports ([#2270], [#2271], [@jablko])
 
 ### Changed
-- [Docs] order: add type to the default groups ([#2272], [@charpeni])
+- [Docs] [`order`]: add type to the default groups ([#2272], [@charpeni])
+- [readme] Add note to TypeScript docs to install appropriate resolver ([#2279], [@johnthagen])
 
 ## [2.25.2] - 2021-10-12
 
@@ -1492,6 +1493,7 @@ for info on changes for earlier releases.
 [@jkimbo]: https://github.com/jkimbo
 [@joaovieira]: https://github.com/joaovieira
 [@johndevedu]: https://github.com/johndevedu
+[@johnthagen]: https://github.com/johnthagen
 [@jonboiser]: https://github.com/jonboiser
 [@josh]: https://github.com/josh
 [@JounQin]: https://github.com/JounQin
diff --git a/README.md b/README.md
index d800cbfe57..935792a3b5 100644
--- a/README.md
+++ b/README.md
@@ -174,6 +174,9 @@ extends:
 
 [`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser
 
+You will also need to install and configure the TypeScript resolver:
+[`eslint-import-resolver-typescript`](https://github.com/alexgorbatchev/eslint-import-resolver-typescript).
+
 # Resolvers
 
 With the advent of module bundlers and the current state of modules and module

From 498b1024e616636385a62a44202b3eb1d0da7bac Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 29 Oct 2021 09:56:08 -0700
Subject: [PATCH 407/767] [Refactor] `importType`: combine redundant `isScoped`
 and `isScopedModule`

---
 CHANGELOG.md                 | 1 +
 src/core/importType.js       | 4 ----
 src/rules/extensions.js      | 6 +++---
 tests/src/core/importType.js | 9 +--------
 4 files changed, 5 insertions(+), 15 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5ca12a1b4..35046f0f8c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 ### Changed
 - [Docs] [`order`]: add type to the default groups ([#2272], [@charpeni])
 - [readme] Add note to TypeScript docs to install appropriate resolver ([#2279], [@johnthagen])
+- [Refactor] `importType`: combine redundant `isScoped` and `isScopedModule` ([@ljharb])
 
 ## [2.25.2] - 2021-10-12
 
diff --git a/src/core/importType.js b/src/core/importType.js
index 6e4ac9a4da..e16a439e9d 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -101,10 +101,6 @@ function typeTest(name, context, path) {
   return 'unknown';
 }
 
-export function isScopedModule(name) {
-  return name.indexOf('@') === 0 && !name.startsWith('@/');
-}
-
 export default function resolveImportType(name, context) {
   return typeTest(name, context, resolve(name, context));
 }
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index c22d1f87bf..677a0a0959 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -1,7 +1,7 @@
 import path from 'path';
 
 import resolve from 'eslint-module-utils/resolve';
-import { isBuiltIn, isExternalModule, isScoped, isScopedModule } from '../core/importType';
+import { isBuiltIn, isExternalModule, isScoped } from '../core/importType';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
@@ -131,7 +131,7 @@ module.exports = {
       const slashCount = file.split('/').length - 1;
 
       if (slashCount === 0)  return true;
-      if (isScopedModule(file) && slashCount <= 1) return true;
+      if (isScoped(file) && slashCount <= 1) return true;
       return false;
     }
 
@@ -161,7 +161,7 @@ module.exports = {
         importPath,
         context.settings,
         resolve(importPath, context),
-        context
+        context,
       ) || isScoped(importPath);
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 0dcd5266bb..5f15f230aa 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -1,7 +1,7 @@
 import { expect } from 'chai';
 import * as path from 'path';
 
-import importType, { isExternalModule, isScopedModule, isScoped } from 'core/importType';
+import importType, { isExternalModule, isScoped } from 'core/importType';
 
 import { testContext, testFilePath } from '../utils';
 
@@ -239,13 +239,6 @@ describe('importType(name)', function () {
     }, 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
   });
 
-  it('correctly identifies scoped modules with `isScopedModule`', () => {
-    expect(isScopedModule('@/abc')).to.equal(false);
-    expect(isScopedModule('@/abc/def')).to.equal(false);
-    expect(isScopedModule('@a/abc')).to.equal(true);
-    expect(isScopedModule('@a/abc/def')).to.equal(true);
-  });
-
   it('correctly identifies scoped modules with `isScoped`', () => {
     expect(isScoped('@/abc')).to.equal(false);
     expect(isScoped('@/abc/def')).to.equal(false);

From 6682e9a492f1a138e0a32d11d3a65feecfec3aee Mon Sep 17 00:00:00 2001
From: Bernhard Jahn <bernhard.jahn@mobilexag.de>
Date: Fri, 29 Oct 2021 17:40:35 +0200
Subject: [PATCH 408/767] [Fix] `importType`: fix `isExternalModule`
 calculation

Fixes #2258
---
 CHANGELOG.md                 |  4 ++++
 src/core/importType.js       |  2 +-
 tests/src/core/importType.js | 10 ++++++++++
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35046f0f8c..3821c7e6f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ### Fixed
 - [`extensions`]: ignore unresolveable type-only imports ([#2270], [#2271], [@jablko])
+- `importType`: fix `isExternalModule` calculation ([#2282], [@mx-bernhard])
 
 ### Changed
 - [Docs] [`order`]: add type to the default groups ([#2272], [@charpeni])
@@ -937,6 +938,8 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2282]: https://github.com/import-js/eslint-plugin-import/pull/2282
+[#2279]: https://github.com/import-js/eslint-plugin-import/pull/2279
 [#2272]: https://github.com/import-js/eslint-plugin-import/pull/2272
 [#2271]: https://github.com/import-js/eslint-plugin-import/pull/2271
 [#2270]: https://github.com/import-js/eslint-plugin-import/pull/2270
@@ -1543,6 +1546,7 @@ for info on changes for earlier releases.
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@mplewis]: https://github.com/mplewis
 [@mrmckeb]: https://github.com/mrmckeb
+[@mx-bernhard]: https://github.com/mx-bernhard
 [@nickofthyme]: https://github.com/nickofthyme
 [@nicolashenry]: https://github.com/nicolashenry
 [@noelebrun]: https://github.com/noelebrun
diff --git a/src/core/importType.js b/src/core/importType.js
index e16a439e9d..085ce65820 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -29,7 +29,7 @@ export function isExternalModule(name, settings, path, context) {
   if (arguments.length < 4) {
     throw new TypeError('isExternalModule: name, settings, path, and context are all required');
   }
-  return isModule(name) && isExternalPath(name, settings, path, getContextPackagePath(context));
+  return (isModule(name) || isScoped(name)) && isExternalPath(name, settings, path, getContextPackagePath(context));
 }
 
 export function isExternalModuleMain(name, settings, path, context) {
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 5f15f230aa..528377e697 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -234,11 +234,21 @@ describe('importType(name)', function () {
   it('`isExternalModule` works with windows directory separator', function () {
     const context = testContext();
     expect(isExternalModule('foo', {}, 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
+    expect(isExternalModule('@foo/bar', {}, 'E:\\path\\to\\node_modules\\@foo\\bar', context)).to.equal(true);
     expect(isExternalModule('foo', {
       'import/external-module-folders': ['E:\\path\\to\\node_modules'],
     }, 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
   });
 
+  it('`isExternalModule` works with unix directory separator', function () {
+    const context = testContext();
+    expect(isExternalModule('foo', {}, '/path/to/node_modules/foo', context)).to.equal(true);
+    expect(isExternalModule('@foo/bar', {}, '/path/to/node_modules/@foo/bar', context)).to.equal(true);
+    expect(isExternalModule('foo', {
+      'import/external-module-folders': ['/path/to/node_modules'],
+    }, '/path/to/node_modules/foo', context)).to.equal(true);
+  });
+
   it('correctly identifies scoped modules with `isScoped`', () => {
     expect(isScoped('@/abc')).to.equal(false);
     expect(isScoped('@/abc/def')).to.equal(false);

From add650a1aeb118a4334bf2e9c56699ba1a836565 Mon Sep 17 00:00:00 2001
From: Kai <Schweinepriester@users.noreply.github.com>
Date: Thu, 4 Nov 2021 00:48:07 +0100
Subject: [PATCH 409/767] [Docs] HTTP => HTTPS

---
 .gitignore                       | 4 ++--
 CHANGELOG.md                     | 7 +++++--
 CONTRIBUTING.md                  | 2 +-
 README.md                        | 6 +++---
 docs/rules/first.md              | 2 +-
 docs/rules/no-duplicates.md      | 2 +-
 docs/rules/no-mutable-exports.md | 4 ++--
 docs/rules/unambiguous.md        | 2 +-
 resolvers/node/CHANGELOG.md      | 4 ++--
 resolvers/webpack/CHANGELOG.md   | 4 ++--
 resolvers/webpack/index.js       | 2 +-
 resolvers/webpack/test/alias.js  | 4 ++--
 src/rules/namespace.js           | 2 +-
 tests/files/flowtypes.js         | 2 +-
 tests/src/rules/no-unresolved.js | 2 +-
 utils/CHANGELOG.md               | 4 ++--
 utils/moduleVisitor.js           | 4 ++--
 utils/resolve.js                 | 2 +-
 18 files changed, 31 insertions(+), 28 deletions(-)

diff --git a/.gitignore b/.gitignore
index e1114fe9ac..8e2f6da1ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,10 +13,10 @@ lib-cov
 # Coverage directory used by tools like istanbul
 coverage
 
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
 .grunt
 
-# Compiled binary addons (http://nodejs.org/api/addons.html)
+# Compiled binary addons (https://nodejs.org/api/addons.html)
 build/Release
 
 # Copied from ./LICENSE for the npm module releases
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3821c7e6f0..ed35b29ad5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,8 @@
 # Change Log
 
 All notable changes to this project will be documented in this file.
-This project adheres to [Semantic Versioning](http://semver.org/).
-This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
+This project adheres to [Semantic Versioning](https://semver.org/).
+This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## [Unreleased]
 
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 - [Docs] [`order`]: add type to the default groups ([#2272], [@charpeni])
 - [readme] Add note to TypeScript docs to install appropriate resolver ([#2279], [@johnthagen])
 - [Refactor] `importType`: combine redundant `isScoped` and `isScopedModule` ([@ljharb])
+- [Docs] HTTP => HTTPS ([#2287], [@Schweinepriester])
 
 ## [2.25.2] - 2021-10-12
 
@@ -938,6 +939,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2287]: https://github.com/import-js/eslint-plugin-import/pull/2287
 [#2282]: https://github.com/import-js/eslint-plugin-import/pull/2282
 [#2279]: https://github.com/import-js/eslint-plugin-import/pull/2279
 [#2272]: https://github.com/import-js/eslint-plugin-import/pull/2272
@@ -1576,6 +1578,7 @@ for info on changes for earlier releases.
 [@saschanaz]: https://github.com/saschanaz
 [@schmidsi]: https://github.com/schmidsi
 [@schmod]: https://github.com/schmod
+[@Schweinepriester]: https://github.com/Schweinepriester
 [@scottnonnenberg]: https://github.com/scottnonnenberg
 [@sergei-startsev]: https://github.com/sergei-startsev
 [@sharmilajesupaul]: https://github.com/sharmilajesupaul
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 35a6b14b57..c992d67f0f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -110,7 +110,7 @@ If we can all get together behind the common goal of embracing empathy, everythi
 
 #### Attribution
 
-Thanks for help from http://mozillascience.github.io/working-open-workshop/contributing/
+Thanks for help from https://mozillascience.github.io/working-open-workshop/contributing/
 for inspiration before I wrote this. --ben
 
 [README.md]: ./README.md
diff --git a/README.md b/README.md
index 935792a3b5..1d7b55ff51 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 [![coverage][codecov-image]][codecov-url]
 [![win32 build status](https://ci.appveyor.com/api/projects/status/3mw2fifalmjlqf56/branch/main?svg=true)](https://ci.appveyor.com/project/import-js/eslint-plugin-import/branch/main)
 [![npm](https://img.shields.io/npm/v/eslint-plugin-import.svg)](https://www.npmjs.com/package/eslint-plugin-import)
-[![npm downloads](https://img.shields.io/npm/dt/eslint-plugin-import.svg?maxAge=2592000)](http://www.npmtrends.com/eslint-plugin-import)
+[![npm downloads](https://img.shields.io/npm/dt/eslint-plugin-import.svg?maxAge=2592000)](https://www.npmtrends.com/eslint-plugin-import)
 
 This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, and prevent issues with misspelling of file paths and import names. All the goodness that the ES2015+ static module syntax intends to provide, marked up in your editor.
 
@@ -256,7 +256,7 @@ the process's current working directory if no `package.json` is found.
 If you are interesting in writing a resolver, see the [spec](./resolvers/README.md) for more details.
 
 [`resolve`]: https://www.npmjs.com/package/resolve
-[`externals`]: http://webpack.github.io/docs/library-and-externals.html
+[`externals`]: https://webpack.github.io/docs/library-and-externals.html
 
 [Node]: https://www.npmjs.com/package/eslint-import-resolver-node
 [webpack]: https://www.npmjs.com/package/eslint-import-resolver-webpack
@@ -483,7 +483,7 @@ The purpose of the `chdir` setting, in this case, is to set the working director
 from which ESLint is executed to be the same as the directory on which SublimeLinter-eslint
 bases the relative path it provides.
 
-See the SublimeLinter docs on [`chdir`](http://www.sublimelinter.com/en/latest/linter_settings.html#chdir)
+See the SublimeLinter docs on [`chdir`](https://www.sublimelinter.com/en/latest/linter_settings.html#chdir)
 for more information, in case this does not work with your project.
 
 If you are not using `.eslintignore`, or don't have a Sublime project file, you can also
diff --git a/docs/rules/first.md b/docs/rules/first.md
index cc19003be2..c71ab7d8ab 100644
--- a/docs/rules/first.md
+++ b/docs/rules/first.md
@@ -45,7 +45,7 @@ A directive in this case is assumed to be a single statement that contains only
 a literal string-valued expression.
 
 `'use strict'` would be a good example, except that [modules are always in strict
-mode](http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-code) so it would be surprising to see a `'use strict'` sharing a file with `import`s and
+mode](https://262.ecma-international.org/6.0/#sec-strict-mode-code) so it would be surprising to see a `'use strict'` sharing a file with `import`s and
 `export`s.
 
 Given that, see [#255] for the reasoning.
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index c37510325e..5252db1b79 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -3,7 +3,7 @@
 Reports if a resolved path is imported more than once.
 +(fixable) The `--fix` option on the [command line] automatically fixes some problems reported by this rule.
 
-ESLint core has a similar rule ([`no-duplicate-imports`](http://eslint.org/docs/rules/no-duplicate-imports)), but this version
+ESLint core has a similar rule ([`no-duplicate-imports`](https://eslint.org/docs/rules/no-duplicate-imports)), but this version
 is different in two key ways:
 
 1. the paths in the source code don't have to exactly match, they just have to point to the same module on the filesystem. (i.e. `./foo` and `./foo.js`)
diff --git a/docs/rules/no-mutable-exports.md b/docs/rules/no-mutable-exports.md
index e161e87b12..f4cc7843ad 100644
--- a/docs/rules/no-mutable-exports.md
+++ b/docs/rules/no-mutable-exports.md
@@ -44,8 +44,8 @@ want to enable the following core ESLint rules:
 - [no-func-assign]
 - [no-class-assign]
 
-[no-func-assign]: http://eslint.org/docs/rules/no-func-assign
-[no-class-assign]: http://eslint.org/docs/rules/no-class-assign
+[no-func-assign]: https://eslint.org/docs/rules/no-func-assign
+[no-class-assign]: https://eslint.org/docs/rules/no-class-assign
 
 ## When Not To Use It
 
diff --git a/docs/rules/unambiguous.md b/docs/rules/unambiguous.md
index 92839b0c35..5be7d3df22 100644
--- a/docs/rules/unambiguous.md
+++ b/docs/rules/unambiguous.md
@@ -50,5 +50,5 @@ a `module`.
 - [`parserOptions.sourceType`]
 - [node-eps#13](https://github.com/nodejs/node-eps/issues/13)
 
-[`parserOptions.sourceType`]: http://eslint.org/docs/user-guide/configuring#specifying-parser-options
+[`parserOptions.sourceType`]: https://eslint.org/docs/user-guide/configuring#specifying-parser-options
 [Unambiguous JavaScript Grammar]: https://github.com/nodejs/node-eps/blob/HEAD/002-es-modules.md#32-determining-if-source-is-an-es-module
diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index c237855a2e..8812f12760 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -1,7 +1,7 @@
 # Change Log
 All notable changes to this resolver will be documented in this file.
-This project adheres to [Semantic Versioning](http://semver.org/).
-This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
+This project adheres to [Semantic Versioning](https://semver.org/).
+This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
 
diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 212f77b0d0..1626bb2720 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -1,7 +1,7 @@
 # Change Log
 All notable changes to this resolver will be documented in this file.
-This project adheres to [Semantic Versioning](http://semver.org/).
-This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
+This project adheres to [Semantic Versioning](https://semver.org/).
+This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
 
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 690c3b52a1..b569d53224 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -236,7 +236,7 @@ function createWebpack2ResolveSync(webpackRequire, resolveConfig) {
 }
 
 /**
- * webpack 1 defaults: http://webpack.github.io/docs/configuration.html#resolve-packagemains
+ * webpack 1 defaults: https://webpack.github.io/docs/configuration.html#resolve-packagemains
  * @type {Array}
  */
 const webpack1DefaultMains = [
diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js
index 06aad44699..946365b303 100644
--- a/resolvers/webpack/test/alias.js
+++ b/resolvers/webpack/test/alias.js
@@ -22,7 +22,7 @@ describe('resolve.alias', function () {
 
 // todo: reimplement with resolver function / config
 // describe.skip('webpack alias spec', function () {
-//   // from table: http://webpack.github.io/docs/configuration.html#resolve-alias
+//   // from table: https://webpack.github.io/docs/configuration.html#resolve-alias
 //   function tableLine(alias, xyz, xyzFile) {
 //     describe(JSON.stringify(alias), function () {
 //       it('xyz: ' + xyz, function () {
@@ -82,7 +82,7 @@ describe('resolve.alias', function () {
 // });
 
 // describe.skip('nested module names', function () {
-//   // from table: http://webpack.github.io/docs/configuration.html#resolve-alias
+//   // from table: https://webpack.github.io/docs/configuration.html#resolve-alias
 //   function nestedName(alias, xyz, xyzFile) {
 //     describe(JSON.stringify(alias), function () {
 //       it('top/xyz: ' + xyz, function () {
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 74ee9dae3c..6325b88ba2 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -68,7 +68,7 @@ module.exports = {
             case 'ImportDefaultSpecifier':
             case 'ImportSpecifier': {
               const meta = imports.get(
-                // default to 'default' for default http://i.imgur.com/nj6qAWy.jpg
+                // default to 'default' for default https://i.imgur.com/nj6qAWy.jpg
                 specifier.imported ? specifier.imported.name : 'default',
               );
               if (!meta || !meta.namespace) { break; }
diff --git a/tests/files/flowtypes.js b/tests/files/flowtypes.js
index 2df2471475..4282cf80b9 100644
--- a/tests/files/flowtypes.js
+++ b/tests/files/flowtypes.js
@@ -1,6 +1,6 @@
 // @flow
 // requires babel-eslint parser or flow plugin
-// http://flowtype.org/blog/2015/02/18/Import-Types.html
+// https://flowtype.org/blog/2015/02/18/Import-Types.html
 export type MyType = {
   id: number,
   firstName: string,
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index a5ff6da5d1..71efc128e3 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -67,7 +67,7 @@ function runResolverTests(resolver) {
         options: [{ amd: true }] }),
       rest({ code: 'require(["./does-not-exist"], function (bar) {})',
         options: [{ amd: false }] }),
-      // magic modules: http://git.io/vByan
+      // magic modules: https://git.io/vByan
       rest({ code: 'define(["require", "exports", "module"], function (r, e, m) { })',
         options: [{ amd: true }] }),
 
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index bfa7e8036c..65d67a35c7 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -1,7 +1,7 @@
 # Change Log
 All notable changes to this module will be documented in this file.
-This project adheres to [Semantic Versioning](http://semver.org/).
-This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
+This project adheres to [Semantic Versioning](https://semver.org/).
+This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
 
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index 8fb2b2604c..ade475e2a9 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -54,7 +54,7 @@ exports.default = function visitModules(visitor, options) {
   }
 
   // for CommonJS `require` calls
-  // adapted from @mctep: http://git.io/v4rAu
+  // adapted from @mctep: https://git.io/v4rAu
   function checkCommon(call) {
     if (call.callee.type !== 'Identifier') return;
     if (call.callee.name !== 'require') return;
@@ -81,7 +81,7 @@ exports.default = function visitModules(visitor, options) {
       if (typeof element.value !== 'string') continue;
 
       if (element.value === 'require' ||
-          element.value === 'exports') continue; // magic modules: http://git.io/vByan
+          element.value === 'exports') continue; // magic modules: https://git.io/vByan
 
       checkSourceValue(element, element);
     }
diff --git a/utils/resolve.js b/utils/resolve.js
index 27d5dcc1e1..31fb659079 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -51,7 +51,7 @@ function tryRequire(target, sourceFile) {
   return require(resolved);
 }
 
-// http://stackoverflow.com/a/27382838
+// https://stackoverflow.com/a/27382838
 exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings, strict) {
   // don't care if the FS is case-sensitive
   if (CASE_SENSITIVE_FS) return true;

From 332d3c8e19f8bc9fb983ba9ae85644ace1ba6c6f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Nov 2021 15:32:18 -0800
Subject: [PATCH 410/767] [Fix] `no-import-module-exports`: avoid false
 positives with a shadowed `module` or `exports`

Fixes #2297
---
 CHANGELOG.md                                |  2 +
 src/rules/no-import-module-exports.js       | 13 ++++--
 tests/src/rules/no-import-module-exports.js | 50 +++++++++++++++++++++
 3 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed35b29ad5..a0a7223add 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [`extensions`]: ignore unresolveable type-only imports ([#2270], [#2271], [@jablko])
 - `importType`: fix `isExternalModule` calculation ([#2282], [@mx-bernhard])
+- [`no-import-module-exports`]: avoid false positives with a shadowed `module` or `exports` ([#2297], [@ljharb])
 
 ### Changed
 - [Docs] [`order`]: add type to the default groups ([#2272], [@charpeni])
@@ -939,6 +940,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2297]: https://github.com/import-js/eslint-plugin-import/pull/2297
 [#2287]: https://github.com/import-js/eslint-plugin-import/pull/2287
 [#2282]: https://github.com/import-js/eslint-plugin-import/pull/2282
 [#2279]: https://github.com/import-js/eslint-plugin-import/pull/2279
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index 45710929ce..60140752ce 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -13,6 +13,12 @@ function getEntryPoint(context) {
   }
 }
 
+function findScope(context, identifier) {
+  const scopeManager = context.getSourceCode().scopeManager;
+
+  return scopeManager.scopes.slice().reverse().find((scope) => scope.variables.some(variable => variable.identifiers.some((node) => node.name === identifier)));
+}
+
 module.exports = {
   meta: {
     type: 'problem',
@@ -43,10 +49,11 @@ module.exports = {
       const isEntryPoint = entryPoint === fileName;
       const isIdentifier = node.object.type === 'Identifier';
       const hasKeywords = (/^(module|exports)$/).test(node.object.name);
-      const isException = options.exceptions &&
-        options.exceptions.some(glob => minimatch(fileName, glob));
+      const objectScope = hasKeywords && findScope(context, node.object.name);
+      const hasCJSExportReference = hasKeywords && (!objectScope || objectScope.type === 'module');
+      const isException = !!options.exceptions && options.exceptions.some(glob => minimatch(fileName, glob));
 
-      if (isIdentifier && hasKeywords && !isEntryPoint && !isException) {
+      if (isIdentifier && hasCJSExportReference && !isEntryPoint && !isException) {
         importDeclarations.forEach(importDeclaration => {
           context.report({
             node: importDeclaration,
diff --git a/tests/src/rules/no-import-module-exports.js b/tests/src/rules/no-import-module-exports.js
index 9ffbe6b56e..0c3718cef3 100644
--- a/tests/src/rules/no-import-module-exports.js
+++ b/tests/src/rules/no-import-module-exports.js
@@ -64,6 +64,56 @@ ruleTester.run('no-import-module-exports', rule, {
       `,
       filename: path.join(process.cwd(), 'tests/files/missing-entrypoint/cli.js'),
     }),
+    test({
+      code: `
+        import fs from 'fs/promises';
+
+        const subscriptions = new Map();
+        
+        export default async (client) => {
+            /**
+             * loads all modules and their subscriptions
+             */
+            const modules = await fs.readdir('./src/modules');
+        
+            await Promise.all(
+                modules.map(async (moduleName) => {
+                    // Loads the module
+                    const module = await import(\`./modules/\${moduleName}/module.js\`);
+                    // skips the module, in case it is disabled.
+                    if (module.enabled) {
+                        // Loads each of it's subscriptions into their according list.
+                        module.subscriptions.forEach((fun, event) => {
+                            if (!subscriptions.has(event)) {
+                                subscriptions.set(event, []);
+                            }
+                            subscriptions.get(event).push(fun);
+                        });
+                    }
+                })
+            );
+        
+            /**
+             * Setting up all events.
+             * binds all events inside the subscriptions map to call all functions provided
+             */
+            subscriptions.forEach((funs, event) => {
+                client.on(event, (...args) => {
+                    funs.forEach(async (fun) => {
+                        try {
+                            await fun(client, ...args);
+                        } catch (e) {
+                            client.emit('error', e);
+                        }
+                    });
+                });
+            });
+        };
+      `,
+      parserOptions: {
+        ecmaVersion: 2020,
+      },
+    }),
   ],
   invalid: [
     test({

From cdcc76a7bf00d89180ee148c37549f89b105ddd3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Nov 2021 15:40:58 -0800
Subject: [PATCH 411/767] [eslint] consolidate configs

---
 .eslintrc                               | 47 +++++++++++++++++++------
 resolvers/.eslintrc.yml                 |  3 --
 src/.eslintrc.yml                       |  3 --
 src/rules/default.js                    |  2 +-
 src/rules/export.js                     |  6 ++--
 src/rules/first.js                      |  4 +--
 src/rules/newline-after-import.js       |  2 +-
 src/rules/no-cycle.js                   |  4 +--
 src/rules/no-duplicates.js              |  8 ++---
 src/rules/no-extraneous-dependencies.js |  8 ++---
 src/rules/no-namespace.js               |  2 +-
 src/rules/no-relative-packages.js       |  2 +-
 src/rules/no-unresolved.js              |  4 +--
 src/rules/no-unused-modules.js          |  6 ++--
 src/rules/no-useless-path-segments.js   |  6 ++--
 src/rules/no-webpack-loader-syntax.js   |  2 +-
 src/rules/order.js                      | 12 +++----
 utils/.eslintrc                         | 15 --------
 18 files changed, 71 insertions(+), 65 deletions(-)
 delete mode 100644 resolvers/.eslintrc.yml
 delete mode 100644 src/.eslintrc.yml
 delete mode 100644 utils/.eslintrc

diff --git a/.eslintrc b/.eslintrc
index 4064c571d8..12fb8b7a23 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -18,7 +18,13 @@
         "ecmaVersion": 2020,
     },
     "rules": {
-        "comma-dangle": [2, "always-multiline"],
+        "comma-dangle": ["error", {
+            "arrays": "always-multiline",
+            "objects": "always-multiline",
+            "imports": "always-multiline",
+            "exports": "always-multiline",
+            "functions": "always-multiline",
+        }],
         "comma-style": [2, "last"],
         "curly": [2, "multi-line"],
         "eol-last": [2, "always"],
@@ -26,18 +32,17 @@
         "func-call-spacing": 2,
         "indent": [2, 2],
         "keyword-spacing": ["error", {
-          before: true,
-          after: true,
-          overrides: {
-            return: { after: true },
-            throw: { after: true },
-            case: { after: true }
+          "before": true,
+          "after": true,
+          "overrides": {
+            "return": { "after": true },
+            "throw": { "after": true },
+            "case": { "after": true }
           }
         }],
-        "max-len": [1, 99, 2],
+        "max-len": 0,
         "no-cond-assign": [2, "always"],
         "no-return-assign": [2, "always"],
-        "no-shadow": 1,
         "no-var": 2,
         "object-curly-spacing": [2, "always"],
         "object-shorthand": ["error", "always", {
@@ -91,6 +96,12 @@
                 "no-console": "off",
             },
         },
+        {
+            "files": "resolvers/**",
+            "env": {
+                "es6": false,
+            },
+        },
         {
             "files": [
                 "resolvers/*/test/**/*",
@@ -99,6 +110,22 @@
                 "mocha": true,
                 "es6": false
             },
-        }
+        },
+        {
+            "files": "utils/**",
+            "parserOptions": {
+                "ecmaVersion": 6,
+            },
+            "rules": {
+                "comma-dangle": ["error", {
+                    "arrays": "always-multiline",
+                    "objects": "always-multiline",
+                    "imports": "always-multiline",
+                    "exports": "always-multiline",
+                    "functions": "never"
+                }],
+                "no-console": 1,
+            },
+        },
     ],
 }
diff --git a/resolvers/.eslintrc.yml b/resolvers/.eslintrc.yml
deleted file mode 100644
index 9db33eda46..0000000000
--- a/resolvers/.eslintrc.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-env:
-  es6: false
diff --git a/src/.eslintrc.yml b/src/.eslintrc.yml
deleted file mode 100644
index 340d66bf69..0000000000
--- a/src/.eslintrc.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-rules:
-  comma-dangle: [1, "always-multiline"]
diff --git a/src/rules/default.js b/src/rules/default.js
index b8277b4525..6b917ccae3 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -15,7 +15,7 @@ module.exports = {
     function checkDefault(specifierType, node) {
 
       const defaultSpecifier = node.specifiers.find(
-        specifier => specifier.type === specifierType
+        specifier => specifier.type === specifierType,
       );
 
       if (!defaultSpecifier) return;
diff --git a/src/rules/export.js b/src/rules/export.js
index be75fa07f2..e0b2c57857 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -90,7 +90,7 @@ module.exports = {
       'ExportSpecifier': (node) => addNamed(
         node.exported.name,
         node.exported,
-        getParent(node.parent)
+        getParent(node.parent),
       ),
 
       'ExportNamedDeclaration': function (node) {
@@ -146,7 +146,7 @@ module.exports = {
         if (!any) {
           context.report(
             node.source,
-            `No named exports found in module '${node.source.value}'.`
+            `No named exports found in module '${node.source.value}'.`,
           );
         }
       },
@@ -164,7 +164,7 @@ module.exports = {
               } else {
                 context.report(
                   node,
-                  `Multiple exports of name '${name.replace(tsTypePrefix, '')}'.`
+                  `Multiple exports of name '${name.replace(tsTypePrefix, '')}'.`,
                 );
               }
             }
diff --git a/src/rules/first.js b/src/rules/first.js
index eb613d330b..087b840cb8 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -105,7 +105,7 @@ module.exports = {
               const range = [0, removeFixers[removeFixers.length - 1].range[1]];
               let insertSourceCode = sortNodes.map(function (_errorInfo) {
                 const nodeSourceCode = String.prototype.slice.apply(
-                  originSourceCode, _errorInfo.range
+                  originSourceCode, _errorInfo.range,
                 );
                 if (/\S/.test(nodeSourceCode[0])) {
                   return '\n' + nodeSourceCode;
@@ -124,7 +124,7 @@ module.exports = {
               const fixers = [insertFixer].concat(removeFixers);
               fixers.forEach(function (computedFixer, i) {
                 replaceSourceCode += (originSourceCode.slice(
-                  fixers[i - 1] ? fixers[i - 1].range[1] : 0, computedFixer.range[0]
+                  fixers[i - 1] ? fixers[i - 1].range[1] : 0, computedFixer.range[0],
                 ) + computedFixer.text);
               });
               return fixer.replaceTextRange(range, replaceSourceCode);
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 1b946b35ad..a3e0a11e19 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -107,7 +107,7 @@ module.exports = {
 after ${type} statement not followed by another ${type}.`,
           fix: fixer => fixer.insertTextAfter(
             node,
-            '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference)
+            '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference),
           ),
         });
       }
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index dda5a679d2..cefa41f99d 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -46,7 +46,7 @@ module.exports = {
       name,
       context.settings,
       resolve(name, context),
-      context
+      context,
     );
 
     function checkSourceValue(sourceNode, importer) {
@@ -88,7 +88,7 @@ module.exports = {
           const toTraverse = [...declarations].filter(({ source, isOnlyImportingTypes }) =>
             !ignoreModule(source.value) &&
             // Ignore only type imports
-            !isOnlyImportingTypes
+            !isOnlyImportingTypes,
           );
           /*
           Only report as a cycle if there are any import declarations that are considered by
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index c887b39e7a..43c2c5b201 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -45,7 +45,7 @@ function getFix(first, rest, sourceCode) {
   }
 
   const defaultImportNames = new Set(
-    [first, ...rest].map(getDefaultImportName).filter(Boolean)
+    [first, ...rest].map(getDefaultImportName).filter(Boolean),
   );
 
   // Bail if there are multiple different default import names – it's up to the
@@ -83,7 +83,7 @@ function getFix(first, rest, sourceCode) {
   const unnecessaryImports = restWithoutComments.filter(node =>
     !hasSpecifiers(node) &&
     !hasNamespace(node) &&
-    !specifiers.some(specifier => specifier.importNode === node)
+    !specifiers.some(specifier => specifier.importNode === node),
   );
 
   const shouldAddDefault = getDefaultImportName(first) == null && defaultImportNames.size === 1;
@@ -115,7 +115,7 @@ function getFix(first, rest, sourceCode) {
           specifier.isEmpty ? needsComma : true,
         ];
       },
-      ['', !firstHasTrailingComma && !firstIsEmpty]
+      ['', !firstHasTrailingComma && !firstIsEmpty],
     );
 
     const fixes = [];
@@ -123,7 +123,7 @@ function getFix(first, rest, sourceCode) {
     if (shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
       // `import './foo'` → `import def, {...} from './foo'`
       fixes.push(
-        fixer.insertTextAfter(firstToken, ` ${defaultImportName}, {${specifiersText}} from`)
+        fixer.insertTextAfter(firstToken, ` ${defaultImportName}, {${specifiersText}} from`),
       );
     } else if (shouldAddDefault && openBrace == null && !shouldAddSpecifiers) {
       // `import './foo'` → `import def from './foo'`
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 25a91aef51..b54ee28bb7 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -55,13 +55,13 @@ function getDependencies(context, packageDir) {
         const packageJsonPath = path.join(dir, 'package.json');
         if (!depFieldCache.has(packageJsonPath)) {
           const depFields = extractDepFields(
-            JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
+            JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')),
           );
           depFieldCache.set(packageJsonPath, depFields);
         }
         const _packageContent = depFieldCache.get(packageJsonPath);
         Object.keys(packageContent).forEach(depsKey =>
-          Object.assign(packageContent[depsKey], _packageContent[depsKey])
+          Object.assign(packageContent[depsKey], _packageContent[depsKey]),
         );
       });
     } else {
@@ -69,8 +69,8 @@ function getDependencies(context, packageDir) {
       Object.assign(
         packageContent,
         extractDepFields(
-          readPkgUp({ cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), normalize: false }).pkg
-        )
+          readPkgUp({ cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), normalize: false }).pkg,
+        ),
       );
     }
 
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index fb3d76052a..c615dfff52 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -76,7 +76,7 @@ module.exports = {
             const importLocalNames = generateLocalNames(
               importNames,
               importNameConflicts,
-              namespaceVariable.name
+              namespaceVariable.name,
             );
 
             // Replace the ImportNamespaceSpecifier with a list of ImportSpecifiers
diff --git a/src/rules/no-relative-packages.js b/src/rules/no-relative-packages.js
index 714eb3f5e3..17406e80eb 100644
--- a/src/rules/no-relative-packages.js
+++ b/src/rules/no-relative-packages.js
@@ -37,7 +37,7 @@ function checkImportForRelativePackage(context, importPath, node) {
     const properImport = path.join(
       importPkg.pkg.name,
       path.dirname(properPath),
-      importBaseName === path.basename(importRoot) ? '' : importBaseName
+      importBaseName === path.basename(importRoot) ? '' : importBaseName,
     );
     context.report({
       node,
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index 5491018976..b9dae97c8e 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -40,14 +40,14 @@ module.exports = {
       if (resolvedPath === undefined) {
         context.report(
           source,
-          `Unable to resolve path to module '${source.value}'.`
+          `Unable to resolve path to module '${source.value}'.`,
         );
       } else if (caseSensitive || caseSensitiveStrict) {
         const cacheSettings = ModuleCache.getSettings(context.settings);
         if (!fileExistsWithCaseSync(resolvedPath, cacheSettings, caseSensitiveStrict)) {
           context.report(
             source,
-            `Casing of ${source.value} does not match the underlying filesystem.`
+            `Casing of ${source.value} does not match the underlying filesystem.`,
           );
         }
       }
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 068eb911c3..9891d4097e 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -248,7 +248,7 @@ const prepareImportsAndExports = (srcFiles, context) => {
         }
         const localImport = imports.get(key) || new Set();
         value.declarations.forEach(({ importedSpecifiers }) =>
-          importedSpecifiers.forEach(specifier => localImport.add(specifier))
+          importedSpecifiers.forEach(specifier => localImport.add(specifier)),
         );
         imports.set(key, localImport);
       });
@@ -564,13 +564,13 @@ module.exports = {
         if (exportStatement.whereUsed.size < 1) {
           context.report(
             node,
-            `exported declaration '${value}' not used within other modules`
+            `exported declaration '${value}' not used within other modules`,
           );
         }
       } else {
         context.report(
           node,
-          `exported declaration '${value}' not used within other modules`
+          `exported declaration '${value}' not used within other modules`,
         );
       }
     };
diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index a058608028..c0156d09f8 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -88,7 +88,7 @@ module.exports = {
 
       const fileExtensions = getFileExtensions(context.settings);
       const regexUnnecessaryIndex = new RegExp(
-        `.*\\/index(\\${Array.from(fileExtensions).join('|\\')})?$`
+        `.*\\/index(\\${Array.from(fileExtensions).join('|\\')})?$`,
       );
 
       // Check if path contains unnecessary index (including a configured extension)
@@ -135,8 +135,8 @@ module.exports = {
           importPathSplit
             .slice(0, countExpectedRelativeParents)
             .concat(importPathSplit.slice(countImportPathRelativeParents + diff))
-            .join('/')
-        )
+            .join('/'),
+        ),
       );
     }
 
diff --git a/src/rules/no-webpack-loader-syntax.js b/src/rules/no-webpack-loader-syntax.js
index 2f49ad6c6a..e517207bac 100644
--- a/src/rules/no-webpack-loader-syntax.js
+++ b/src/rules/no-webpack-loader-syntax.js
@@ -4,7 +4,7 @@ import docsUrl from '../docsUrl';
 function reportIfNonStandard(context, node, name) {
   if (name && name.indexOf('!') !== -1) {
     context.report(node, `Unexpected '!' in '${name}'. ` +
-      'Do not use import syntax to configure webpack loaders.'
+      'Do not use import syntax to configure webpack loaders.',
     );
   }
 }
diff --git a/src/rules/order.js b/src/rules/order.js
index 194a3fd536..fce979f090 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -200,7 +200,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
       fix: canFix && (fixer =>
         fixer.replaceTextRange(
           [firstRootStart, secondRootEnd],
-          newCode + sourceCode.text.substring(firstRootStart, secondRootStart)
+          newCode + sourceCode.text.substring(firstRootStart, secondRootStart),
         )),
     });
   } else if (order === 'after') {
@@ -210,7 +210,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
       fix: canFix && (fixer =>
         fixer.replaceTextRange(
           [secondRootStart, firstRootEnd],
-          sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode
+          sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode,
         )),
     });
   }
@@ -463,7 +463,7 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports) {
   const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
     const linesBetweenImports = context.getSourceCode().lines.slice(
       previousImport.node.loc.end.line,
-      currentImport.node.loc.start.line - 1
+      currentImport.node.loc.start.line - 1,
     );
 
     return linesBetweenImports.filter((line) => !line.trim().length).length;
@@ -631,7 +631,7 @@ module.exports = {
             },
             ranks,
             getBlockImports(node.parent),
-            pathGroupsExcludedImportTypes
+            pathGroupsExcludedImportTypes,
           );
         }
       },
@@ -662,7 +662,7 @@ module.exports = {
           },
           ranks,
           getBlockImports(node.parent),
-          pathGroupsExcludedImportTypes
+          pathGroupsExcludedImportTypes,
         );
       },
       CallExpression: function handleRequires(node) {
@@ -684,7 +684,7 @@ module.exports = {
           },
           ranks,
           getBlockImports(block),
-          pathGroupsExcludedImportTypes
+          pathGroupsExcludedImportTypes,
         );
       },
       'Program:exit': function reportAndReset() {
diff --git a/utils/.eslintrc b/utils/.eslintrc
deleted file mode 100644
index fa000aa724..0000000000
--- a/utils/.eslintrc
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "parserOptions": {
-    "ecmaVersion": 6,
-  },
-  "rules": {
-    "comma-dangle": ["error", {
-      "arrays": "always-multiline",
-      "objects": "always-multiline",
-      "imports": "always-multiline",
-      "exports": "always-multiline",
-      "functions": "never"
-    }],
-    "no-console": 1,
-  }
-}

From 3fbc252d5aba56da34aa9271c1fad4f06e19e2d2 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Nov 2021 15:58:32 -0800
Subject: [PATCH 412/767] [Deps] update `eslint-module-utils`, `is-core-module`

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index aebbc30810..5f34f1f180 100644
--- a/package.json
+++ b/package.json
@@ -103,9 +103,9 @@
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
-    "eslint-module-utils": "^2.7.0",
+    "eslint-module-utils": "^2.7.1",
     "has": "^1.0.3",
-    "is-core-module": "^2.7.0",
+    "is-core-module": "^2.8.0",
     "is-glob": "^4.0.3",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.5",

From 790d9afa9eeebaacb14624267a4923405e16a1f7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Nov 2021 16:07:32 -0800
Subject: [PATCH 413/767] [Tests] skip 2020 test in eslint < 6

---
 tests/src/rules/no-import-module-exports.js | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tests/src/rules/no-import-module-exports.js b/tests/src/rules/no-import-module-exports.js
index 0c3718cef3..a40eb7e276 100644
--- a/tests/src/rules/no-import-module-exports.js
+++ b/tests/src/rules/no-import-module-exports.js
@@ -1,7 +1,7 @@
 import path from 'path';
 import { RuleTester } from 'eslint';
 
-import { test } from '../utils';
+import { test, testVersion } from '../utils';
 
 const ruleTester = new RuleTester({
   parserOptions: { ecmaVersion: 6, sourceType: 'module' },
@@ -15,7 +15,7 @@ const error = {
 };
 
 ruleTester.run('no-import-module-exports', rule, {
-  valid: [
+  valid: [].concat(
     test({
       code: `
         const thing = require('thing')
@@ -64,7 +64,7 @@ ruleTester.run('no-import-module-exports', rule, {
       `,
       filename: path.join(process.cwd(), 'tests/files/missing-entrypoint/cli.js'),
     }),
-    test({
+    testVersion('>= 6', () => ({
       code: `
         import fs from 'fs/promises';
 
@@ -113,8 +113,8 @@ ruleTester.run('no-import-module-exports', rule, {
       parserOptions: {
         ecmaVersion: 2020,
       },
-    }),
-  ],
+    })) || [],
+  ),
   invalid: [
     test({
       code: `

From dfc5b54819a40ad51e922ea8a398285b81a5802d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Nov 2021 16:27:19 -0800
Subject: [PATCH 414/767] [Fix] `no-import-module-exports`: avoid a crash in
 eslint < 4

---
 src/rules/no-import-module-exports.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index 60140752ce..4af1e7b453 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -14,9 +14,9 @@ function getEntryPoint(context) {
 }
 
 function findScope(context, identifier) {
-  const scopeManager = context.getSourceCode().scopeManager;
+  const { scopeManager } = context.getSourceCode();
 
-  return scopeManager.scopes.slice().reverse().find((scope) => scope.variables.some(variable => variable.identifiers.some((node) => node.name === identifier)));
+  return scopeManager && scopeManager.scopes.slice().reverse().find((scope) => scope.variables.some(variable => variable.identifiers.some((node) => node.name === identifier)));
 }
 
 module.exports = {

From 7c239fed485ea0785a96c1fa2045d96c181bb79c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 9 Nov 2021 21:47:48 -0800
Subject: [PATCH 415/767] Bump to v2.25.3

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0a7223add..0d4d920a4c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.25.3] - 2021-11-09
+
 ### Fixed
 - [`extensions`]: ignore unresolveable type-only imports ([#2270], [#2271], [@jablko])
 - `importType`: fix `isExternalModule` calculation ([#2282], [@mx-bernhard])
@@ -1326,7 +1328,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.2...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.3...HEAD
+[2.25.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.2...v2.25.3
 [2.25.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.1...v2.25.2
 [2.25.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.0...v2.25.1
 [2.25.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.2...v2.25.0
diff --git a/package.json b/package.json
index 5f34f1f180..551bcb8d2c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.25.2",
+  "version": "2.25.3",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From e8794f1fad6d039c03848906ae61271f362aa1df Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 17 Nov 2021 15:13:32 -0800
Subject: [PATCH 416/767] [Fix] `importType`: avoid crashing on a non-string

---
 CHANGELOG.md                  | 20 ++++++++++++--------
 src/core/importType.js        |  2 +-
 src/rules/no-absolute-path.js |  2 +-
 tests/src/core/importType.js  | 13 ++++++++++++-
 4 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d4d920a4c..fbb5c8092d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,23 +6,26 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- `importType`: avoid crashing on a non-string' ([#2305], thanks [@ljharb])
+
 ## [2.25.3] - 2021-11-09
 
 ### Fixed
-- [`extensions`]: ignore unresolveable type-only imports ([#2270], [#2271], [@jablko])
-- `importType`: fix `isExternalModule` calculation ([#2282], [@mx-bernhard])
-- [`no-import-module-exports`]: avoid false positives with a shadowed `module` or `exports` ([#2297], [@ljharb])
+- [`extensions`]: ignore unresolveable type-only imports ([#2270], [#2271], thanks [@jablko])
+- `importType`: fix `isExternalModule` calculation ([#2282], thanks [@mx-bernhard])
+- [`no-import-module-exports`]: avoid false positives with a shadowed `module` or `exports` ([#2297], thanks [@ljharb])
 
 ### Changed
-- [Docs] [`order`]: add type to the default groups ([#2272], [@charpeni])
-- [readme] Add note to TypeScript docs to install appropriate resolver ([#2279], [@johnthagen])
-- [Refactor] `importType`: combine redundant `isScoped` and `isScopedModule` ([@ljharb])
-- [Docs] HTTP => HTTPS ([#2287], [@Schweinepriester])
+- [Docs] [`order`]: add type to the default groups ([#2272], thanks [@charpeni])
+- [readme] Add note to TypeScript docs to install appropriate resolver ([#2279], thanks [@johnthagen])
+- [Refactor] `importType`: combine redundant `isScoped` and `isScopedModule` (thanks [@ljharb])
+- [Docs] HTTP => HTTPS ([#2287], thanks [@Schweinepriester])
 
 ## [2.25.2] - 2021-10-12
 
 ### Fixed
-- [Deps] update `eslint-module-utils` for real this time ([#2255])
+- [Deps] update `eslint-module-utils` for real this time ([#2255], thanks [@ljharb])
 
 ## [2.25.1] - 2021-10-11
 
@@ -942,6 +945,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
 [#2297]: https://github.com/import-js/eslint-plugin-import/pull/2297
 [#2287]: https://github.com/import-js/eslint-plugin-import/pull/2287
 [#2282]: https://github.com/import-js/eslint-plugin-import/pull/2282
diff --git a/src/core/importType.js b/src/core/importType.js
index 085ce65820..3e579b9440 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -14,7 +14,7 @@ function baseModule(name) {
 }
 
 export function isAbsolute(name) {
-  return nodeIsAbsolute(name);
+  return typeof name === 'string' && nodeIsAbsolute(name);
 }
 
 // path is defined only when a resolver resolves to a non-standard path
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index 4111fd7e67..fe0a1b6d31 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -13,7 +13,7 @@ module.exports = {
 
   create(context) {
     function reportIfAbsolute(source) {
-      if (typeof source.value === 'string' && isAbsolute(source.value)) {
+      if (isAbsolute(source.value)) {
         context.report(source, 'Do not import modules using an absolute path');
       }
     }
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 528377e697..4f4a862a65 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -1,7 +1,7 @@
 import { expect } from 'chai';
 import * as path from 'path';
 
-import importType, { isExternalModule, isScoped } from 'core/importType';
+import importType, { isExternalModule, isScoped, isAbsolute } from 'core/importType';
 
 import { testContext, testFilePath } from '../utils';
 
@@ -256,3 +256,14 @@ describe('importType(name)', function () {
     expect(isScoped('@a/abc/def')).to.equal(true);
   });
 });
+
+describe('isAbsolute', () => {
+  it('does not throw on a non-string', () => {
+    expect(() => isAbsolute()).not.to.throw();
+    expect(() => isAbsolute(null)).not.to.throw();
+    expect(() => isAbsolute(true)).not.to.throw();
+    expect(() => isAbsolute(false)).not.to.throw();
+    expect(() => isAbsolute(0)).not.to.throw();
+    expect(() => isAbsolute(NaN)).not.to.throw();
+  });
+});

From f4d3020afdf06a1988281619ab680e176dd7a4fb Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 10 Nov 2021 14:20:21 -0800
Subject: [PATCH 417/767] [Refactor] `no-default-export`: tweak rule

---
 src/rules/no-default-export.js | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index cb7c0bb724..bcdca1ccac 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -16,9 +16,7 @@ module.exports = {
     }
 
     const preferNamed = 'Prefer named exports.';
-    const noAliasDefault = ({ local }) =>
-      `Do not alias \`${local.name}\` as \`default\`. Just export ` +
-      `\`${local.name}\` itself instead.`;
+    const noAliasDefault = ({ local }) => `Do not alias \`${local.name}\` as \`default\`. Just export \`${local.name}\` itself instead.`;
 
     return {
       ExportDefaultDeclaration(node) {
@@ -26,12 +24,10 @@ module.exports = {
       },
 
       ExportNamedDeclaration(node) {
-        node.specifiers.forEach(specifier => {
-          if (specifier.type === 'ExportDefaultSpecifier' &&
-              specifier.exported.name === 'default') {
+        node.specifiers.filter(specifier => specifier.exported.name === 'default').forEach(specifier => {
+          if (specifier.type === 'ExportDefaultSpecifier') {
             context.report({ node, message: preferNamed });
-          } else if (specifier.type === 'ExportSpecifier' &&
-              specifier.exported.name === 'default') {
+          } else if (specifier.type === 'ExportSpecifier') {
             context.report({ node, message: noAliasDefault(specifier) });
           }
         });

From 2c3353015da029ff301fba001fa3b78cb951d10b Mon Sep 17 00:00:00 2001
From: Patrick McElhaney <robert.mcelhaney@walgreens.com>
Date: Wed, 10 Nov 2021 16:39:13 -0500
Subject: [PATCH 418/767] [Fix] `no-default-import`: report on the token
 "default" instead of the entire node

---
 CHANGELOG.md                         |  7 +++
 src/rules/no-default-export.js       |  8 ++-
 tests/src/rules/no-default-export.js | 94 ++++++++++++++++++++--------
 tests/src/utils.js                   |  2 +-
 4 files changed, 82 insertions(+), 29 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fbb5c8092d..4d03e9821c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - `importType`: avoid crashing on a non-string' ([#2305], thanks [@ljharb])
 
+### Changed
+- [`no-default-import`]: report on the token "default" instead of the entire node ([#2299], [@pmcelhaney])
+
 ## [2.25.3] - 2021-11-09
 
 ### Fixed
@@ -945,7 +948,11 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+<<<<<<< HEAD
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
+=======
+[#2299]: https://github.com/import-js/eslint-plugin-import/pull/2299
+>>>>>>> 374ce41e... [Fix] `no-default-import`: report on the token "default" instead of the entire node
 [#2297]: https://github.com/import-js/eslint-plugin-import/pull/2297
 [#2287]: https://github.com/import-js/eslint-plugin-import/pull/2287
 [#2282]: https://github.com/import-js/eslint-plugin-import/pull/2282
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index bcdca1ccac..a17428c563 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -20,15 +20,17 @@ module.exports = {
 
     return {
       ExportDefaultDeclaration(node) {
-        context.report({ node, message: preferNamed });
+        const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {};
+        context.report({ node, message: preferNamed, loc });
       },
 
       ExportNamedDeclaration(node) {
         node.specifiers.filter(specifier => specifier.exported.name === 'default').forEach(specifier => {
+          const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {};
           if (specifier.type === 'ExportDefaultSpecifier') {
-            context.report({ node, message: preferNamed });
+            context.report({ node, message: preferNamed, loc });
           } else if (specifier.type === 'ExportSpecifier') {
-            context.report({ node, message: noAliasDefault(specifier) });
+            context.report({ node, message: noAliasDefault(specifier), loc  });
           }
         });
       },
diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index bc0119a019..61e55d9593 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -1,4 +1,4 @@
-import { test } from '../utils';
+import { test, testVersion } from '../utils';
 
 import { RuleTester } from 'eslint';
 
@@ -85,38 +85,82 @@ ruleTester.run('no-default-export', rule, {
       parser: require.resolve('babel-eslint'),
     }),
   ],
-  invalid: [
-    test({
+  invalid: [].concat(
+    testVersion('> 2', () => ({
       code: 'export default function bar() {};',
-      errors: [{
-        type: 'ExportDefaultDeclaration',
-        message: 'Prefer named exports.',
-      }],
-    }),
-    test({
+      errors: [
+        {
+          type: 'ExportDefaultDeclaration',
+          message: 'Prefer named exports.',
+          line: 1,
+          column: 8,
+        },
+      ],
+    })),
+    testVersion('> 2', () => ({
       code: `
         export const foo = 'foo';
         export default bar;`,
-      errors: [{
-        type: 'ExportDefaultDeclaration',
-        message: 'Prefer named exports.',
-      }],
-    }),
+      errors: [
+        {
+          type: 'ExportDefaultDeclaration',
+          message: 'Prefer named exports.',
+          line: 3,
+          column: 16,
+        },
+      ],
+    })),
+    testVersion('> 2', () => ({
+      code: 'export default class Bar {};',
+      errors: [
+        {
+          type: 'ExportDefaultDeclaration',
+          message: 'Prefer named exports.',
+          line: 1,
+          column: 8,
+        },
+      ],
+    })),
+    testVersion('> 2', () => ({
+      code: 'export default function() {};',
+      errors: [
+        {
+          type: 'ExportDefaultDeclaration',
+          message: 'Prefer named exports.',
+          line: 1,
+          column: 8,
+        },
+      ],
+    })),
+    testVersion('> 2', () => ({
+      code: 'export default class {};',
+      errors: [
+        {
+          type: 'ExportDefaultDeclaration',
+          message: 'Prefer named exports.',
+          line: 1,
+          column: 8,
+        },
+      ],
+    })),
     test({
       code: 'let foo; export { foo as default }',
-      errors: [{
-        type: 'ExportNamedDeclaration',
-        message: 'Do not alias `foo` as `default`. Just export `foo` itself ' +
-          'instead.',
-      }],
+      errors: [
+        {
+          type: 'ExportNamedDeclaration',
+          message: 'Do not alias `foo` as `default`. Just export `foo` itself instead.',
+        },
+      ],
     }),
     test({
       code: 'export default from "foo.js"',
       parser: require.resolve('babel-eslint'),
-      errors: [{
-        type: 'ExportNamedDeclaration',
-        message: 'Prefer named exports.',
-      }],
-    }),
-  ],
+      errors: [
+        {
+          type: 'ExportNamedDeclaration',
+          message: 'Prefer named exports.',
+        },
+      ],
+    }),
+  ),
 });
diff --git a/tests/src/utils.js b/tests/src/utils.js
index 4d23af7551..012c3a7c7b 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -28,7 +28,7 @@ export function getNonDefaultParsers() {
 export const FILENAME = testFilePath('foo.js');
 
 export function testVersion(specifier, t) {
-  return semver.satisfies(eslintPkg.version, specifier) && test(t());
+  return semver.satisfies(eslintPkg.version, specifier) ? test(t()) : [];
 }
 
 export function test(t) {

From 32cae194f35d97f5b88e41cb643fac8860857306 Mon Sep 17 00:00:00 2001
From: johnthagen <johnthagen@users.noreply.github.com>
Date: Fri, 29 Oct 2021 10:38:03 -0400
Subject: [PATCH 419/767] [Docs] `order`: Remove duplicate mention of default

---
 CHANGELOG.md        | 7 +++----
 docs/rules/order.md | 4 +++-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d03e9821c..3897a3b81b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - `importType`: avoid crashing on a non-string' ([#2305], thanks [@ljharb])
 
 ### Changed
-- [`no-default-import`]: report on the token "default" instead of the entire node ([#2299], [@pmcelhaney])
+- [`no-default-import`]: report on the token "default" instead of the entire node ([#2299], thanks [@pmcelhaney])
+- [Docs] [`order`]: Remove duplicate mention of default ([#2280], thanks [@johnthagen])
 
 ## [2.25.3] - 2021-11-09
 
@@ -948,14 +949,12 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
-<<<<<<< HEAD
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
-=======
 [#2299]: https://github.com/import-js/eslint-plugin-import/pull/2299
->>>>>>> 374ce41e... [Fix] `no-default-import`: report on the token "default" instead of the entire node
 [#2297]: https://github.com/import-js/eslint-plugin-import/pull/2297
 [#2287]: https://github.com/import-js/eslint-plugin-import/pull/2287
 [#2282]: https://github.com/import-js/eslint-plugin-import/pull/2282
+[#2280]: https://github.com/import-js/eslint-plugin-import/pull/2280
 [#2279]: https://github.com/import-js/eslint-plugin-import/pull/2279
 [#2272]: https://github.com/import-js/eslint-plugin-import/pull/2272
 [#2271]: https://github.com/import-js/eslint-plugin-import/pull/2271
diff --git a/docs/rules/order.md b/docs/rules/order.md
index a1bae0b16c..437467e244 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -175,11 +175,13 @@ The default value is `["builtin", "external"]`.
 
 Enforces or forbids new lines between import groups:
 
-- If set to `ignore`, no errors related to new lines between import groups will be reported (default).
+- If set to `ignore`, no errors related to new lines between import groups will be reported.
 - If set to `always`, at least one new line between each group will be enforced, and new lines inside a group will be forbidden. To prevent multiple lines between imports, core `no-multiple-empty-lines` rule can be used.
 - If set to `always-and-inside-groups`, it will act like `always` except newlines are allowed inside import groups.
 - If set to `never`, no new lines are allowed in the entire import section.
 
+The default value is `"ignore"`.
+
 With the default group setting, the following will be invalid:
 
 ```js

From 8ce09368693824416e97119ccb219ec1dfb54090 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 20 Nov 2021 21:46:31 -0800
Subject: [PATCH 420/767] [Deps] update `tsconfig-paths`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 551bcb8d2c..98816bd227 100644
--- a/package.json
+++ b/package.json
@@ -110,6 +110,6 @@
     "minimatch": "^3.0.4",
     "object.values": "^1.1.5",
     "resolve": "^1.20.0",
-    "tsconfig-paths": "^3.11.0"
+    "tsconfig-paths": "^3.12.0"
   }
 }

From 3edcd8d9a83f72a597ea54a7fe8267311a389d96 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 22 Nov 2021 18:50:03 -0800
Subject: [PATCH 421/767] [Tests] `packages`: run on multiple eslint versions

---
 .github/workflows/packages.yml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index e2389f5efa..a9f3f187c3 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -25,6 +25,9 @@ jobs:
       fail-fast: false
       matrix:
         node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
+        eslint:
+          - 8
+          - 7
         package:
           - resolvers/node
           - resolvers/webpack

From 3875392f5b29d35881027a27474a78113de6eab0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 22 Nov 2021 17:08:54 -0800
Subject: [PATCH 422/767] [Fix] `first`: prevent crash when parsing angular
 templates

Fixes #2210
---
 .github/workflows/node-4+.yml  |   3 +-
 .github/workflows/packages.yml |   1 +
 CHANGELOG.md                   |   2 +
 package.json                   |   1 +
 src/rules/first.js             |   3 +
 tests/dep-time-travel.sh       |   7 +-
 tests/files/component.html     | 139 +++++++++++++++++++++++++++++++++
 tests/src/rules/first.js       |  13 ++-
 8 files changed, 163 insertions(+), 6 deletions(-)
 create mode 100644 tests/files/component.html

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 427edc6cc0..3af06b3bc3 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -18,7 +18,7 @@ jobs:
 
   latest:
     needs: [matrix]
-    name: 'latest majors'
+    name: 'majors'
     runs-on: ubuntu-latest
 
     strategy:
@@ -96,6 +96,7 @@ jobs:
         continue-on-error: ${{ matrix.eslint == 4 && matrix.node-version == 4 }}
         name: 'nvm install ${{ matrix.node-version }} && npm install, with eslint ${{ matrix.eslint }}'
         env:
+          NPM_CONFIG_LEGACY_PEER_DEPS: ${{ matrix.node-version == 11 && false || true }}
           ESLINT_VERSION: ${{ matrix.eslint }}
           TRAVIS_NODE_VERSION: ${{ matrix.node-version }}
         with:
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index a9f3f187c3..e8cfaa8100 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -39,6 +39,7 @@ jobs:
       - uses: ljharb/actions/node/install@main
         name: 'nvm install ${{ matrix.node-version }} && npm install'
         env:
+          NPM_CONFIG_LEGACY_PEER_DEPS: ${{ matrix.node-version == 11 && false || true }}
           ESLINT_VERSION: ${{ matrix.eslint }}
           TRAVIS_NODE_VERSION: ${{ matrix.node-version }}
         with:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3897a3b81b..bac6b00404 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - `importType`: avoid crashing on a non-string' ([#2305], thanks [@ljharb])
+- [`first`]: prevent crash when parsing angular templates ([#2210], thanks [@ljharb])
 
 ### Changed
 - [`no-default-import`]: report on the token "default" instead of the entire node ([#2299], thanks [@pmcelhaney])
@@ -1227,6 +1228,7 @@ for info on changes for earlier releases.
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
 [#2255]: https://github.com/import-js/eslint-plugin-import/issues/2255
+[#2210]: https://github.com/import-js/eslint-plugin-import/issues/2210
 [#2201]: https://github.com/import-js/eslint-plugin-import/issues/2201
 [#2199]: https://github.com/import-js/eslint-plugin-import/issues/2199
 [#2161]: https://github.com/import-js/eslint-plugin-import/issues/2161
diff --git a/package.json b/package.json
index 98816bd227..a48f86b225 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
   },
   "homepage": "https://github.com/import-js/eslint-plugin-import",
   "devDependencies": {
+    "@angular-eslint/template-parser": "^13.0.1",
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3",
diff --git a/src/rules/first.js b/src/rules/first.js
index 087b840cb8..285a377f27 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -31,6 +31,9 @@ module.exports = {
     return {
       'Program': function (n) {
         const body = n.body;
+        if (!body) {
+          return;
+        }
         const absoluteFirst = context.options[0] === 'absolute-first';
         const message = 'Import in body of module; reorder to top.';
         const sourceCode = context.getSourceCode();
diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index 116a4bfd4f..82681b38f3 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -6,9 +6,12 @@ echo "installing ${ESLINT_VERSION} in node ${TRAVIS_NODE_VERSION} with TS parser
 
 export NPM_CONFIG_LEGACY_PEER_DEPS=true
 
-npm install --no-save "eslint@${ESLINT_VERSION}" --ignore-scripts
-
+if [[ "$ESLINT_VERSION" -lt "7" ]]; then
+  echo "Removing @angular-eslint/template-parser..."
+  npm uninstall --no-save @angular-eslint/template-parser
+fi
 
+npm install --no-save "eslint@${ESLINT_VERSION}" --ignore-scripts
 
 if [[ -n "$TS_PARSER" ]]; then # if TS parser is manually set, always use it
   echo "Downgrading @typescript-eslint/parser..."
diff --git a/tests/files/component.html b/tests/files/component.html
new file mode 100644
index 0000000000..b63f55e0b2
--- /dev/null
+++ b/tests/files/component.html
@@ -0,0 +1,139 @@
+<header class="flex">
+  <svg width="40" height="40" viewBox="0 0 262 163">
+    <polygon
+      id="Path"
+      fill="#ffffff"
+      points="130.68 104.59 97.49 52.71 97.44 96.3 40.24 0 0 0 0 162.57 39.79 162.57 39.92 66.39 96.53 158.26"
+    ></polygon>
+    <polygon
+      id="Path"
+      fill="#ffffff"
+      points="97.5 41.79 137.24 41.79 137.33 41.33 137.33 0 97.54 0 97.49 41.33"
+    ></polygon>
+    <path
+      d="M198.66,86.86 C189.139872,86.6795216 180.538723,92.516445 177.19,101.43 C182.764789,93.0931021 193.379673,89.7432211 202.73,93.37 C207.05,95.13 212.73,97.97 217.23,96.45 C212.950306,90.4438814 206.034895,86.8725952 198.66,86.86 L198.66,86.86 Z"
+      id="Path"
+      fill="#96D8E9"
+    ></path>
+    <path
+      d="M243.75,106.42 C243.75,101.55 241.1,100.42 235.6,98.42 C231.52,97 226.89,95.4 223.52,91 C222.86,90.13 222.25,89.15 221.6,88.11 C220.14382,85.4164099 218.169266,83.037429 215.79,81.11 C212.58,78.75 208.37,77.6 202.91,77.6 C191.954261,77.6076705 182.084192,84.2206169 177.91,94.35 C183.186964,87.0278244 191.956716,83.0605026 200.940147,83.9314609 C209.923578,84.8024193 217.767888,90.3805017 221.54,98.58 C223.424615,101.689762 227.141337,103.174819 230.65,102.22 C236.02,101.07 235.65,106.15 243.76,107.87 L243.75,106.42 Z"
+      id="Path"
+      fill="#48C4E5"
+    ></path>
+    <path
+      d="M261.46,105.38 L261.46,105.27 C261.34,73.03 235.17,45.45 202.91,45.45 C183.207085,45.4363165 164.821777,55.3450614 154,71.81 L153.79,71.45 L137.23,45.45 L97.5,45.4499858 L135.25,104.57 L98.41,162.57 L137,162.57 L153.79,136.78 L170.88,162.57 L209.48,162.57 L174.48,107.49 C173.899005,106.416838 173.583536,105.220114 173.56,104 C173.557346,96.2203871 176.64661,88.7586448 182.147627,83.2576275 C187.648645,77.7566101 195.110387,74.6673462 202.89,74.67 C219.11,74.67 221.82,84.37 225.32,88.93 C232.23,97.93 246.03,93.99 246.03,105.73 L246.03,105.73 C246.071086,108.480945 247.576662,111.001004 249.979593,112.340896 C252.382524,113.680787 255.317747,113.636949 257.679593,112.225896 C260.041438,110.814842 261.471086,108.250945 261.43,105.5 L261.43,105.5 L261.43,105.38 L261.46,105.38 Z"
+      id="Path"
+      fill="#ffffff"
+    ></path>
+    <path
+      d="M261.5,113.68 C261.892278,116.421801 261.504116,119.218653 260.38,121.75 C258.18,126.84 254.51,125.14 254.51,125.14 C254.51,125.14 251.35,123.6 253.27,120.65 C255.4,117.36 259.61,117.74 261.5,113.68 Z"
+      id="Path"
+      fill="#022f56"
+    ></path>
+  </svg>
+  <h1>Welcome to {{ title }}!</h1>
+</header>
+<main>
+  <h2>Resources &amp; Tools</h2>
+  <p>Thank you for using and showing some ♥ for Nx.</p>
+  <div class="flex github-star-container">
+    <a
+      href="https://github.com/nrwl/nx"
+      target="_blank"
+      rel="noopener noreferrer"
+    >
+      If you like Nx, please give it a star:
+      <div class="github-star-badge">
+        <svg
+          class="material-icons"
+          xmlns="http://www.w3.org/2000/svg"
+          width="24"
+          height="24"
+          viewBox="0 0 24 24"
+        >
+          <path d="M0 0h24v24H0z" fill="none" />
+          <path
+            d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"
+          />
+        </svg>
+        Star
+      </div>
+    </a>
+  </div>
+  <p>Here are some links to help you get started.</p>
+  <ul class="resources">
+    <li class="col-span-2">
+      <a class="resource flex" href="https://nxplaybook.com/p/nx-workspaces">
+        Nx video course
+      </a>
+    </li>
+    <li class="col-span-2">
+      <a
+        class="resource flex"
+        href="https://nx.dev/latest/angular/getting-started/intro"
+      >
+        Nx video tutorial
+      </a>
+    </li>
+    <li class="col-span-2">
+      <a
+        class="resource flex"
+        href="https://nx.dev/latest/angular/tutorial/01-create-application"
+      >
+        Interactive tutorial
+      </a>
+    </li>
+    <li class="col-span-2">
+      <a class="resource flex" href="https://nx.app/">
+        <svg
+          width="36"
+          height="36"
+          viewBox="0 0 120 120"
+          fill="none"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M120 15V30C103.44 30 90 43.44 90 60C90 76.56 76.56 90 60 90C43.44 90 30 103.44 30 120H15C6.72 120 0 113.28 0 105V15C0 6.72 6.72 0 15 0H105C113.28 0 120 6.72 120 15Z"
+            fill="#0E2039"
+          />
+          <path
+            d="M120 30V105C120 113.28 113.28 120 105 120H30C30 103.44 43.44 90 60 90C76.56 90 90 76.56 90 60C90 43.44 103.44 30 120 30Z"
+            fill="white"
+          />
+        </svg>
+        <span class="gutter-left">Nx Cloud</span>
+      </a>
+    </li>
+  </ul>
+  <h2>Next Steps</h2>
+  <p>Here are some things you can do with Nx.</p>
+  <details open>
+    <summary>Add UI library</summary>
+    <pre>
+  # Generate UI lib
+  nx g @nrwl/angular:lib ui
+
+  # Add a component
+  nx g @nrwl/angular:component xyz --project ui</pre
+    >
+  </details>
+  <details>
+    <summary>View dependency graph</summary>
+    <pre>nx dep-graph</pre>
+  </details>
+  <details>
+    <summary>Run affected commands</summary>
+    <pre>
+  # see what's been affected by changes
+  nx affected:dep-graph
+
+  # run tests for current changes
+  nx affected:test
+
+  # run e2e tests for current changes
+  nx affected:e2e
+  </pre
+    >
+  </details>
+</main>
+
diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index 05328e51e9..8892ff3d62 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -1,4 +1,6 @@
-import { test, getTSParsers } from '../utils';
+import { test, getTSParsers, testVersion } from '../utils';
+import fs from 'fs';
+import path from 'path';
 
 import { RuleTester } from 'eslint';
 
@@ -6,7 +8,7 @@ const ruleTester = new RuleTester();
 const rule = require('rules/first');
 
 ruleTester.run('first', rule, {
-  valid: [
+  valid: [].concat(
     test({
       code: "import { x } from './foo'; import { y } from './bar';\
             export { x, y }",
@@ -21,7 +23,12 @@ ruleTester.run('first', rule, {
       code: "'use directive';\
             import { x } from 'foo';",
     }),
-  ],
+    testVersion('>= 7', () => ({
+      // issue #2210
+      code: String(fs.readFileSync(path.join(__dirname, '../../files/component.html'))),
+      parser: require.resolve('@angular-eslint/template-parser'),
+    })),
+  ),
   invalid: [
     test({
       code: "import { x } from './foo';\

From e8d79b5abe295eb956401b06d7dfb87b29ad5635 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 22 Nov 2021 19:36:35 -0800
Subject: [PATCH 423/767] [Tests] fix OSX tests

---
 .travis.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 0a5e87bd32..21a7070fb7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -26,10 +26,10 @@ matrix:
 
 before_install:
   - 'nvm install-latest-npm'
-  - 'npm install'
+  - 'NPM_CONFIG_LEGACY_PEER_DEPS=true npm install'
   - 'npm run copy-metafiles'
 install:
-  - 'npm install'
+  - 'NPM_CONFIG_LEGACY_PEER_DEPS=true npm install'
   - 'if [ -n "${ESLINT_VERSION}" ]; then ./tests/dep-time-travel.sh; fi'
   - 'npm run pretest'
 

From e15631696440396f39dad6daf99d48f56f7defce Mon Sep 17 00:00:00 2001
From: kkyaruek <yoonhaerim@gmail.com>
Date: Thu, 25 Nov 2021 22:42:27 +0900
Subject: [PATCH 424/767] [Docs] `prefer-default-export`: fix typo

---
 docs/rules/prefer-default-export.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/rules/prefer-default-export.md b/docs/rules/prefer-default-export.md
index 23e584bcc9..4dabb695a2 100644
--- a/docs/rules/prefer-default-export.md
+++ b/docs/rules/prefer-default-export.md
@@ -22,7 +22,7 @@ The following patterns are not warnings:
 // There is a default export.
 export const foo = 'foo';
 const bar = 'bar';
-export default 'bar';
+export default bar;
 ```
 
 ```javascript

From ef980d4b116cc5473990a633ef5214b6e37468b0 Mon Sep 17 00:00:00 2001
From: Omri Bernstein <omri.bernstein@newsela.com>
Date: Mon, 20 Dec 2021 17:15:43 -0500
Subject: [PATCH 425/767] [Fix] `importType`: properly resolve `@/*`-aliased
 imports as internal

---
 CHANGELOG.md                                  |  3 +
 src/core/importType.js                        | 78 ++++++++++++-------
 src/rules/extensions.js                       |  1 -
 src/rules/no-cycle.js                         |  1 -
 tests/src/core/importType.js                  | 32 +++++---
 tests/src/rules/no-extraneous-dependencies.js | 17 ++++
 tests/src/rules/no-internal-modules.js        | 24 ++++++
 tests/src/rules/order.js                      | 39 +++++++++-
 8 files changed, 154 insertions(+), 41 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bac6b00404..88d7c411f7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - `importType`: avoid crashing on a non-string' ([#2305], thanks [@ljharb])
 - [`first`]: prevent crash when parsing angular templates ([#2210], thanks [@ljharb])
+- `importType`: properly resolve `@/*`-aliased imports as internal ([#2334], thanks [@ombene])
 
 ### Changed
 - [`no-default-import`]: report on the token "default" instead of the entire node ([#2299], thanks [@pmcelhaney])
@@ -950,6 +951,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
 [#2299]: https://github.com/import-js/eslint-plugin-import/pull/2299
 [#2297]: https://github.com/import-js/eslint-plugin-import/pull/2297
@@ -1571,6 +1573,7 @@ for info on changes for earlier releases.
 [@noelebrun]: https://github.com/noelebrun
 [@ntdb]: https://github.com/ntdb
 [@nwalters512]: https://github.com/nwalters512
+[@ombene]: https://github.com/ombene
 [@ota-meshi]: https://github.com/ota-meshi
 [@panrafal]: https://github.com/panrafal
 [@paztis]: https://github.com/paztis
diff --git a/src/core/importType.js b/src/core/importType.js
index 3e579b9440..ebdb306bc9 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -13,6 +13,11 @@ function baseModule(name) {
   return pkg;
 }
 
+function isInternalRegexMatch(name, settings) {
+  const internalScope = (settings && settings['import/internal-regex']);
+  return internalScope && new RegExp(internalScope).test(name);
+}
+
 export function isAbsolute(name) {
   return typeof name === 'string' && nodeIsAbsolute(name);
 }
@@ -25,33 +30,18 @@ export function isBuiltIn(name, settings, path) {
   return isCoreModule(base) || extras.indexOf(base) > -1;
 }
 
-export function isExternalModule(name, settings, path, context) {
-  if (arguments.length < 4) {
-    throw new TypeError('isExternalModule: name, settings, path, and context are all required');
+export function isExternalModule(name, path, context) {
+  if (arguments.length < 3) {                                                                                                                                                                              
+    throw new TypeError('isExternalModule: name, path, and context are all required');
   }
-  return (isModule(name) || isScoped(name)) && isExternalPath(name, settings, path, getContextPackagePath(context));
-}
-
-export function isExternalModuleMain(name, settings, path, context) {
-  return isModuleMain(name) && isExternalPath(name, settings, path, getContextPackagePath(context));
+  return (isModule(name) || isScoped(name)) && typeTest(name, context, path) === 'external';
 }
 
-function isExternalPath(name, settings, path, packagePath) {
-  const internalScope = (settings && settings['import/internal-regex']);
-  if (internalScope && new RegExp(internalScope).test(name)) {
-    return false;
-  }
-
-  if (!path || relative(packagePath, path).startsWith('..')) {
-    return true;
+export function isExternalModuleMain(name, path, context) {
+  if (arguments.length < 3) {                                                                                                                                                                              
+    throw new TypeError('isExternalModule: name, path, and context are all required');
   }
-
-  const folders = (settings && settings['import/external-module-folders']) || ['node_modules'];
-  return folders.some((folder) => {
-    const folderPath = nodeResolve(packagePath, folder);
-    const relativePath = relative(folderPath, path);
-    return !relativePath.startsWith('..');
-  });
+  return isModuleMain(name) && typeTest(name, context, path) === 'external';
 }
 
 const moduleRegExp = /^\w/;
@@ -87,17 +77,49 @@ function isRelativeToSibling(name) {
   return /^\.[\\/]/.test(name);
 }
 
-function typeTest(name, context, path) {
+function isExternalPath(path, context) {
+  if (!path) {
+    return false;
+  }
+
+  const { settings } = context;
+  const packagePath = getContextPackagePath(context);
+
+  if (relative(packagePath, path).startsWith('..')) {
+    return true;
+  }
+
+  const folders = (settings && settings['import/external-module-folders']) || ['node_modules'];
+  return folders.some((folder) => {
+    const folderPath = nodeResolve(packagePath, folder);
+    const relativePath = relative(folderPath, path);
+    return !relativePath.startsWith('..');
+  });
+}
+
+function isInternalPath(path, context) {
+  if (!path) {
+    return false;
+  }
+  const packagePath = getContextPackagePath(context);
+  return !relative(packagePath, path).startsWith('../');
+}
+
+function isExternalLookingName(name) {
+  return isModule(name) || isScoped(name);
+}
+
+function typeTest(name, context, path ) {
   const { settings } = context;
+  if (isInternalRegexMatch(name, settings)) { return 'internal'; }
   if (isAbsolute(name, settings, path)) { return 'absolute'; }
   if (isBuiltIn(name, settings, path)) { return 'builtin'; }
-  if (isModule(name, settings, path) || isScoped(name, settings, path)) {
-    const packagePath = getContextPackagePath(context);
-    return isExternalPath(name, settings, path, packagePath) ? 'external' : 'internal';
-  }
   if (isRelativeToParent(name, settings, path)) { return 'parent'; }
   if (isIndex(name, settings, path)) { return 'index'; }
   if (isRelativeToSibling(name, settings, path)) { return 'sibling'; }
+  if (isExternalPath(path, context)) { return 'external'; }
+  if (isInternalPath(path, context)) { return 'internal'; }
+  if (isExternalLookingName(name)) { return 'external'; }
   return 'unknown';
 }
 
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 677a0a0959..8596cbfd0f 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -159,7 +159,6 @@ module.exports = {
       // determine if this is a module
       const isPackage = isExternalModule(
         importPath,
-        context.settings,
         resolve(importPath, context),
         context,
       ) || isScoped(importPath);
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index cefa41f99d..e61c3be26c 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -44,7 +44,6 @@ module.exports = {
     const maxDepth = typeof options.maxDepth === 'number' ? options.maxDepth : Infinity;
     const ignoreModule = (name) => options.ignoreExternal && isExternalModule(
       name,
-      context.settings,
       resolve(name, context),
       context,
     );
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 4f4a862a65..937f193033 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -75,6 +75,17 @@ describe('importType(name)', function () {
     expect(importType('constants', pathContext)).to.equal('internal');
   });
 
+  it("should return 'internal' for aliased internal modules that are found, even if they are not discernible as scoped", function () {
+    // `@` for internal modules is a common alias and is different from scoped names.
+    // Scoped names are prepended with `@` (e.g. `@scoped/some-file.js`) whereas `@`
+    // as an alias by itelf is the full root name (e.g. `@/some-file.js`).
+    const alias = { '@': path.join(pathToTestFiles, 'internal-modules') };
+    const webpackConfig = { resolve: { alias } };
+    const pathContext = testContext({ 'import/resolver': { webpack: { config: webpackConfig } } });
+    expect(importType('@/api/service', pathContext)).to.equal('internal');
+    expect(importType('@/does-not-exist', pathContext)).to.equal('unknown');
+  });
+
   it("should return 'parent' for internal modules that go through the parent", function () {
     expect(importType('../foo', context)).to.equal('parent');
     expect(importType('../../foo', context)).to.equal('parent');
@@ -100,6 +111,7 @@ describe('importType(name)', function () {
   it("should return 'unknown' for any unhandled cases", function () {
     expect(importType('  /malformed', context)).to.equal('unknown');
     expect(importType('   foo', context)).to.equal('unknown');
+    expect(importType('-/no-such-path', context)).to.equal('unknown');
   });
 
   it("should return 'builtin' for additional core modules", function () {
@@ -233,20 +245,20 @@ describe('importType(name)', function () {
 
   it('`isExternalModule` works with windows directory separator', function () {
     const context = testContext();
-    expect(isExternalModule('foo', {}, 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
-    expect(isExternalModule('@foo/bar', {}, 'E:\\path\\to\\node_modules\\@foo\\bar', context)).to.equal(true);
-    expect(isExternalModule('foo', {
-      'import/external-module-folders': ['E:\\path\\to\\node_modules'],
-    }, 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
+    expect(isExternalModule('foo', 'E:\\path\\to\\node_modules\\foo', context)).to.equal(true);
+    expect(isExternalModule('@foo/bar', 'E:\\path\\to\\node_modules\\@foo\\bar', context)).to.equal(true);
+    expect(isExternalModule('foo', 'E:\\path\\to\\node_modules\\foo', testContext({
+      settings: { 'import/external-module-folders': ['E:\\path\\to\\node_modules'] },
+    }))).to.equal(true);
   });
 
   it('`isExternalModule` works with unix directory separator', function () {
     const context = testContext();
-    expect(isExternalModule('foo', {}, '/path/to/node_modules/foo', context)).to.equal(true);
-    expect(isExternalModule('@foo/bar', {}, '/path/to/node_modules/@foo/bar', context)).to.equal(true);
-    expect(isExternalModule('foo', {
-      'import/external-module-folders': ['/path/to/node_modules'],
-    }, '/path/to/node_modules/foo', context)).to.equal(true);
+    expect(isExternalModule('foo', '/path/to/node_modules/foo', context)).to.equal(true);
+    expect(isExternalModule('@foo/bar', '/path/to/node_modules/@foo/bar', context)).to.equal(true);
+    expect(isExternalModule('foo', '/path/to/node_modules/foo', testContext({
+      settings: { 'import/external-module-folders': ['/path/to/node_modules'] },
+    }))).to.equal(true);
   });
 
   it('correctly identifies scoped modules with `isScoped`', () => {
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 131604ad95..d4c9f6d7f5 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -164,6 +164,23 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       `,
       settings: { 'import/resolver': 'webpack' },
     }),
+
+    test({
+      code: 'import "@custom-internal-alias/api/service";',
+      settings: {
+        'import/resolver': {
+          webpack: {
+            config: {
+              resolve: {
+                alias: {
+                  '@custom-internal-alias': testFilePath('internal-modules'),
+                },
+              },
+            },
+          },
+        },
+      },
+    }),
   ],
   invalid: [
     test({
diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js
index 2fee9f4502..4a733d142a 100644
--- a/tests/src/rules/no-internal-modules.js
+++ b/tests/src/rules/no-internal-modules.js
@@ -304,6 +304,30 @@ ruleTester.run('no-internal-modules', rule, {
         column: 8,
       } ],
     }),
+    test({
+      code: 'import "@/api/service";',
+      options: [ {
+        forbid: [ '**/api/*' ],
+      } ],
+      errors: [ {
+        message: 'Reaching to "@/api/service" is not allowed.',
+        line: 1,
+        column: 8,
+      } ],
+      settings: {
+        'import/resolver': {
+          webpack: {
+            config: {
+              resolve: {
+                alias: {
+                  '@': testFilePath('internal-modules'),
+                },
+              },
+            },
+          },
+        },
+      },
+    }),
     // exports
     test({
       code: 'export * from "./plugin2/index.js";\nexport * from "./plugin2/app/index"',
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 4b15cec898..79426c4c43 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,4 +1,4 @@
-import { test, getTSParsers, getNonDefaultParsers } from '../utils';
+import { test, getTSParsers, getNonDefaultParsers, testFilePath } from '../utils';
 
 import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
@@ -847,6 +847,43 @@ ruleTester.run('order', rule, {
         ],
       }),
     ]),
+    // Using `@/*` to alias internal modules
+    test({
+      code: `
+        import fs from 'fs';
+
+        import express from 'express';
+
+        import service from '@/api/service';
+        
+        import fooParent from '../foo';
+        
+        import fooSibling from './foo';
+        
+        import index from './';
+        
+        import internalDoesNotExistSoIsUnknown from '@/does-not-exist';
+      `,
+      options: [
+        {
+          groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'],
+          'newlines-between': 'always',
+        },
+      ],
+      settings: {
+        'import/resolver': {
+          webpack: {
+            config: {
+              resolve: {
+                alias: {
+                  '@': testFilePath('internal-modules'),
+                },
+              },
+            },
+          },
+        },
+      },
+    }),
   ],
   invalid: [
     // builtin before external module (require)

From e3ca68edaf7b34ee17afe13f2117fed87c200007 Mon Sep 17 00:00:00 2001
From: Ludovico Fischer <livrerie@gmail.com>
Date: Thu, 30 Dec 2021 18:58:46 +0100
Subject: [PATCH 426/767] [Fix] `named`/`ExportMap`: handle named imports from
 CJS modules that use dynamic import

Fix #2294

Mark ambiguous (i.e. not unambiguously ESM) modules that contain dynamic import()
so that they can be ignored like other ambiguous modules when analysing named imports.

In this way, the named rule accepts named imports from CJS modules that contain
dynamic imports.

Also fix the case where the importing module uses a require() call.
---
 CHANGELOG.md                              |  3 +++
 src/ExportMap.js                          | 10 +++++++++-
 src/rules/named.js                        |  3 ++-
 tests/files/dynamic-import-in-commonjs.js |  5 +++++
 tests/src/rules/named.js                  | 11 ++++++++++-
 5 files changed, 29 insertions(+), 3 deletions(-)
 create mode 100644 tests/files/dynamic-import-in-commonjs.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88d7c411f7..cf11927c7c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - `importType`: avoid crashing on a non-string' ([#2305], thanks [@ljharb])
 - [`first`]: prevent crash when parsing angular templates ([#2210], thanks [@ljharb])
 - `importType`: properly resolve `@/*`-aliased imports as internal ([#2334], thanks [@ombene])
+- [`named`]/`ExportMap`: handle named imports from CJS modules that use dynamic import ([#2341], thanks [@ludofischer])
 
 ### Changed
 - [`no-default-import`]: report on the token "default" instead of the entire node ([#2299], thanks [@pmcelhaney])
@@ -951,6 +952,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2341]: https://github.com/import-js/eslint-plugin-import/pull/2341
 [#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
 [#2299]: https://github.com/import-js/eslint-plugin-import/pull/2299
@@ -1549,6 +1551,7 @@ for info on changes for earlier releases.
 [@lo1tuma]: https://github.com/lo1tuma
 [@loganfsmyth]: https://github.com/loganfsmyth
 [@luczsoma]: https://github.com/luczsoma
+[@ludofischer]: https://github.com/ludofischer
 [@lukeapage]: https://github.com/lukeapage
 [@lydell]: https://github.com/lydell
 [@Mairu]: https://github.com/Mairu
diff --git a/src/ExportMap.js b/src/ExportMap.js
index d818fa6ca8..564b5d63d8 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -43,6 +43,10 @@ export default class ExportMap {
      */
     this.imports = new Map();
     this.errors = [];
+    /**
+     * type {'ambiguous' | 'Module' | 'Script'}
+     */
+    this.parseGoal = 'ambiguous';
   }
 
   get hasDefault() { return this.get('default') != null; } // stronger than this.has
@@ -406,7 +410,8 @@ ExportMap.parse = function (path, content, context) {
     },
   });
 
-  if (!unambiguous.isModule(ast) && !hasDynamicImports) return null;
+  const unambiguouslyESM = unambiguous.isModule(ast);
+  if (!unambiguouslyESM && !hasDynamicImports) return null;
 
   const docstyle = (context.settings && context.settings['import/docstyle']) || ['jsdoc'];
   const docStyleParsers = {};
@@ -710,6 +715,9 @@ ExportMap.parse = function (path, content, context) {
     m.namespace.set('default', {}); // add default export
   }
 
+  if (unambiguouslyESM) {
+    m.parseGoal = 'Module';
+  }
   return m;
 };
 
diff --git a/src/rules/named.js b/src/rules/named.js
index 24e6bc0ac5..a529c295b7 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -40,7 +40,7 @@ module.exports = {
       }
 
       const imports = Exports.get(node.source.value, context);
-      if (imports == null) {
+      if (imports == null || imports.parseGoal === 'ambiguous') {
         return;
       }
 
@@ -97,6 +97,7 @@ module.exports = {
         // return if it's not a string source
         || source.type !== 'Literal'
         || variableExports == null
+        || variableExports.parseGoal === 'ambiguous'
       ) {
         return;
       }
diff --git a/tests/files/dynamic-import-in-commonjs.js b/tests/files/dynamic-import-in-commonjs.js
new file mode 100644
index 0000000000..259feb4cd9
--- /dev/null
+++ b/tests/files/dynamic-import-in-commonjs.js
@@ -0,0 +1,5 @@
+async function doSomething() {
+  await import('./bar.js');
+}
+
+exports.something = 'hello';
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 992baa0fd0..10ba76b79d 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -190,7 +190,16 @@ ruleTester.run('named', rule, {
         sourceType: 'module',
         ecmaVersion: 2020,
       },
-    })) || []),
+    })),
+
+    testVersion('>=7.8.0', () =>({ code: 'const { something } = require("./dynamic-import-in-commonjs")',
+      parserOptions: { ecmaVersion: 2021 },
+      options: [{ commonjs: true }],
+    })),
+
+    testVersion('>=7.8.0', () => ({ code: 'import { something } from "./dynamic-import-in-commonjs"',
+      parserOptions: { ecmaVersion: 2021 } })),
+    ),
   ],
 
   invalid: [

From 210e40a11815bf8ae573324c2449933dcc1df5b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= <nicolo.ribaudo@gmail.com>
Date: Fri, 31 Dec 2021 00:27:03 +0100
Subject: [PATCH 427/767] [utils] [patch] Fix `@babel/eslint-parser` 8
 compatibility

---
 utils/CHANGELOG.md |  7 ++++++-
 utils/parse.js     | 21 +++++++--------------
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 65d67a35c7..e299e01b01 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,10 +5,13 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Fixed
+- [patch] Fix `@babel/eslint-parser` 8 compatibility ([#2343], thanks [@nicolo-ribaudo])
+
 ## v2.7.1 - 2021-10-13
 
 ### Fixed
- - fixed SyntaxError in node <= 6: Unexpected token ) in parse.js ([#2261], thanks [@VitusFW])
+- fixed SyntaxError in node <= 6: Unexpected token ) in parse.js ([#2261], thanks [@VitusFW])
 
 ## v2.7.0 - 2021-10-11
 
@@ -102,6 +105,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2343]: https://github.com/import-js/eslint-plugin-import/pull/2343
 [#2261]: https://github.com/import-js/eslint-plugin-import/pull/2261
 [#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
 [#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
@@ -138,6 +142,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@manuth]: https://github.com/manuth
 [@maxkomarychev]: https://github.com/maxkomarychev
 [@mgwalker]: https://github.com/mgwalker
+[@nicolo-ribaudo]: https://github.com/nicolo-ribaudo
 [@pmcelhaney]: https://github.com/pmcelhaney
 [@sergei-startsev]: https://github.com/sergei-startsev
 [@sompylasar]: https://github.com/sompylasar
diff --git a/utils/parse.js b/utils/parse.js
index a771544ea7..810533ed52 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -7,34 +7,27 @@ const fs = require('fs');
 
 const log = require('debug')('eslint-plugin-import:parse');
 
-function getBabelVisitorKeys(parserPath) {
+function getBabelEslintVisitorKeys(parserPath) {
   if (parserPath.endsWith('index.js')) {
     const hypotheticalLocation = parserPath.replace('index.js', 'visitor-keys.js');
     if (fs.existsSync(hypotheticalLocation)) {
       const keys = moduleRequire(hypotheticalLocation);
       return keys.default || keys;
     }
-  } else if (parserPath.endsWith('index.cjs')) {
-    const hypotheticalLocation = parserPath.replace('index.cjs', 'worker/ast-info.cjs');
-    if (fs.existsSync(hypotheticalLocation)) {
-      const astInfo = moduleRequire(hypotheticalLocation);
-      return astInfo.getVisitorKeys();
-    }
   }
   return null;
 }
 
 function keysFromParser(parserPath, parserInstance, parsedResult) {
+  // Exposed by @typescript-eslint/parser and @babel/eslint-parser
+  if (parsedResult && parsedResult.visitorKeys) {
+    return parsedResult.visitorKeys;
+  }
   if (/.*espree.*/.test(parserPath)) {
     return parserInstance.VisitorKeys;
   }
-  if (/.*(babel-eslint|@babel\/eslint-parser).*/.test(parserPath)) {
-    return getBabelVisitorKeys(parserPath);
-  }
-  if (/.*@typescript-eslint\/parser/.test(parserPath)) {
-    if (parsedResult) {
-      return parsedResult.visitorKeys;
-    }
+  if (/.*babel-eslint.*/.test(parserPath)) {
+    return getBabelEslintVisitorKeys(parserPath);
   }
   return null;
 }

From 9e06effc700b1c1bd5ada3bff42fefa668d99b6d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 1 Jan 2022 22:33:29 -0800
Subject: [PATCH 428/767] [utils] [Refactor] inline `pkgDir` implementation;
 remove `pkg-dir`

---
 utils/CHANGELOG.md |  3 +++
 utils/package.json |  3 +--
 utils/pkgDir.js    | 11 +++++++++++
 utils/resolve.js   |  5 ++---
 4 files changed, 17 insertions(+), 5 deletions(-)
 create mode 100644 utils/pkgDir.js

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index e299e01b01..0ac0704b1d 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -8,6 +8,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [patch] Fix `@babel/eslint-parser` 8 compatibility ([#2343], thanks [@nicolo-ribaudo])
 
+### Changed
+- [Refactor] inline `pkgDir` implementation; remove `pkg-dir`
+
 ## v2.7.1 - 2021-10-13
 
 ### Fixed
diff --git a/utils/package.json b/utils/package.json
index 2c4c53bd47..5c68ed6263 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -27,7 +27,6 @@
   "homepage": "https://github.com/import-js/eslint-plugin-import#readme",
   "dependencies": {
     "debug": "^3.2.7",
-    "find-up": "^2.1.0",
-    "pkg-dir": "^2.0.0"
+    "find-up": "^2.1.0"
   }
 }
diff --git a/utils/pkgDir.js b/utils/pkgDir.js
new file mode 100644
index 0000000000..34412202f1
--- /dev/null
+++ b/utils/pkgDir.js
@@ -0,0 +1,11 @@
+'use strict';
+
+const path = require('path');
+const pkgUp = require('./pkgUp').default;
+
+exports.__esModule = true;
+
+exports.default = function (cwd) {
+  const fp = pkgUp({ cwd });
+  return fp ? path.dirname(fp) : null;
+};
diff --git a/utils/resolve.js b/utils/resolve.js
index 31fb659079..4a35c6a472 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -1,14 +1,13 @@
 'use strict';
 exports.__esModule = true;
 
-const pkgDir = require('pkg-dir');
-
 const fs = require('fs');
 const Module = require('module');
 const path = require('path');
 
 const hashObject = require('./hash').hashObject;
 const ModuleCache = require('./ModuleCache').default;
+const pkgDir = require('./pkgDir').default;
 
 const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname.toUpperCase(), 'reSOLVE.js'));
 exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS;
@@ -175,7 +174,7 @@ function resolverReducer(resolvers, map) {
 }
 
 function getBaseDir(sourceFile) {
-  return pkgDir.sync(sourceFile) || process.cwd();
+  return pkgDir(sourceFile) || process.cwd();
 }
 function requireResolver(name, sourceFile) {
   // Try to resolve package with conventional name

From de8873973a3185b8d4a5c4bbbf6f2f22c4abc288 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 1 Jan 2022 22:36:27 -0800
Subject: [PATCH 429/767] utils: v2.7.2

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 0ac0704b1d..487a064464 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.7.2 - 2022-01-01
+
 ### Fixed
 - [patch] Fix `@babel/eslint-parser` 8 compatibility ([#2343], thanks [@nicolo-ribaudo])
 
diff --git a/utils/package.json b/utils/package.json
index 5c68ed6263..97f95162f1 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.7.1",
+  "version": "2.7.2",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From ef9368150b2ecab02acd6642181ec3e0ba852261 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 1 Jan 2022 22:54:43 -0800
Subject: [PATCH 430/767] [Deps] update `eslint-module-utils`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index a48f86b225..318a9e4346 100644
--- a/package.json
+++ b/package.json
@@ -104,7 +104,7 @@
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
-    "eslint-module-utils": "^2.7.1",
+    "eslint-module-utils": "^2.7.2",
     "has": "^1.0.3",
     "is-core-module": "^2.8.0",
     "is-glob": "^4.0.3",

From dbf668e99026c211ced6125297f47f38e0e866c7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 1 Jan 2022 22:55:45 -0800
Subject: [PATCH 431/767] [Dev Deps] update `safe-publish-latest`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 318a9e4346..170820de4a 100644
--- a/package.json
+++ b/package.json
@@ -89,7 +89,7 @@
     "nyc": "^11.9.0",
     "redux": "^3.7.2",
     "rimraf": "^2.7.1",
-    "safe-publish-latest": "^1.1.4",
+    "safe-publish-latest": "^2.0.0",
     "semver": "^6.3.0",
     "sinon": "^2.4.1",
     "typescript": "^2.8.1 || ~3.9.5",

From 68cea3e6b6fe5fd61e5cf2e2c7c0be9e8dc597cb Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 2 Jan 2022 13:30:53 -0800
Subject: [PATCH 432/767] Bump to v2.25.4

---
 CHANGELOG.md | 6 +++++-
 package.json | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf11927c7c..3894d312c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.25.4] - 2022-01-02
+
 ### Fixed
 - `importType`: avoid crashing on a non-string' ([#2305], thanks [@ljharb])
 - [`first`]: prevent crash when parsing angular templates ([#2210], thanks [@ljharb])
@@ -15,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [`no-default-import`]: report on the token "default" instead of the entire node ([#2299], thanks [@pmcelhaney])
 - [Docs] [`order`]: Remove duplicate mention of default ([#2280], thanks [@johnthagen])
+- [Deps] update `eslint-module-utils`
 
 ## [2.25.3] - 2021-11-09
 
@@ -1344,7 +1347,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.3...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.4...HEAD
+[2.25.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.3...v2.25.4
 [2.25.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.2...v2.25.3
 [2.25.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.1...v2.25.2
 [2.25.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.0...v2.25.1
diff --git a/package.json b/package.json
index 170820de4a..07068866be 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.25.3",
+  "version": "2.25.4",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From df8c1a8c3b7365ca057305996012dc536f44c512 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 11 Jan 2022 22:28:04 -0800
Subject: [PATCH 433/767] [utils] [Fix] `parse`: restore compatibility by
 making the return value `ast` again

Fixes #2350
---
 utils/CHANGELOG.md |  4 ++++
 utils/parse.js     | 27 ++++++++++++++-------------
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 487a064464..7e36bb9fd6 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Fixed
+- [Fix] `parse`: restore compatibility by making the return value `ast` again ([#2350], thanks [@ljharb])
+
 ## v2.7.2 - 2022-01-01
 
 ### Fixed
@@ -110,6 +113,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2350]: https://github.com/import-js/eslint-plugin-import/issues/2350
 [#2343]: https://github.com/import-js/eslint-plugin-import/pull/2343
 [#2261]: https://github.com/import-js/eslint-plugin-import/pull/2261
 [#2212]: https://github.com/import-js/eslint-plugin-import/pull/2212
diff --git a/utils/parse.js b/utils/parse.js
index 810533ed52..98e8215992 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -32,6 +32,16 @@ function keysFromParser(parserPath, parserInstance, parsedResult) {
   return null;
 }
 
+// this exists to smooth over the unintentional breaking change in v2.7.
+// TODO, semver-major: avoid mutating `ast` and return a plain object instead.
+function makeParseReturn(ast, visitorKeys) {
+  if (ast) {
+    ast.visitorKeys = visitorKeys;
+    ast.ast = ast;
+  }
+  return ast;
+}
+
 exports.default = function parse(path, content, context) {
 
   if (context == null) throw new Error('need context to parse properly');
@@ -73,10 +83,7 @@ exports.default = function parse(path, content, context) {
     try {
       const parserRaw = parser.parseForESLint(content, parserOptions);
       ast = parserRaw.ast;
-      return {
-        ast,
-        visitorKeys: keysFromParser(parserPath, parser, parserRaw),
-      };
+      return makeParseReturn(ast, keysFromParser(parserPath, parser, parserRaw));
     } catch (e) {
       console.warn();
       console.warn('Error while parsing ' + parserOptions.filePath);
@@ -89,18 +96,12 @@ exports.default = function parse(path, content, context) {
           '` is invalid and will just be ignored'
       );
     } else {
-      return {
-        ast,
-        visitorKeys: keysFromParser(parserPath, parser, undefined),
-      };
+      return makeParseReturn(ast, keysFromParser(parserPath, parser, undefined));
     }
   }
 
-  const keys = keysFromParser(parserPath, parser, undefined);
-  return {
-    ast: parser.parse(content, parserOptions),
-    visitorKeys: keys,
-  };
+  const ast = parser.parse(content, parserOptions);
+  return makeParseReturn(ast, keysFromParser(parserPath, parser, undefined));
 };
 
 function getParserPath(path, context) {

From 9e4c9a9a06020ed272e49a278c391fcf267e66af Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 11 Jan 2022 22:47:21 -0800
Subject: [PATCH 434/767] [Deps] update `is-core-module`, `resolve`

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 07068866be..6f618421d0 100644
--- a/package.json
+++ b/package.json
@@ -106,11 +106,11 @@
     "eslint-import-resolver-node": "^0.3.6",
     "eslint-module-utils": "^2.7.2",
     "has": "^1.0.3",
-    "is-core-module": "^2.8.0",
+    "is-core-module": "^2.8.1",
     "is-glob": "^4.0.3",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.5",
-    "resolve": "^1.20.0",
+    "resolve": "^1.21.0",
     "tsconfig-paths": "^3.12.0"
   }
 }

From 1cb0dc735f8a6eab77d1b9f29cde2439cc0c5e31 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sat, 22 Jan 2022 11:20:01 +0900
Subject: [PATCH 435/767] [Tests] `no-nodejs-modules`: add tests for node
 protocol URL

---
 CHANGELOG.md                         |  7 ++-
 tests/src/rules/no-nodejs-modules.js | 70 ++++++++++++++++++++++++++--
 2 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3894d312c1..bd878a8b11 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Changed
+- [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
+
 ## [2.25.4] - 2022-01-02
 
 ### Fixed
@@ -955,6 +958,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
 [#2341]: https://github.com/import-js/eslint-plugin-import/pull/2341
 [#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
@@ -1618,6 +1622,7 @@ for info on changes for earlier releases.
 [@skyrpex]: https://github.com/skyrpex
 [@sompylasar]: https://github.com/sompylasar
 [@soryy708]: https://github.com/soryy708
+[@sosukesuzuki]: https://github.com/sosukesuzuki
 [@spalger]: https://github.com/spalger
 [@st-sloth]: https://github.com/st-sloth
 [@stekycz]: https://github.com/stekycz
@@ -1646,4 +1651,4 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xpl]: https://github.com/xpl
 [@yordis]: https://github.com/yordis
-[@zloirock]: https://github.com/zloirock
+[@zloirock]: https://github.com/zloirock
\ No newline at end of file
diff --git a/tests/src/rules/no-nodejs-modules.js b/tests/src/rules/no-nodejs-modules.js
index 3587a71dca..9be605709a 100644
--- a/tests/src/rules/no-nodejs-modules.js
+++ b/tests/src/rules/no-nodejs-modules.js
@@ -1,6 +1,7 @@
 import { test } from '../utils';
 
 import { RuleTester } from 'eslint';
+const isCore = require('is-core-module');
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-nodejs-modules');
@@ -10,7 +11,7 @@ const error = message => ({
 });
 
 ruleTester.run('no-nodejs-modules', rule, {
-  valid: [
+  valid: [].concat(
     test({ code: 'import _ from "lodash"' }),
     test({ code: 'import find from "lodash.find"' }),
     test({ code: 'import foo from "./foo"' }),
@@ -55,8 +56,42 @@ ruleTester.run('no-nodejs-modules', rule, {
         allow: ['path', 'events'],
       }],
     }),
-  ],
-  invalid: [
+    isCore('node:events') ? [
+      test({
+        code: 'import events from "node:events"',
+        options: [{
+          allow: ['node:events'],
+        }],
+      }),
+      test({
+        code: 'var events = require("node:events")',
+        options: [{
+          allow: ['node:events'],
+        }],
+      }),
+    ]: [],
+    isCore('node:path') ? [
+      test({
+        code: 'import path from "node:path"',
+        options: [{
+          allow: ['node:path'],
+        }],
+      }),
+      test({
+        code: 'var path = require("node:path")',
+        options: [{
+          allow: ['node:path'],
+        }],
+      }),
+    ] : [],
+    isCore('node:path') && isCore('node:events') ? test({
+      code: 'import path from "node:path";import events from "node:events"',
+      options: [{
+        allow: ['node:path', 'node:events'],
+      }],
+    }) : [],
+  ),
+  invalid: [].concat(
     test({
       code: 'import path from "path"',
       errors: [error('Do not import Node.js builtin module "path"')],
@@ -80,5 +115,32 @@ ruleTester.run('no-nodejs-modules', rule, {
       }],
       errors: [error('Do not import Node.js builtin module "fs"')],
     }),
-  ],
+    isCore('node:path') ? [
+      test({
+        code: 'import path from "node:path"',
+        errors: [error('Do not import Node.js builtin module "node:path"')],
+      }),
+      test({
+        code: 'var path = require("node:path")',
+        errors: [error('Do not import Node.js builtin module "node:path"')],
+      }),
+    ] : [],
+    isCore('node:fs') ? [
+      test({
+        code: 'import fs from "node:fs"',
+        errors: [error('Do not import Node.js builtin module "node:fs"')],
+      }),
+      test({
+        code: 'var fs = require("node:fs")',
+        errors: [error('Do not import Node.js builtin module "node:fs"')],
+      }),
+      test({
+        code: 'import fs from "node:fs"',
+        options: [{
+          allow: ['node:path'],
+        }],
+        errors: [error('Do not import Node.js builtin module "node:fs"')],
+      }),
+    ] : [],
+  ),
 });

From f795e8f79be7bbb522bab218d1d802f753c4dc4e Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Mon, 17 Jan 2022 17:45:07 +0900
Subject: [PATCH 436/767] [Tests] configure ESLint overrides to parse arbitrary
 module namespace names

---
 tests/files/{.eslintrc => .eslintrc.js} | 40 +++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)
 rename tests/files/{.eslintrc => .eslintrc.js} (85%)

diff --git a/tests/files/.eslintrc b/tests/files/.eslintrc.js
similarity index 85%
rename from tests/files/.eslintrc
rename to tests/files/.eslintrc.js
index 6d36c133b3..6f25298010 100644
--- a/tests/files/.eslintrc
+++ b/tests/files/.eslintrc.js
@@ -1,4 +1,9 @@
-{
+const eslintPkg = require('eslint/package.json');
+const semver = require('semver');
+
+const supportsArbitraryModuleNamespaceIdentifierNames = semver.satisfies(eslintPkg.version, '>= 8.7');
+
+const config = {
   "parser": "babel-eslint",
   "parserOptions": {
     "sourceType": "module",
@@ -281,5 +286,36 @@
     "import/no-duplicates": 0,
     "import/no-extraneous-dependencies": 0,
     "import/unambiguous": 0
-  }
+  },
+  ignorePatterns: [
+    "default-export-namespace-string.js",
+    "default-export-string.js",
+    "export-default-string-and-named.js",
+    "no-unused-modules/arbitrary-module-namespace-identifier-name-a.js",
+    "no-unused-modules/arbitrary-module-namespace-identifier-name-b.js",
+    "no-unused-modules/arbitrary-module-namespace-identifier-name-c.js"
+  ],
+}
+
+if (supportsArbitraryModuleNamespaceIdentifierNames) {
+  config.ignorePatterns = [];
+  config.overrides = [
+    // For parsing arbitrary module namespace names
+    {
+      "files": [
+        "default-export-namespace-string.js",
+        "default-export-string.js",
+        "export-default-string-and-named.js",
+        "no-unused-modules/arbitrary-module-namespace-identifier-name-a.js",
+        "no-unused-modules/arbitrary-module-namespace-identifier-name-b.js",
+        "no-unused-modules/arbitrary-module-namespace-identifier-name-c.js"
+      ],
+      "parser": "espree",
+      "parserOptions": {
+        "ecmaVersion": 2022
+      }
+    }
+  ];
 }
+
+module.exports = config;

From 887e67061de42ac2b416282cd7f92ceb3fb612ee Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sun, 16 Jan 2022 13:39:24 +0900
Subject: [PATCH 437/767] [Tests] `default`, `no-anonymous-default-export`,
 `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`:
 add tests for arbitrary module namespace names

---
 CHANGELOG.md                                  |  2 ++
 .../files/export-default-string-and-named.js  |  4 +++
 tests/src/rules/default.js                    | 14 ++++++--
 .../src/rules/no-anonymous-default-export.js  | 11 ++++--
 tests/src/rules/no-mutable-exports.js         | 20 ++++++++---
 tests/src/rules/no-named-as-default-member.js | 28 ++++++++++++---
 tests/src/rules/no-named-as-default.js        | 34 ++++++++++++++++---
 7 files changed, 92 insertions(+), 21 deletions(-)
 create mode 100644 tests/files/export-default-string-and-named.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd878a8b11..98703defce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
+- [Tests] `default`, `no-anonymous-default-export`, `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 
 ## [2.25.4] - 2022-01-02
 
@@ -959,6 +960,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
+[#2358]: https://github.com/import-js/eslint-plugin-import/pull/2358
 [#2341]: https://github.com/import-js/eslint-plugin-import/pull/2341
 [#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
diff --git a/tests/files/export-default-string-and-named.js b/tests/files/export-default-string-and-named.js
new file mode 100644
index 0000000000..62c7d13c4f
--- /dev/null
+++ b/tests/files/export-default-string-and-named.js
@@ -0,0 +1,4 @@
+const bar = "bar";
+export function foo() {}
+
+export { bar as "default" }
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index 0274e43745..c173f83542 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -1,5 +1,5 @@
 import path from 'path';
-import { test, SYNTAX_CASES, getTSParsers } from '../utils';
+import { test, testVersion, SYNTAX_CASES, getTSParsers } from '../utils';
 import { RuleTester } from 'eslint';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
@@ -8,7 +8,7 @@ const ruleTester = new RuleTester();
 const rule = require('rules/default');
 
 ruleTester.run('default', rule, {
-  valid: [
+  valid: [].concat(
     test({ code: 'import "./malformed.js"' }),
 
     test({ code: 'import foo from "./empty-folder";' }),
@@ -92,8 +92,16 @@ ruleTester.run('default', rule, {
       parser: require.resolve('babel-eslint'),
     }),
 
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'export { "default" as bar } from "./bar"',
+      parserOptions: {
+        ecmaVersion: 2022,
+      },
+    })),
+
     ...SYNTAX_CASES,
-  ],
+  ),
 
   invalid: [
     test({
diff --git a/tests/src/rules/no-anonymous-default-export.js b/tests/src/rules/no-anonymous-default-export.js
index 231f1b667d..0428ee1b99 100644
--- a/tests/src/rules/no-anonymous-default-export.js
+++ b/tests/src/rules/no-anonymous-default-export.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES } from '../utils';
+import { test, testVersion, SYNTAX_CASES } from '../utils';
 
 import { RuleTester } from 'eslint';
 
@@ -6,7 +6,7 @@ const ruleTester = new RuleTester();
 const rule = require('rules/no-anonymous-default-export');
 
 ruleTester.run('no-anonymous-default-export', rule, {
-  valid: [
+  valid: [].concat(
     // Exports with identifiers are valid
     test({ code: 'const foo = 123\nexport default foo' }),
     test({ code: 'export default function foo() {}' }),
@@ -31,12 +31,17 @@ ruleTester.run('no-anonymous-default-export', rule, {
     test({ code: 'export * from \'foo\'' }),
     test({ code: 'const foo = 123\nexport { foo }' }),
     test({ code: 'const foo = 123\nexport { foo as default }' }),
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'const foo = 123\nexport { foo as "default" }',
+      parserOptions: { ecmaVersion: 2022 },
+    })),
 
     // Allow call expressions by default for backwards compatibility
     test({ code: 'export default foo(bar)' }),
 
     ...SYNTAX_CASES,
-  ],
+  ),
 
   invalid: [
     test({ code: 'export default []', errors: [{ message: 'Assign array to a variable before exporting as module default' }] }),
diff --git a/tests/src/rules/no-mutable-exports.js b/tests/src/rules/no-mutable-exports.js
index 2ecae48cdb..e96b841b5c 100644
--- a/tests/src/rules/no-mutable-exports.js
+++ b/tests/src/rules/no-mutable-exports.js
@@ -1,11 +1,11 @@
-import { test } from '../utils';
+import { test, testVersion } from '../utils';
 import { RuleTester } from 'eslint';
 import rule from 'rules/no-mutable-exports';
 
 const ruleTester = new RuleTester();
 
 ruleTester.run('no-mutable-exports', rule, {
-  valid: [
+  valid: [].concat(
     test({ code: 'export const count = 1' }),
     test({ code: 'export function getCount() {}' }),
     test({ code: 'export class Counter {}' }),
@@ -32,8 +32,12 @@ ruleTester.run('no-mutable-exports', rule, {
       parser: require.resolve('babel-eslint'),
       code: 'type Foo = {}\nexport type {Foo}',
     }),
-  ],
-  invalid: [
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'const count = 1\nexport { count as "counter" }', parserOptions: { ecmaVersion: 2022 },
+    })),
+  ),
+  invalid: [].concat(
     test({
       code: 'export let count = 1',
       errors: ['Exporting mutable \'let\' binding, use \'const\' instead.'],
@@ -66,6 +70,12 @@ ruleTester.run('no-mutable-exports', rule, {
       code: 'var count = 1\nexport default count',
       errors: ['Exporting mutable \'var\' binding, use \'const\' instead.'],
     }),
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'let count = 1\nexport { count as "counter" }',
+      errors: ['Exporting mutable \'let\' binding, use \'const\' instead.'],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
 
     // todo: undeclared globals
     // test({
@@ -76,5 +86,5 @@ ruleTester.run('no-mutable-exports', rule, {
     //   code: 'count = 1\nexport default count',
     //   errors: ['Exporting mutable global binding, use \'const\' instead.'],
     // }),
-  ],
+  ),
 });
diff --git a/tests/src/rules/no-named-as-default-member.js b/tests/src/rules/no-named-as-default-member.js
index b4f3cf5896..53cba230ba 100644
--- a/tests/src/rules/no-named-as-default-member.js
+++ b/tests/src/rules/no-named-as-default-member.js
@@ -1,21 +1,27 @@
-import { test, SYNTAX_CASES } from '../utils';
+import { test, testVersion, SYNTAX_CASES } from '../utils';
 import { RuleTester } from 'eslint';
 import rule from 'rules/no-named-as-default-member';
 
 const ruleTester = new RuleTester();
 
 ruleTester.run('no-named-as-default-member', rule, {
-  valid: [
+  valid: [].concat(
     test({ code: 'import bar, {foo} from "./bar";' }),
     test({ code: 'import bar from "./bar"; const baz = bar.baz' }),
     test({ code: 'import {foo} from "./bar"; const baz = foo.baz;' }),
     test({ code: 'import * as named from "./named-exports"; const a = named.a' }),
     test({ code: 'import foo from "./default-export-default-property"; const a = foo.default' }),
 
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'import bar, { foo } from "./export-default-string-and-named"',
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+
     ...SYNTAX_CASES,
-  ],
+  ),
 
-  invalid: [
+  invalid: [].concat(
     test({
       code: 'import bar from "./bar"; const foo = bar.foo;',
       errors: [{
@@ -56,5 +62,17 @@ ruleTester.run('no-named-as-default-member', rule, {
         type: 'Identifier',
       }],
     }),
-  ],
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'import bar from "./export-default-string-and-named"; const foo = bar.foo;',
+      errors: [{
+        message: (
+          'Caution: `bar` also has a named export `foo`. ' +
+          'Check if you meant to write `import {foo} from \'./export-default-string-and-named\'` instead.'
+        ),
+        type: 'MemberExpression',
+      }],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+  ),
 });
diff --git a/tests/src/rules/no-named-as-default.js b/tests/src/rules/no-named-as-default.js
index 57b2f53bd8..129419350e 100644
--- a/tests/src/rules/no-named-as-default.js
+++ b/tests/src/rules/no-named-as-default.js
@@ -1,11 +1,11 @@
-import { test, SYNTAX_CASES } from '../utils';
+import { test, testVersion, SYNTAX_CASES } from '../utils';
 import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-named-as-default');
 
 ruleTester.run('no-named-as-default', rule, {
-  valid: [
+  valid: [].concat(
     test({ code: 'import "./malformed.js"' }),
 
     test({ code: 'import bar, { foo } from "./bar";' }),
@@ -21,10 +21,16 @@ ruleTester.run('no-named-as-default', rule, {
     test({ code: 'export default from "./bar";',
       parser: require.resolve('babel-eslint') }),
 
+    // es2022: Arbitrary module namespae identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'import bar, { foo } from "./export-default-string-and-named"',
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+
     ...SYNTAX_CASES,
-  ],
+  ),
 
-  invalid: [
+  invalid: [].concat(
     test({
       code: 'import foo from "./bar";',
       errors: [ {
@@ -57,5 +63,23 @@ ruleTester.run('no-named-as-default', rule, {
         type: 'Literal',
       }],
     }),
-  ],
+
+    // es2022: Arbitrary module namespae identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'import foo from "./export-default-string-and-named"',
+      errors: [{
+        message: 'Using exported name \'foo\' as identifier for default export.',
+        type: 'ImportDefaultSpecifier',
+      }],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+    testVersion('>= 8.7', () => ({
+      code: 'import foo, { foo as bar } from "./export-default-string-and-named"',
+      errors: [{
+        message: 'Using exported name \'foo\' as identifier for default export.',
+        type: 'ImportDefaultSpecifier',
+      }],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+  ),
 });

From e9a33279a4cc0b9e8f23349100349f6d85eb9f0a Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sat, 15 Jan 2022 14:38:07 +0900
Subject: [PATCH 438/767] [New] `no-named-default`: support arbitrary module
 namespace names

---
 CHANGELOG.md                        |  3 +++
 src/rules/no-named-default.js       |  2 +-
 tests/src/rules/no-named-default.js | 18 +++++++++++++++---
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98703defce..2c87b3aac2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Added
+- [`no-named-default`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
 - [Tests] `default`, `no-anonymous-default-export`, `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
diff --git a/src/rules/no-named-default.js b/src/rules/no-named-default.js
index 116c89cf57..6a5c1db703 100644
--- a/src/rules/no-named-default.js
+++ b/src/rules/no-named-default.js
@@ -17,7 +17,7 @@ module.exports = {
             return;
           }
 
-          if (im.type === 'ImportSpecifier' && im.imported.name === 'default') {
+          if (im.type === 'ImportSpecifier' && (im.imported.name || im.imported.value) === 'default') {
             context.report({
               node: im.local,
               message: `Use default import syntax to import '${im.local.name}'.` });
diff --git a/tests/src/rules/no-named-default.js b/tests/src/rules/no-named-default.js
index 56470f2bac..1ed1502871 100644
--- a/tests/src/rules/no-named-default.js
+++ b/tests/src/rules/no-named-default.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES } from '../utils';
+import { test, testVersion, SYNTAX_CASES } from '../utils';
 import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester();
@@ -22,7 +22,7 @@ ruleTester.run('no-named-default', rule, {
     ...SYNTAX_CASES,
   ],
 
-  invalid: [
+  invalid: [].concat(
     /*test({
       code: 'import { default } from "./bar";',
       errors: [{
@@ -45,5 +45,17 @@ ruleTester.run('no-named-default', rule, {
         type: 'Identifier',
       }],
     }),
-  ],
+
+    // es2022: Arbitrary module namespae identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'import { "default" as bar } from "./bar";',
+      errors: [{
+        message: 'Use default import syntax to import \'bar\'.',
+        type: 'Identifier',
+      }],
+      parserOptions: {
+        ecmaVersion: 2022,
+      },
+    })) || [],
+  ),
 });

From c296b0bedb58e2f905d306bac2f1b4d5ef8adecc Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sat, 15 Jan 2022 15:05:52 +0900
Subject: [PATCH 439/767] [New] `no-default-export`: support arbitrary module
 namespace names

---
 CHANGELOG.md                         |  2 +-
 src/rules/no-default-export.js       |  2 +-
 tests/src/rules/no-default-export.js | 11 +++++++++++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c87b3aac2..755ebec2a0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## [Unreleased]
 
 ### Added
-- [`no-named-default`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-named-default`, `no-default-export`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index a17428c563..ed1aaf8db6 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -25,7 +25,7 @@ module.exports = {
       },
 
       ExportNamedDeclaration(node) {
-        node.specifiers.filter(specifier => specifier.exported.name === 'default').forEach(specifier => {
+        node.specifiers.filter(specifier => (specifier.exported.name || specifier.exported.value) === 'default').forEach(specifier => {
           const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {};
           if (specifier.type === 'ExportDefaultSpecifier') {
             context.report({ node, message: preferNamed, loc });
diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index 61e55d9593..1d149421f9 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -162,5 +162,16 @@ ruleTester.run('no-default-export', rule, {
         },
       ],
     }),
+    // es2022: Arbitrary module namespae identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'let foo; export { foo as "default" }',
+      errors: [
+        {
+          type: 'ExportNamedDeclaration',
+          message: 'Do not alias `foo` as `default`. Just export `foo` itself instead.',
+        },
+      ],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
   ),
 });

From 16c5add20b4aa526426e427efab57f67857dbb52 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sat, 15 Jan 2022 15:11:46 +0900
Subject: [PATCH 440/767] [New] `prefer-default-export`: support arbitrary
 module namespace names

---
 CHANGELOG.md                             |  2 +-
 src/rules/prefer-default-export.js       |  2 +-
 tests/src/rules/prefer-default-export.js | 11 ++++++++---
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 755ebec2a0..b70aa88e73 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## [Unreleased]
 
 ### Added
-- [`no-named-default`, `no-default-export`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-named-default`, `no-default-export`, `prefer-default-export`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index a8c52bb1a0..230efad12f 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -40,7 +40,7 @@ module.exports = {
       },
 
       'ExportSpecifier': function (node) {
-        if (node.exported.name === 'default') {
+        if ((node.exported.name || node.exported.value) === 'default') {
           hasDefaultExport = true;
         } else {
           specifierExportCount++;
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 36205b1935..d00a99668b 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -1,4 +1,4 @@
-import { test, getNonDefaultParsers } from '../utils';
+import { test, testVersion, getNonDefaultParsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 
@@ -6,7 +6,7 @@ const ruleTester = new RuleTester();
 const rule = require('../../../src/rules/prefer-default-export');
 
 ruleTester.run('prefer-default-export', rule, {
-  valid: [
+  valid: [].concat(
     test({
       code: `
         export const foo = 'foo';
@@ -94,7 +94,12 @@ ruleTester.run('prefer-default-export', rule, {
       `,
       parser: require.resolve('babel-eslint'),
     }),
-  ],
+    // es2022: Arbitrary module namespae identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'let foo; export { foo as "default" };',
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+  ),
   invalid: [
     test({
       code: `

From 8ee2497fd5c9d62c1a167f7b0680295fb07a3204 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sat, 15 Jan 2022 15:20:46 +0900
Subject: [PATCH 441/767] [New] `no-named-export`: support arbitrary module
 namespace names

---
 CHANGELOG.md                       |  2 +-
 src/rules/no-named-export.js       |  2 +-
 tests/src/rules/no-named-export.js | 12 +++++++++---
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b70aa88e73..d2f11444fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## [Unreleased]
 
 ### Added
-- [`no-named-default`, `no-default-export`, `prefer-default-export`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
diff --git a/src/rules/no-named-export.js b/src/rules/no-named-export.js
index bb586ead00..6c92ad9cae 100644
--- a/src/rules/no-named-export.js
+++ b/src/rules/no-named-export.js
@@ -25,7 +25,7 @@ module.exports = {
           return context.report({ node, message });
         }
 
-        const someNamed = node.specifiers.some(specifier => specifier.exported.name !== 'default');
+        const someNamed = node.specifiers.some(specifier => (specifier.exported.name || specifier.exported.value) !== 'default');
         if (someNamed) {
           context.report({ node, message });
         }
diff --git a/tests/src/rules/no-named-export.js b/tests/src/rules/no-named-export.js
index 41d0fcd7cf..4d8978b35f 100644
--- a/tests/src/rules/no-named-export.js
+++ b/tests/src/rules/no-named-export.js
@@ -1,11 +1,11 @@
 import { RuleTester } from 'eslint';
-import { test } from '../utils';
+import { test, testVersion } from '../utils';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-named-export');
 
 ruleTester.run('no-named-export', rule, {
-  valid: [
+  valid: [].concat(
     test({
       code: 'export default function bar() {};',
     }),
@@ -27,7 +27,13 @@ ruleTester.run('no-named-export', rule, {
     test({
       code: `import {default as foo} from './foo';`,
     }),
-  ],
+
+    // es2022: Arbitrary module namespae identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'let foo; export { foo as "default" }',
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+  ),
   invalid: [
     test({
       code: `

From 4382b345e777a58a576029a755d5c72051a07542 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sun, 16 Jan 2022 13:51:12 +0900
Subject: [PATCH 442/767] [New] `export`: support arbitrary namespace names

---
 CHANGELOG.md              |  2 +-
 src/rules/export.js       |  2 +-
 tests/src/rules/export.js | 16 ++++++++++++++--
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d2f11444fd..a223919d1e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## [Unreleased]
 
 ### Added
-- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
diff --git a/src/rules/export.js b/src/rules/export.js
index e0b2c57857..b9378f0910 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -88,7 +88,7 @@ module.exports = {
       'ExportDefaultDeclaration': (node) => addNamed('default', node, getParent(node)),
 
       'ExportSpecifier': (node) => addNamed(
-        node.exported.name,
+        node.exported.name || node.exported.value,
         node.exported,
         getParent(node.parent),
       ),
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 29fae41015..d075aea6bd 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -46,7 +46,7 @@ ruleTester.run('export', rule, {
     })) || [],
   ),
 
-  invalid: [
+  invalid: [].concat(
     // multiple defaults
     // test({
     //   code: 'export default foo; export default bar',
@@ -122,7 +122,19 @@ ruleTester.run('export', rule, {
       code: 'export * from "./default-export"',
       errors: [`No named exports found in module './default-export'.`],
     }),
-  ],
+
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'let foo; export { foo as "foo" }; export * from "./export-all"',
+      errors: [
+        'Multiple exports of name \'foo\'.',
+        'Multiple exports of name \'foo\'.',
+      ],
+      parserOptions: {
+        ecmaVersion: 2022,
+      },
+    })),
+  ),
 });
 
 

From 8cd3a0ef3f52c3385703ab2cb5d6c978a467ebb1 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sun, 16 Jan 2022 14:44:13 +0900
Subject: [PATCH 443/767] [New] `named`: support arbitrary module namespace
 names

---
 CHANGELOG.md             |  2 +-
 src/rules/named.js       |  8 +++++---
 tests/src/rules/named.js | 32 +++++++++++++++++++++++++++-----
 3 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a223919d1e..9dcb2a5b7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## [Unreleased]
 
 ### Added
-- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
diff --git a/src/rules/named.js b/src/rules/named.js
index a529c295b7..ad1b5e1728 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -58,7 +58,9 @@ module.exports = {
           return;
         }
 
-        const deepLookup = imports.hasDeep(im[key].name);
+        const name = im[key].name || im[key].value;
+
+        const deepLookup = imports.hasDeep(name);
 
         if (!deepLookup.found) {
           if (deepLookup.path.length > 1) {
@@ -66,9 +68,9 @@ module.exports = {
               .map(i => path.relative(path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename()), i.path))
               .join(' -> ');
 
-            context.report(im[key], `${im[key].name} not found via ${deepPath}`);
+            context.report(im[key], `${name} not found via ${deepPath}`);
           } else {
-            context.report(im[key], im[key].name + ' not found in \'' + node.source.value + '\'');
+            context.report(im[key], name + ' not found in \'' + node.source.value + '\'');
           }
         }
       });
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 10ba76b79d..af2f9ce185 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -7,9 +7,8 @@ import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 const ruleTester = new RuleTester();
 const rule = require('rules/named');
 
-function error(name, module) {
-  return { message: name + ' not found in \'' + module + '\'',
-    type: 'Identifier' };
+function error(name, module, type = 'Identifier') {
+  return { message: name + ' not found in \'' + module + '\'', type };
 }
 
 ruleTester.run('named', rule, {
@@ -199,10 +198,16 @@ ruleTester.run('named', rule, {
 
     testVersion('>=7.8.0', () => ({ code: 'import { something } from "./dynamic-import-in-commonjs"',
       parserOptions: { ecmaVersion: 2021 } })),
+
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'import { "foo" as foo } from "./bar"', parserOptions: { ecmaVersion: 2022 } })),
+    testVersion('>= 8.7', () => ({
+      code: 'import { "foo" as foo } from "./empty-module"', parserOptions: { ecmaVersion: 2022 } })),
     ),
   ],
 
-  invalid: [
+  invalid: [].concat(
     test({ code: 'import { somethingElse } from "./test-module"',
       errors: [ error('somethingElse', './test-module') ] }),
 
@@ -323,7 +328,24 @@ ruleTester.run('named', rule, {
       code: 'import { default as barDefault } from "./re-export"',
       errors: [`default not found in './re-export'`],
     }),
-  ],
+
+    // es2022: Arbitrary module namespace identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'import { "somethingElse" as somethingElse } from "./test-module"',
+      errors: [ error('somethingElse', './test-module', 'Literal') ],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+    testVersion('>= 8.7', () => ({
+      code: 'import { "baz" as baz, "bop" as bop } from "./bar"',
+      errors: [error('baz', './bar', 'Literal'), error('bop', './bar', 'Literal')],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+    testVersion('>= 8.7', () => ({
+      code: 'import { "default" as barDefault } from "./re-export"',
+      errors: [`default not found in './re-export'`],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+  ),
 });
 
 // #311: import of mismatched case

From 37126ec0b74342ec494905ad9f5cb1fe8eb6f3d8 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sun, 16 Jan 2022 16:02:29 +0900
Subject: [PATCH 444/767] [New] `namespace`: support arbitrary module namespace
 names

---
 CHANGELOG.md                                  |  2 +-
 src/ExportMap.js                              |  4 +-
 src/rules/namespace.js                        |  2 +-
 .../files/default-export-namespace-string.js  |  1 +
 tests/files/default-export-string.js          |  3 ++
 tests/src/rules/namespace.js                  | 42 +++++++++++++++++--
 6 files changed, 47 insertions(+), 7 deletions(-)
 create mode 100644 tests/files/default-export-namespace-string.js
 create mode 100644 tests/files/default-export-string.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9dcb2a5b7a..7397016776 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## [Unreleased]
 
 ### Added
-- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 564b5d63d8..f11a8752fc 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -479,11 +479,11 @@ ExportMap.parse = function (path, content, context) {
       }));
       return;
     case 'ExportAllDeclaration':
-      m.namespace.set(s.exported.name, addNamespace(exportMeta, s.source.value));
+      m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.source.value));
       return;
     case 'ExportSpecifier':
       if (!n.source) {
-        m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local));
+        m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.local));
         return;
       }
       // else falls through
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 6325b88ba2..8a7099df61 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -69,7 +69,7 @@ module.exports = {
             case 'ImportSpecifier': {
               const meta = imports.get(
                 // default to 'default' for default https://i.imgur.com/nj6qAWy.jpg
-                specifier.imported ? specifier.imported.name : 'default',
+                specifier.imported ? (specifier.imported.name || specifier.imported.value) : 'default',
               );
               if (!meta || !meta.namespace) { break; }
               namespaces.set(specifier.local.name, meta.namespace);
diff --git a/tests/files/default-export-namespace-string.js b/tests/files/default-export-namespace-string.js
new file mode 100644
index 0000000000..5b4a01ab72
--- /dev/null
+++ b/tests/files/default-export-namespace-string.js
@@ -0,0 +1 @@
+export * as "default" from "./named-exports";
diff --git a/tests/files/default-export-string.js b/tests/files/default-export-string.js
new file mode 100644
index 0000000000..4f68b517e6
--- /dev/null
+++ b/tests/files/default-export-string.js
@@ -0,0 +1,3 @@
+function foo() { return 'bar' }
+
+export { foo as "default" }
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 826637b970..15ab133b1f 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -183,10 +183,35 @@ const valid = [
     parserOptions: {
       ecmaVersion: 2020,
     },
-  })) || []),
+  })),
+  // es2022: Arbitrary module namespace identifier names
+  testVersion('>= 8.7', () => ({
+    code: "import * as names from './default-export-string';",
+    parserOptions: { ecmaVersion: 2022 },
+  })),
+  testVersion('>= 8.7', () => ({
+    code: "import * as names from './default-export-string'; console.log(names.default)",
+    parserOptions: { ecmaVersion: 2022 },
+  })),
+  testVersion('>= 8.7', () => ({
+    code: "import * as names from './default-export-namespace-string';",
+    parserOptions: { ecmaVersion: 2022 },
+  })),
+  testVersion('>= 8.7', () => ({
+    code: "import * as names from './default-export-namespace-string'; console.log(names.default)",
+    parserOptions: { ecmaVersion: 2022 },
+  })),
+  testVersion('>= 8.7', () => ({
+    code: `import { "b" as b } from "./deep/a"; console.log(b.c.d.e)`,
+    parserOptions: { ecmaVersion: 2022 },
+  })),
+  testVersion('>= 8.7', () => ({
+    code: `import { "b" as b } from "./deep/a"; var {c:{d:{e}}} = b`,
+    parserOptions: { ecmaVersion: 2022 },
+  }))),
 ];
 
-const invalid = [
+const invalid = [].concat(
   test({ code: "import * as names from './named-exports'; " +
                ' console.log(names.c);',
   errors: [error('c', 'names')] }),
@@ -275,7 +300,18 @@ const invalid = [
     },
   }),
 
-]
+  // es2022: Arbitrary module namespace identifier names
+  testVersion('>= 8.7', () => ({
+    code: `import { "b" as b } from "./deep/a"; console.log(b.e)`,
+    errors: [ "'e' not found in imported namespace 'b'." ],
+    parserOptions: { ecmaVersion: 2022 },
+  })),
+  testVersion('>= 8.7', () => ({
+    code: `import { "b" as b } from "./deep/a"; console.log(b.c.e)`,
+    errors: [ "'e' not found in deeply imported namespace 'b.c'." ],
+    parserOptions: { ecmaVersion: 2022 },
+  })),
+)
 
 ///////////////////////
 // deep dereferences //

From 1becbb1ea5073fe592e117cbf2079e31e116d4c7 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Mon, 17 Jan 2022 16:41:23 +0900
Subject: [PATCH 445/767] [New] `no-unused-modules`: support arbitrary module
 namespace names

---
 CHANGELOG.md                                  |  2 +-
 src/ExportMap.js                              |  2 +-
 src/rules/no-unused-modules.js                | 10 +++---
 ...rary-module-namespace-identifier-name-a.js |  2 ++
 ...rary-module-namespace-identifier-name-b.js |  1 +
 ...rary-module-namespace-identifier-name-c.js |  2 ++
 tests/src/rules/no-unused-modules.js          | 32 ++++++++++++++++++-
 7 files changed, 43 insertions(+), 8 deletions(-)
 create mode 100644 tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-a.js
 create mode 100644 tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-b.js
 create mode 100644 tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-c.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7397016776..63de41cd73 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## [Unreleased]
 
 ### Added
-- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
diff --git a/src/ExportMap.js b/src/ExportMap.js
index f11a8752fc..7425dce44a 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -593,7 +593,7 @@ ExportMap.parse = function (path, content, context) {
           importedSpecifiers.add(specifier.type);
         }
         if (specifier.type === 'ImportSpecifier') {
-          importedSpecifiers.add(specifier.imported.name);
+          importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
         }
 
         // import { type Foo } (Flow)
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 9891d4097e..efc2169946 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -604,7 +604,7 @@ module.exports = {
           if (specifiers.length > 0) {
             specifiers.forEach(specifier => {
               if (specifier.exported) {
-                newExportIdentifiers.add(specifier.exported.name);
+                newExportIdentifiers.add(specifier.exported.name || specifier.exported.value);
               }
             });
           }
@@ -715,8 +715,8 @@ module.exports = {
           if (astNode.source) {
             resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context);
             astNode.specifiers.forEach(specifier => {
-              const name = specifier.local.name;
-              if (specifier.local.name === DEFAULT) {
+              const name = specifier.local.name || specifier.local.value;
+              if (name === DEFAULT) {
                 newDefaultImports.add(resolvedPath);
               } else {
                 newImports.set(name, resolvedPath);
@@ -753,7 +753,7 @@ module.exports = {
                 specifier.type === IMPORT_NAMESPACE_SPECIFIER) {
               return;
             }
-            newImports.set(specifier.imported.name, resolvedPath);
+            newImports.set(specifier.imported.name || specifier.imported.value, resolvedPath);
           });
         }
       });
@@ -942,7 +942,7 @@ module.exports = {
       },
       'ExportNamedDeclaration': node => {
         node.specifiers.forEach(specifier => {
-          checkUsage(node, specifier.exported.name);
+          checkUsage(node, specifier.exported.name || specifier.exported.value);
         });
         forEachDeclarationIdentifier(node.declaration, (name) => {
           checkUsage(node, name);
diff --git a/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-a.js b/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-a.js
new file mode 100644
index 0000000000..7ad810de86
--- /dev/null
+++ b/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-a.js
@@ -0,0 +1,2 @@
+const foo = 333
+export { foo as "foo" }
diff --git a/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-b.js b/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-b.js
new file mode 100644
index 0000000000..fa7652725e
--- /dev/null
+++ b/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-b.js
@@ -0,0 +1 @@
+import { "foo" as foo } from "./arbitrary-module-namespace-identifier-name-a.js"
diff --git a/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-c.js b/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-c.js
new file mode 100644
index 0000000000..7ad810de86
--- /dev/null
+++ b/tests/files/no-unused-modules/arbitrary-module-namespace-identifier-name-c.js
@@ -0,0 +1,2 @@
+const foo = 333
+export { foo as "foo" }
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 6f87058c4a..8610ff4aa0 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -1,4 +1,4 @@
-import { test, testFilePath, getTSParsers } from '../utils';
+import { test, testVersion, testFilePath, getTSParsers } from '../utils';
 import jsxConfig from '../../../config/react';
 import typescriptConfig from '../../../config/typescript';
 
@@ -1261,3 +1261,33 @@ describe('support (nested) destructuring assignment', () => {
     invalid: [],
   });
 });
+
+describe('support ES2022 Arbitrary module namespace identifier names', () => {
+  ruleTester.run('no-unused-module', rule, {
+    valid: [].concat(
+      testVersion('>= 8.7', () => ({
+        options: unusedExportsOptions,
+        code: `import { "foo" as foo } from "./arbitrary-module-namespace-identifier-name-a"`,
+        parserOptions: { ecmaVersion: 2022 },
+        filename: testFilePath('./no-unused-modules/arbitrary-module-namespace-identifier-name-b.js'),
+      })),
+      testVersion('>= 8.7', () => ({
+        options: unusedExportsOptions,
+        code: 'const foo = 333;\nexport { foo as "foo" }',
+        parserOptions: { ecmaVersion: 2022 },
+        filename: testFilePath('./no-unused-modules/arbitrary-module-namespace-identifier-name-a.js'),
+      })),
+    ),
+    invalid: [].concat(
+      testVersion('>= 8.7', () => ({
+        options: unusedExportsOptions,
+        code: 'const foo = 333\nexport { foo as "foo" }',
+        parserOptions: { ecmaVersion: 2022 },
+        filename: testFilePath('./no-unused-modules/arbitrary-module-namespace-identifier-name-c.js'),
+        errors: [
+          error(`exported declaration 'foo' not used within other modules`),
+        ],
+      })),
+    ),
+  });
+});

From 7cead4674e363eb055599b5ca229ec75a424c81b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 23 Jan 2022 08:32:50 -0800
Subject: [PATCH 446/767] [Deps] update `resolve`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 6f618421d0..1f958ec745 100644
--- a/package.json
+++ b/package.json
@@ -110,7 +110,7 @@
     "is-glob": "^4.0.3",
     "minimatch": "^3.0.4",
     "object.values": "^1.1.5",
-    "resolve": "^1.21.0",
+    "resolve": "^1.22.0",
     "tsconfig-paths": "^3.12.0"
   }
 }

From b74013ded017c65ffe8d9a47e14935d2c605b2d3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 23 Jan 2022 08:37:48 -0800
Subject: [PATCH 447/767] [Tests] export resolved parsers for cleaner
 comparison

---
 tests/src/core/getExports.js                  |  1 -
 tests/src/rules/default.js                    | 28 ++++++-------
 tests/src/rules/dynamic-import-chunkname.js   |  6 +--
 tests/src/rules/extensions.js                 |  4 +-
 tests/src/rules/max-dependencies.js           |  8 ++--
 tests/src/rules/named.js                      | 34 +++++++--------
 tests/src/rules/namespace.js                  | 20 ++++-----
 tests/src/rules/newline-after-import.js       | 20 ++++-----
 tests/src/rules/no-cycle.js                   | 24 +++++------
 tests/src/rules/no-default-export.js          | 12 +++---
 tests/src/rules/no-duplicates.js              |  8 ++--
 tests/src/rules/no-dynamic-require.js         | 30 ++++++-------
 tests/src/rules/no-extraneous-dependencies.js | 12 +++---
 tests/src/rules/no-mutable-exports.js         |  6 +--
 tests/src/rules/no-named-as-default.js        | 12 +++---
 tests/src/rules/no-named-default.js           |  8 ++--
 tests/src/rules/no-named-export.js            | 12 +++---
 tests/src/rules/no-relative-parent-imports.js |  4 +-
 tests/src/rules/no-unresolved.js              | 18 ++++----
 tests/src/rules/no-unused-modules.js          | 42 +++++++++----------
 tests/src/rules/no-useless-path-segments.js   | 14 +++----
 tests/src/rules/order.js                      |  4 +-
 tests/src/rules/prefer-default-export.js      | 12 +++---
 tests/src/rules/unambiguous.js                |  3 +-
 tests/src/utils.js                            | 25 +++++------
 25 files changed, 184 insertions(+), 183 deletions(-)

diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 604ae5cf28..867644bc19 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -343,7 +343,6 @@ describe('ExportMap', function () {
   });
 
   context('alternate parsers', function () {
-
     const configs = [
       // ['string form', { 'typescript-eslint-parser': '.ts' }],
     ];
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index c173f83542..9eab9a5a35 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -1,5 +1,5 @@
 import path from 'path';
-import { test, testVersion, SYNTAX_CASES, getTSParsers } from '../utils';
+import { test, testVersion, SYNTAX_CASES, getTSParsers, parsers } from '../utils';
 import { RuleTester } from 'eslint';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
@@ -29,19 +29,19 @@ ruleTester.run('default', rule, {
 
     // es7 export syntax
     test({ code: 'export bar from "./bar"',
-      parser: require.resolve('babel-eslint') }),
+      parser: parsers.BABEL_OLD }),
     test({ code: 'export { default as bar } from "./bar"' }),
     test({ code: 'export bar, { foo } from "./bar"',
-      parser: require.resolve('babel-eslint') }),
+      parser: parsers.BABEL_OLD }),
     test({ code: 'export { default as bar, foo } from "./bar"' }),
     test({ code: 'export bar, * as names from "./bar"',
-      parser: require.resolve('babel-eslint') }),
+      parser: parsers.BABEL_OLD }),
 
     // sanity check
     test({ code: 'export {a} from "./named-exports"' }),
     test({
       code: 'import twofer from "./trampoline"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // jsx
@@ -69,27 +69,27 @@ ruleTester.run('default', rule, {
     // from no-errors
     test({
       code: "import Foo from './jsx/FooES7.js';",
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // #545: more ES7 cases
     test({
       code: "import bar from './default-export-from.js';",
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: "import bar from './default-export-from-named.js';",
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: "import bar from './default-export-from-ignored.js';",
       settings: { 'import/ignore': ['common'] },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: "export bar from './default-export-from-ignored.js';",
       settings: { 'import/ignore': ['common'] },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // es2022: Arbitrary module namespace identifier names
@@ -117,23 +117,23 @@ ruleTester.run('default', rule, {
     // es7 export syntax
     test({
       code: 'export baz from "./named-exports"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ['No default export found in imported module "./named-exports".'],
     }),
     test({
       code: 'export baz, { bar } from "./named-exports"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ['No default export found in imported module "./named-exports".'],
     }),
     test({
       code: 'export baz, * as names from "./named-exports"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ['No default export found in imported module "./named-exports".'],
     }),
     // exports default from a module with no default
     test({
       code: 'import twofer from "./broken-trampoline"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ['No default export found in imported module "./broken-trampoline".'],
     }),
 
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index a2ee55f13a..7e482cf03c 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -1,4 +1,4 @@
-import { SYNTAX_CASES, getTSParsers } from '../utils';
+import { SYNTAX_CASES, getTSParsers, parsers } from '../utils';
 import { RuleTester } from 'eslint';
 import semver from 'semver';
 
@@ -15,7 +15,7 @@ const pickyCommentOptions = [{
 const multipleImportFunctionOptions = [{
   importFunctions: ['dynamicImport', 'definitelyNotStaticImport'],
 }];
-const parser = require.resolve('babel-eslint');
+const parser = parsers.BABEL_OLD;
 
 const noLeadingCommentError = 'dynamic imports require a leading comment with the webpack chunkname';
 const nonBlockCommentError = 'dynamic imports require a /* foo */ style comment, not a // foo comment';
@@ -495,7 +495,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
 
 context('TypeScript', () => {
   getTSParsers().forEach((typescriptParser) => {
-    const nodeType = typescriptParser.includes('typescript-eslint-parser') || (typescriptParser.includes('@typescript-eslint/parser') && semver.satisfies(require('@typescript-eslint/parser/package.json').version, '^2'))
+    const nodeType = typescriptParser === parsers.TS_OLD || (typescriptParser === parsers.TS_NEW && semver.satisfies(require('@typescript-eslint/parser/package.json').version, '^2'))
       ? 'CallExpression'
       : 'ImportExpression';
 
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 93ebc28f8e..cf93fac9f4 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -1,6 +1,6 @@
 import { RuleTester } from 'eslint';
 import rule from 'rules/extensions';
-import { getTSParsers, test, testFilePath } from '../utils';
+import { getTSParsers, test, testFilePath, parsers } from '../utils';
 
 const ruleTester = new RuleTester();
 
@@ -601,7 +601,7 @@ ruleTester.run('extensions', rule, {
 describe('TypeScript', () => {
   getTSParsers()
     // Type-only imports were added in TypeScript ESTree 2.23.0
-    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .filter((parser) => parser !== parsers.TS_OLD)
     .forEach((parser) => {
       ruleTester.run(`${parser}: extensions ignore type-only`, rule, {
         valid: [
diff --git a/tests/src/rules/max-dependencies.js b/tests/src/rules/max-dependencies.js
index 6d80bbf046..982a4b427a 100644
--- a/tests/src/rules/max-dependencies.js
+++ b/tests/src/rules/max-dependencies.js
@@ -1,4 +1,4 @@
-import { test, getTSParsers } from '../utils';
+import { test, getTSParsers, parsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 
@@ -66,7 +66,7 @@ ruleTester.run('max-dependencies', rule, {
 
     test({
       code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{
         max: 1,
       }],
@@ -77,7 +77,7 @@ ruleTester.run('max-dependencies', rule, {
 
     test({
       code: 'import type { x } from \'./foo\'; import type { y } from \'./bar\'; import type { z } from \'./baz\'',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{
         max: 2,
         ignoreTypeImports: false,
@@ -92,7 +92,7 @@ ruleTester.run('max-dependencies', rule, {
 describe('TypeScript', () => {
   getTSParsers()
     // Type-only imports were added in TypeScript ESTree 2.23.0
-    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .filter((parser) => parser !== parsers.TS_OLD)
     .forEach((parser) => {
       ruleTester.run(`max-dependencies (${parser.replace(process.cwd(), '.')})`, rule, {
         valid: [
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index af2f9ce185..b5500a6d31 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES, getTSParsers, testFilePath, testVersion } from '../utils';
+import { test, SYNTAX_CASES, getTSParsers, testFilePath, testVersion, parsers } from '../utils';
 import { RuleTester } from 'eslint';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
@@ -54,11 +54,11 @@ ruleTester.run('named', rule, {
     // es7
     test({
       code: 'export bar, { foo } from "./bar"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import { foo, bar } from "./named-trampoline"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // regression tests
@@ -73,43 +73,43 @@ ruleTester.run('named', rule, {
     // should ignore imported/exported flow types, even if they don’t exist
     test({
       code: 'import type { MissingType } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import typeof { MissingType } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import type { MyOpaqueType } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import typeof { MyOpaqueType } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import { type MyOpaqueType, MyClass } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import { typeof MyOpaqueType, MyClass } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import typeof MissingType from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import typeof * as MissingType from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'export type { MissingType } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'export type { MyOpaqueType } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // jsnext
@@ -244,17 +244,17 @@ ruleTester.run('named', rule, {
     // es7
     test({
       code: 'export bar2, { bar } from "./bar"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ["bar not found in './bar'"],
     }),
     test({
       code: 'import { foo, bar, baz } from "./named-trampoline"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ["baz not found in './named-trampoline'"],
     }),
     test({
       code: 'import { baz } from "./broken-trampoline"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ['baz not found via broken-trampoline.js -> named-exports.js'],
     }),
 
@@ -294,7 +294,7 @@ ruleTester.run('named', rule, {
 
     test({
       code: 'import  { type MyOpaqueType, MyMissingClass } from "./flowtypes"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ["MyMissingClass not found in './flowtypes'"],
     }),
 
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 15ab133b1f..1465d21363 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -1,4 +1,4 @@
-import { test, SYNTAX_CASES, getTSParsers, testVersion, testFilePath } from '../utils';
+import { test, SYNTAX_CASES, getTSParsers, testVersion, testFilePath, parsers } from '../utils';
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
 
@@ -57,16 +57,16 @@ const valid = [
   // es7 //
   /////////
   test({ code: 'export * as names from "./named-exports"',
-    parser: require.resolve('babel-eslint') }),
+    parser: parsers.BABEL_OLD }),
   test({ code: 'export defport, * as names from "./named-exports"',
-    parser: require.resolve('babel-eslint') }),
+    parser: parsers.BABEL_OLD }),
   // non-existent is handled by no-unresolved
   test({ code: 'export * as names from "./does-not-exist"',
-    parser: require.resolve('babel-eslint') }),
+    parser: parsers.BABEL_OLD }),
 
   test({
     code: 'import * as Endpoints from "./issue-195/Endpoints"; console.log(Endpoints.Users)',
-    parser: require.resolve('babel-eslint'),
+    parser: parsers.BABEL_OLD,
   }),
 
   // respect hoisting
@@ -81,11 +81,11 @@ const valid = [
   test({ code: "import * as names from './default-export'; console.log(names.default)" }),
   test({
     code: 'export * as names from "./default-export"',
-    parser: require.resolve('babel-eslint'),
+    parser: parsers.BABEL_OLD,
   }),
   test({
     code: 'export defport, * as names from "./default-export"',
-    parser: require.resolve('babel-eslint'),
+    parser: parsers.BABEL_OLD,
   }),
 
   // #456: optionally ignore computed references
@@ -103,7 +103,7 @@ const valid = [
   }),
   test({
     code: `import * as names from './named-exports'; const {a, b, ...rest} = names;`,
-    parser: require.resolve('babel-eslint'),
+    parser: parsers.BABEL_OLD,
   }),
 
   // #1144: should handle re-export CommonJS as namespace
@@ -251,7 +251,7 @@ const invalid = [].concat(
 
   test({
     code: 'import * as Endpoints from "./issue-195/Endpoints"; console.log(Endpoints.Foo)',
-    parser: require.resolve('babel-eslint'),
+    parser: parsers.BABEL_OLD,
     errors: ["'Foo' not found in imported namespace 'Endpoints'."],
   }),
 
@@ -316,7 +316,7 @@ const invalid = [].concat(
 ///////////////////////
 // deep dereferences //
 //////////////////////
-;[['deep', require.resolve('espree')], ['deep-es7', require.resolve('babel-eslint')]].forEach(function ([folder, parser]) { // close over params
+;[['deep', require.resolve('espree')], ['deep-es7', parsers.BABEL_OLD]].forEach(function ([folder, parser]) { // close over params
   valid.push(
     test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.c.d.e)` }),
     test({ parser, code: `import { b } from "./${folder}/a"; console.log(b.c.d.e)` }),
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index a00e86900f..9ad18cbff8 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -1,7 +1,7 @@
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
 
-import { getTSParsers, testVersion } from '../utils';
+import { getTSParsers, parsers, testVersion } from '../utils';
 
 const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.';
 const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => {
@@ -161,22 +161,22 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         class App {}
       `,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     },
     {
       code: `var foo = require('foo');\n\n@SomeDecorator(foo)\nclass Foo {}`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     },
     {
       code : `// issue 1004\nimport foo from 'foo';\n\n@SomeDecorator(foo)\nexport default class Test {}`,
       parserOptions: { sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     },
     {
       code : `// issue 1004\nconst foo = require('foo');\n\n@SomeDecorator(foo)\nexport default class Test {}`,
       parserOptions: { sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     },
     ...flatMap(getTSParsers(), (parser) => [
       {
@@ -415,7 +415,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: IMPORT_ERROR_MESSAGE,
       } ],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     },
     {
       code: `var foo = require('foo');\n@SomeDecorator(foo)\nclass Foo {}`,
@@ -426,7 +426,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: REQUIRE_ERROR_MESSAGE,
       } ],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     },
     {
       code: `// issue 10042\nimport foo from 'foo';\n@SomeDecorator(foo)\nexport default class Test {}`,
@@ -437,7 +437,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: IMPORT_ERROR_MESSAGE,
       } ],
       parserOptions: { sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     },
     {
       code: `// issue 1004\nconst foo = require('foo');\n@SomeDecorator(foo)\nexport default class Test {}`,
@@ -448,7 +448,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: REQUIRE_ERROR_MESSAGE,
       } ],
       parserOptions: { sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     },
     testVersion('>= 6', () => ({
       code: `
@@ -472,7 +472,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         },
       ],
       parserOptions: { sourceType: 'module' },
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     })) || [],
   ),
 });
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index c4e3235e78..22e097dd2c 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -1,4 +1,4 @@
-import { test as _test, testFilePath } from '../utils';
+import { parsers, test as _test, testFilePath } from '../utils';
 
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
@@ -63,36 +63,36 @@ ruleTester.run('no-cycle', rule, {
       test({
         code: `import("./${testDialect}/depth-two").then(function({ foo }) {})`,
         options: [{ maxDepth: 1 }],
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
       test({
         code: `import type { FooType } from "./${testDialect}/depth-one"`,
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
       test({
         code: `import type { FooType, BarType } from "./${testDialect}/depth-one"`,
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
     ]),
 
     test({
       code: 'import { bar } from "./flow-types"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import { bar } from "./flow-types-only-importing-type"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import { bar } from "./flow-types-only-importing-multiple-types"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
   ),
 
   invalid: [].concat(
     test({
       code: 'import { bar } from "./flow-types-some-type-imports"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [error(`Dependency cycle detected.`)],
     }),
     test({
@@ -166,17 +166,17 @@ ruleTester.run('no-cycle', rule, {
       test({
         code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
       test({
         code: `import("./${testDialect}/depth-three-star")`,
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
       test({
         code: `import("./${testDialect}/depth-three-indirect")`,
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
       test({
         code: `import { foo } from "./${testDialect}/depth-two"`,
@@ -192,7 +192,7 @@ ruleTester.run('no-cycle', rule, {
 
     test({
       code: 'import { bar } from "./flow-types-depth-one"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [error(`Dependency cycle via ./flow-types-depth-two:4=>./es6/depth-one:1`)],
     }),
   ),
diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index 1d149421f9..6c1a85a1d5 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -1,4 +1,4 @@
-import { test, testVersion } from '../utils';
+import { parsers, test, testVersion } from '../utils';
 
 import { RuleTester } from 'eslint';
 
@@ -58,7 +58,7 @@ ruleTester.run('no-default-export', rule, {
     }),
     test({
       code: 'export { a, b } from "foo.js"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // no exports at all
@@ -74,15 +74,15 @@ ruleTester.run('no-default-export', rule, {
 
     test({
       code: `export type UserId = number;`,
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'export foo from "foo.js"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: `export Memory, { MemoryValue } from './Memory'`,
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
   ],
   invalid: [].concat(
@@ -154,7 +154,7 @@ ruleTester.run('no-default-export', rule, {
     }),
     test({
       code: 'export default from "foo.js"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [
         {
           type: 'ExportNamedDeclaration',
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index ad39543f81..b481e6c823 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -1,5 +1,5 @@
 import * as path from 'path';
-import { test as testUtil, getNonDefaultParsers } from '../utils';
+import { test as testUtil, getNonDefaultParsers, parsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
@@ -26,7 +26,7 @@ ruleTester.run('no-duplicates', rule, {
     // #225: ignore duplicate if is a flow type import
     test({
       code: "import { x } from './foo'; import type { y } from './foo'",
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // #1107: Using different query strings that trigger different webpack loaders.
@@ -107,7 +107,7 @@ ruleTester.run('no-duplicates', rule, {
     test({
       code: "import type { x } from './foo'; import type { y } from './foo'",
       output: "import type { x , y } from './foo'; ",
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
 
@@ -418,7 +418,7 @@ import {x,y} from './foo'
 context('TypeScript', function () {
   getNonDefaultParsers()
     // Type-only imports were added in TypeScript ESTree 2.23.0
-    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .filter((parser) => parser !== parsers.TS_OLD)
     .forEach((parser) => {
       const parserConfig = {
         parser,
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index 4a70e7bc2b..368ec11935 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -1,4 +1,4 @@
-import { test } from '../utils';
+import { parsers, test } from '../utils';
 
 import { RuleTester } from 'eslint';
 
@@ -30,54 +30,54 @@ ruleTester.run('no-dynamic-require', rule, {
     //dynamic import
     test({
       code: 'import("foo")',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'import(`foo`)',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'import("./foo")',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'import("@scope/foo")',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'var foo = import("foo")',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'var foo = import(`foo`)',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'var foo = import("./foo")',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'var foo = import("@scope/foo")',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'import("../" + name)',
       errors: [dynamicImportError],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: false }],
     }),
     test({
       code: 'import(`../${name}`)',
       errors: [dynamicImportError],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
   ],
   invalid: [
@@ -107,25 +107,25 @@ ruleTester.run('no-dynamic-require', rule, {
     test({
       code: 'import("../" + name)',
       errors: [dynamicImportError],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'import(`../${name}`)',
       errors: [dynamicImportError],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'import(name)',
       errors: [dynamicImportError],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
       code: 'import(name())',
       errors: [dynamicImportError],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       options: [{ esmodule: true }],
     }),
     test({
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index d4c9f6d7f5..d4e3886bed 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -1,4 +1,4 @@
-import { getTSParsers, test, testFilePath } from '../utils';
+import { getTSParsers, parsers, test, testFilePath } from '../utils';
 import typescriptConfig from '../../../config/typescript';
 import path from 'path';
 import fs from 'fs';
@@ -82,7 +82,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'import type MyType from "myflowtyped";',
       options: [{ packageDir: packageDirWithFlowTyped }],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: `
@@ -90,7 +90,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
         import typeof TypeScriptModule from 'typescript';
       `,
       options: [{ packageDir: packageDirWithFlowTyped }],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import react from "react";',
@@ -398,7 +398,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
 describe('TypeScript', () => {
   getTSParsers()
     // Type-only imports were added in TypeScript ESTree 2.23.0
-    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .filter((parser) => parser !== parsers.TS_OLD)
     .forEach((parser) => {
       const parserConfig = {
         parser,
@@ -433,12 +433,12 @@ typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', r
     test({
       code: 'import type MyType from "not-a-dependency";',
       filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import type { MyType } from "not-a-dependency";',
       filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
   ],
   invalid: [
diff --git a/tests/src/rules/no-mutable-exports.js b/tests/src/rules/no-mutable-exports.js
index e96b841b5c..1171443c4a 100644
--- a/tests/src/rules/no-mutable-exports.js
+++ b/tests/src/rules/no-mutable-exports.js
@@ -1,4 +1,4 @@
-import { test, testVersion } from '../utils';
+import { parsers, test, testVersion } from '../utils';
 import { RuleTester } from 'eslint';
 import rule from 'rules/no-mutable-exports';
 
@@ -25,11 +25,11 @@ ruleTester.run('no-mutable-exports', rule, {
     test({ code: 'class Counter {}\nexport default Counter' }),
     test({ code: 'class Counter {}\nexport { Counter as default }' }),
     test({
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       code: 'export Something from "./something";',
     }),
     test({
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       code: 'type Foo = {}\nexport type {Foo}',
     }),
     // es2022: Arbitrary module namespace identifier names
diff --git a/tests/src/rules/no-named-as-default.js b/tests/src/rules/no-named-as-default.js
index 129419350e..04ec28e615 100644
--- a/tests/src/rules/no-named-as-default.js
+++ b/tests/src/rules/no-named-as-default.js
@@ -1,4 +1,4 @@
-import { test, testVersion, SYNTAX_CASES } from '../utils';
+import { test, testVersion, SYNTAX_CASES, parsers } from '../utils';
 import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester();
@@ -13,13 +13,13 @@ ruleTester.run('no-named-as-default', rule, {
 
     // es7
     test({ code: 'export bar, { foo } from "./bar";',
-      parser: require.resolve('babel-eslint') }),
+      parser: parsers.BABEL_OLD }),
     test({ code: 'export bar from "./bar";',
-      parser: require.resolve('babel-eslint') }),
+      parser: parsers.BABEL_OLD }),
 
     // #566: don't false-positive on `default` itself
     test({ code: 'export default from "./bar";',
-      parser: require.resolve('babel-eslint') }),
+      parser: parsers.BABEL_OLD }),
 
     // es2022: Arbitrary module namespae identifier names
     testVersion('>= 8.7', () => ({
@@ -45,13 +45,13 @@ ruleTester.run('no-named-as-default', rule, {
     // es7
     test({
       code: 'export foo from "./bar";',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [ {
         message: 'Using exported name \'foo\' as identifier for default export.',
         type: 'ExportDefaultSpecifier' } ] }),
     test({
       code: 'export foo, { foo as bar } from "./bar";',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [ {
         message: 'Using exported name \'foo\' as identifier for default export.',
         type: 'ExportDefaultSpecifier' } ] }),
diff --git a/tests/src/rules/no-named-default.js b/tests/src/rules/no-named-default.js
index 1ed1502871..191c9c6ce9 100644
--- a/tests/src/rules/no-named-default.js
+++ b/tests/src/rules/no-named-default.js
@@ -1,4 +1,4 @@
-import { test, testVersion, SYNTAX_CASES } from '../utils';
+import { test, testVersion, SYNTAX_CASES, parsers } from '../utils';
 import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester();
@@ -12,11 +12,11 @@ ruleTester.run('no-named-default', rule, {
     // Should ignore imported flow types
     test({
       code: 'import { type default as Foo } from "./bar";',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'import { typeof default as Foo } from "./bar";',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     ...SYNTAX_CASES,
@@ -29,7 +29,7 @@ ruleTester.run('no-named-default', rule, {
         message: 'Use default import syntax to import \'default\'.',
         type: 'Identifier',
       }],
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),*/
     test({
       code: 'import { default as bar } from "./bar";',
diff --git a/tests/src/rules/no-named-export.js b/tests/src/rules/no-named-export.js
index 4d8978b35f..58b5da2f85 100644
--- a/tests/src/rules/no-named-export.js
+++ b/tests/src/rules/no-named-export.js
@@ -1,5 +1,5 @@
 import { RuleTester } from 'eslint';
-import { test, testVersion } from '../utils';
+import { parsers, test, testVersion } from '../utils';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-named-export');
@@ -14,7 +14,7 @@ ruleTester.run('no-named-export', rule, {
     }),
     test({
       code: 'export default from "foo.js"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // no exports at all
@@ -152,7 +152,7 @@ ruleTester.run('no-named-export', rule, {
     }),
     test({
       code: 'export { a, b } from "foo.js"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [{
         type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
@@ -160,7 +160,7 @@ ruleTester.run('no-named-export', rule, {
     }),
     test({
       code: `export type UserId = number;`,
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [{
         type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
@@ -168,7 +168,7 @@ ruleTester.run('no-named-export', rule, {
     }),
     test({
       code: 'export foo from "foo.js"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [{
         type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
@@ -176,7 +176,7 @@ ruleTester.run('no-named-export', rule, {
     }),
     test({
       code: `export Memory, { MemoryValue } from './Memory'`,
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       errors: [{
         type: 'ExportNamedDeclaration',
         message: 'Named exports are not allowed.',
diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js
index d6a47ae373..3050498026 100644
--- a/tests/src/rules/no-relative-parent-imports.js
+++ b/tests/src/rules/no-relative-parent-imports.js
@@ -1,10 +1,10 @@
 import { RuleTester } from 'eslint';
 import rule from 'rules/no-relative-parent-imports';
-import { test as _test, testFilePath } from '../utils';
+import { parsers, test as _test, testFilePath } from '../utils';
 
 const test = def => _test(Object.assign(def, {
   filename: testFilePath('./internal-modules/plugins/plugin2/index.js'),
-  parser: require.resolve('babel-eslint'),
+  parser: parsers.BABEL_OLD,
 }));
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 71efc128e3..c0252ad19d 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -1,6 +1,6 @@
-import * as path from 'path';
+import path from 'path';
 
-import { getTSParsers, test, SYNTAX_CASES, testVersion } from '../utils';
+import { getTSParsers, test, SYNTAX_CASES, testVersion, parsers } from '../utils';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
@@ -30,7 +30,7 @@ function runResolverTests(resolver) {
       rest({ code: "import {someThing} from './test-module';" }),
       rest({ code: "import fs from 'fs';" }),
       rest({ code: "import('fs');",
-        parser: require.resolve('babel-eslint') }),
+        parser: parsers.BABEL_OLD }),
 
       // check with eslint parser
       testVersion('>= 7', () => rest({
@@ -46,9 +46,9 @@ function runResolverTests(resolver) {
 
       // stage 1 proposal for export symmetry,
       rest({ code: 'export * as bar from "./bar"',
-        parser: require.resolve('babel-eslint') }),
+        parser: parsers.BABEL_OLD }),
       rest({ code: 'export bar from "./bar"',
-        parser: require.resolve('babel-eslint') }),
+        parser: parsers.BABEL_OLD }),
       rest({ code: 'import foo from "./jsx/MyUnCoolComponent.jsx"' }),
 
       // commonjs setting
@@ -127,7 +127,7 @@ function runResolverTests(resolver) {
           message: 'Unable to resolve path to module \'in-alternate-root\'.',
           type: 'Literal',
         }],
-        parser: require.resolve('babel-eslint') }),
+        parser: parsers.BABEL_OLD }),
 
       rest({ code: 'export { foo } from "./does-not-exist"',
         errors: ["Unable to resolve path to module './does-not-exist'."] }),
@@ -148,11 +148,11 @@ function runResolverTests(resolver) {
 
       // export symmetry proposal
       rest({ code: 'export * as bar from "./does-not-exist"',
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         errors: ["Unable to resolve path to module './does-not-exist'."],
       }),
       rest({ code: 'export bar from "./does-not-exist"',
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         errors: ["Unable to resolve path to module './does-not-exist'."],
       }),
 
@@ -444,7 +444,7 @@ ruleTester.run('import() with built-in parser', rule, {
 
 context('TypeScript', () => {
   // Type-only imports were added in TypeScript ESTree 2.23.0
-  getTSParsers().filter(x => x !== require.resolve('typescript-eslint-parser')).forEach((parser) => {
+  getTSParsers().filter(x => x !== parsers.TS_OLD).forEach((parser) => {
     ruleTester.run(`${parser}: no-unresolved ignore type-only`, rule, {
       valid: [
         test({
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 8610ff4aa0..aa0e123c2b 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -1,4 +1,4 @@
-import { test, testVersion, testFilePath, getTSParsers } from '../utils';
+import { test, testVersion, testFilePath, getTSParsers, parsers } from '../utils';
 import jsxConfig from '../../../config/react';
 import typescriptConfig from '../../../config/typescript';
 
@@ -112,49 +112,49 @@ ruleTester.run('no-unused-modules', rule, {
       options: unusedExportsOptions,
       code: 'import { o2 } from "./file-o";export default () => 12',
       filename: testFilePath('./no-unused-modules/file-a.js'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       options: unusedExportsOptions,
       code: 'export const b = 2',
       filename: testFilePath('./no-unused-modules/file-b.js'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       options: unusedExportsOptions,
       code: 'const c1 = 3; function c2() { return 3 }; export { c1, c2 }',
       filename: testFilePath('./no-unused-modules/file-c.js'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       options: unusedExportsOptions,
       code: 'export function d() { return 4 }',
       filename: testFilePath('./no-unused-modules/file-d.js'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       options: unusedExportsOptions,
       code: 'export class q { q0() {} }',
       filename: testFilePath('./no-unused-modules/file-q.js'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       options: unusedExportsOptions,
       code: 'const e0 = 5; export { e0 as e }',
       filename: testFilePath('./no-unused-modules/file-e.js'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       options: unusedExportsOptions,
       code: 'const l0 = 5; const l = 10; export { l0 as l1, l }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-l.js'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       options: unusedExportsOptions,
       code: 'const o0 = 0; const o1 = 1; export { o0, o1 as o2 }; export default () => {}',
       filename: testFilePath('./no-unused-modules/file-o.js'),
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
   ],
   invalid: [
@@ -263,7 +263,7 @@ describe('dynamic imports', () => {
             const d = 40
             export default d
             `,
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/exports-for-dynamic-js.js'),
       }),
     ],
@@ -277,7 +277,7 @@ describe('dynamic imports', () => {
         const d = 40
         export default d
         `,
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/exports-for-dynamic-js-2.js'),
         errors: [
           error(`exported declaration 'a' not used within other modules`),
@@ -298,7 +298,7 @@ describe('dynamic imports', () => {
             const ts_d = 40
             export default ts_d
             `,
-        parser: require.resolve('@typescript-eslint/parser'),
+        parser: parsers.TS_NEW,
         filename: testFilePath('./no-unused-modules/typescript/exports-for-dynamic-ts.ts'),
       }),
     ],
@@ -1177,7 +1177,7 @@ describe('correctly work with JSX only files', () => {
       test({
         options: unusedExportsJsxOptions,
         code: 'import a from "file-jsx-a";',
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/jsx/file-jsx-a.jsx'),
       }),
     ],
@@ -1185,7 +1185,7 @@ describe('correctly work with JSX only files', () => {
       test({
         options: unusedExportsJsxOptions,
         code: `export const b = 2;`,
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/jsx/file-jsx-b.jsx'),
         errors: [
           error(`exported declaration 'b' not used within other modules`),
@@ -1201,7 +1201,7 @@ describe('ignore flow types', () => {
       test({
         options: unusedExportsOptions,
         code: 'import { type FooType, type FooInterface } from "./flow-2";',
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/flow/flow-0.js'),
       }),
       test({
@@ -1210,13 +1210,13 @@ describe('ignore flow types', () => {
                export type FooType = string;
                export interface FooInterface {};
                `,
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/flow/flow-2.js'),
       }),
       test({
         options: unusedExportsOptions,
         code: 'import type { FooType, FooInterface } from "./flow-4";',
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/flow/flow-3.js'),
       }),
       test({
@@ -1225,7 +1225,7 @@ describe('ignore flow types', () => {
                export type FooType = string;
                export interface FooInterface {};
                `,
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/flow/flow-4.js'),
       }),
       test({
@@ -1234,7 +1234,7 @@ describe('ignore flow types', () => {
                export type Bar = number;
                export interface BarInterface {};
                `,
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/flow/flow-1.js'),
       }),
     ],
@@ -1248,13 +1248,13 @@ describe('support (nested) destructuring assignment', () => {
       test({
         options: unusedExportsOptions,
         code: 'import {a, b} from "./destructuring-b";',
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/destructuring-a.js'),
       }),
       test({
         options: unusedExportsOptions,
         code: 'const obj = {a: 1, dummy: {b: 2}}; export const {a, dummy: {b}} = obj;',
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/destructuring-b.js'),
       }),
     ],
diff --git a/tests/src/rules/no-useless-path-segments.js b/tests/src/rules/no-useless-path-segments.js
index 21d9a5f704..f960953503 100644
--- a/tests/src/rules/no-useless-path-segments.js
+++ b/tests/src/rules/no-useless-path-segments.js
@@ -1,4 +1,4 @@
-import { test } from '../utils';
+import { parsers, test } from '../utils';
 import { RuleTester } from 'eslint';
 
 const ruleTester = new RuleTester();
@@ -29,11 +29,11 @@ function runResolverTests(resolver) {
       test({ code: 'import "./importType"', options: [{ noUselessIndex: true }] }), // ./importType.js does not exist
 
       test({ code: 'import(".")',
-        parser: require.resolve('babel-eslint') }),
+        parser: parsers.BABEL_OLD }),
       test({ code: 'import("..")',
-        parser: require.resolve('babel-eslint') }),
+        parser: parsers.BABEL_OLD }),
       test({ code: 'import("fs").then(function(fs) {})',
-        parser: require.resolve('babel-eslint') }),
+        parser: parsers.BABEL_OLD }),
     ],
 
     invalid: [
@@ -232,19 +232,19 @@ function runResolverTests(resolver) {
         code: 'import("./")',
         output: 'import(".")',
         errors: [ 'Useless path segments for "./", should be "."'],
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
       test({
         code: 'import("../")',
         output: 'import("..")',
         errors: [ 'Useless path segments for "../", should be ".."'],
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
       test({
         code: 'import("./deep//a")',
         output: 'import("./deep/a")',
         errors: [ 'Useless path segments for "./deep//a", should be "./deep/a"'],
-        parser: require.resolve('babel-eslint'),
+        parser: parsers.BABEL_OLD,
       }),
     ],
   });
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 79426c4c43..e552c9a853 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,4 +1,4 @@
-import { test, getTSParsers, getNonDefaultParsers, testFilePath } from '../utils';
+import { test, getTSParsers, getNonDefaultParsers, testFilePath, parsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
@@ -2321,7 +2321,7 @@ ruleTester.run('order', rule, {
 context('TypeScript', function () {
   getNonDefaultParsers()
     // Type-only imports were added in TypeScript ESTree 2.23.0
-    .filter((parser) => parser !== require.resolve('typescript-eslint-parser'))
+    .filter((parser) => parser !== parsers.TS_OLD)
     .forEach((parser) => {
       const parserConfig = {
         parser,
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index d00a99668b..23b6e244ea 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -1,4 +1,4 @@
-import { test, testVersion, getNonDefaultParsers } from '../utils';
+import { test, testVersion, getNonDefaultParsers, parsers } from '../utils';
 
 import { RuleTester } from 'eslint';
 
@@ -64,7 +64,7 @@ ruleTester.run('prefer-default-export', rule, {
     }),
     test({
       code: `export Memory, { MemoryValue } from './Memory'`,
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // no exports at all
@@ -75,24 +75,24 @@ ruleTester.run('prefer-default-export', rule, {
 
     test({
       code: `export type UserId = number;`,
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
 
     // issue #653
     test({
       code: 'export default from "foo.js"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     test({
       code: 'export { a, b } from "foo.js"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     // ...SYNTAX_CASES,
     test({
       code: `
         export const [CounterProvider,, withCounter] = func();;
       `,
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
     }),
     // es2022: Arbitrary module namespae identifier names
     testVersion('>= 8.7', () => ({
diff --git a/tests/src/rules/unambiguous.js b/tests/src/rules/unambiguous.js
index 72e6b10828..8cef69625f 100644
--- a/tests/src/rules/unambiguous.js
+++ b/tests/src/rules/unambiguous.js
@@ -1,4 +1,5 @@
 import { RuleTester } from 'eslint';
+import { parsers } from '../utils';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/unambiguous');
@@ -38,7 +39,7 @@ ruleTester.run('unambiguous', rule, {
     },
     {
       code: 'function x() {}; export * as y from "z"',
-      parser: require.resolve('babel-eslint'),
+      parser: parsers.BABEL_OLD,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
diff --git a/tests/src/utils.js b/tests/src/utils.js
index 012c3a7c7b..49ba6b4702 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -5,24 +5,25 @@ import semver from 'semver';
 // warms up the module cache. this import takes a while (>500ms)
 import 'babel-eslint';
 
+export const parsers = {
+  TS_OLD: semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0') && require.resolve('typescript-eslint-parser'),
+  TS_NEW: semver.satisfies(eslintPkg.version, '>5.0.0') && require.resolve('@typescript-eslint/parser'),
+  BABEL_OLD: require.resolve('babel-eslint'),
+};
+
 export function testFilePath(relativePath) {
   return path.join(process.cwd(), './tests/files', relativePath);
 }
 
 export function getTSParsers() {
-  const parsers = [];
-  if (semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0')) {
-    parsers.push(require.resolve('typescript-eslint-parser'));
-  }
-
-  if (semver.satisfies(eslintPkg.version, '>5.0.0')) {
-    parsers.push(require.resolve('@typescript-eslint/parser'));
-  }
-  return parsers;
+  return [
+    parsers.TS_OLD,
+    parsers.TS_NEW,
+  ].filter(Boolean);
 }
 
 export function getNonDefaultParsers() {
-  return getTSParsers().concat(require.resolve('babel-eslint'));
+  return getTSParsers().concat(parsers.BABEL_OLD).filter(Boolean);
 }
 
 export const FILENAME = testFilePath('foo.js');
@@ -65,7 +66,7 @@ export const SYNTAX_CASES = [
   test({ code: 'for (let [ foo, bar ] of baz) {}' }),
 
   test({ code: 'const { x, y } = bar' }),
-  test({ code: 'const { x, y, ...z } = bar', parser: require.resolve('babel-eslint') }),
+  test({ code: 'const { x, y, ...z } = bar', parser: parsers.BABEL_OLD }),
 
   // all the exports
   test({ code: 'let x; export { x }' }),
@@ -73,7 +74,7 @@ export const SYNTAX_CASES = [
 
   // not sure about these since they reference a file
   // test({ code: 'export { x } from "./y.js"'}),
-  // test({ code: 'export * as y from "./y.js"', parser: require.resolve('babel-eslint')}),
+  // test({ code: 'export * as y from "./y.js"', parser: parsers.BABEL_OLD}),
 
   test({ code: 'export const x = null' }),
   test({ code: 'export var x = null' }),

From 624aa61e69c458d9f932e41ce4ffd189daf81033 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Sat, 22 Jan 2022 20:00:49 +0900
Subject: [PATCH 448/767] [Tests] test on `@typescript-eslint/parser@5`

---
 .github/workflows/node-4+.yml               |  5 ++++
 package.json                                |  2 +-
 tests/dep-time-travel.sh                    |  2 ++
 tests/src/rules/no-webpack-loader-syntax.js | 29 ++++++++++++---------
 4 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 3af06b3bc3..6762bf0bbd 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -34,6 +34,11 @@ jobs:
           - 3
           - 2
         include:
+          - node-version: 'lts/*'
+            eslint: 7
+            ts-parser: 4
+            env:
+              TS_PARSER: 4
           - node-version: 'lts/*'
             eslint: 7
             ts-parser: 3
diff --git a/package.json b/package.json
index 1f958ec745..1e003ec6b8 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,7 @@
     "@angular-eslint/template-parser": "^13.0.1",
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
-    "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3",
+    "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3 || ^5.10.0",
     "array.prototype.flatmap": "^1.2.5",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index 82681b38f3..6ee500fe2c 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -21,6 +21,8 @@ elif [[ "$ESLINT_VERSION" -lt "5" ]]; then # completely remove the new TypeScrip
   npm uninstall --no-save @typescript-eslint/parser
 elif [[ "$TRAVIS_NODE_VERSION" -lt "10" ]]; then # TS parser 3 requires node 10+
   npm i --no-save "@typescript-eslint/parser@3"
+elif [[ "$TRAVIS_NODE_VERSION" -lt "12" ]]; then # TS parser 4 requires node 12+
+  npm i --no-save "@typescript-eslint/parser@4"
 fi
 
 # use these alternate TypeScript dependencies for ESLint < v4
diff --git a/tests/src/rules/no-webpack-loader-syntax.js b/tests/src/rules/no-webpack-loader-syntax.js
index a8aa0dd2b0..2b841e18a3 100644
--- a/tests/src/rules/no-webpack-loader-syntax.js
+++ b/tests/src/rules/no-webpack-loader-syntax.js
@@ -1,6 +1,7 @@
-import { test, getTSParsers } from '../utils';
+import { test, getTSParsers, parsers } from '../utils';
 
 import { RuleTester } from 'eslint';
+import semver from 'semver';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-webpack-loader-syntax');
@@ -82,16 +83,20 @@ context('TypeScript', function () {
         'import/resolver': { 'eslint-import-resolver-typescript': true },
       },
     };
-    ruleTester.run('no-webpack-loader-syntax', rule, {
-      valid: [
-        test(Object.assign({
-          code: 'import { foo } from\nalert()',
-        }, parserConfig)),
-        test(Object.assign({
-          code: 'import foo from\nalert()',
-        }, parserConfig)),
-      ],
-      invalid: [],
-    });
+    // @typescript-eslint/parser@5+ throw error for invalid module specifiers at parsing time.
+    // https://github.com/typescript-eslint/typescript-eslint/releases/tag/v5.0.0
+    if (!(parser === parsers.TS_NEW && semver.satisfies(require('@typescript-eslint/parser/package.json').version, '>= 5'))) {
+      ruleTester.run('no-webpack-loader-syntax', rule, {
+        valid: [
+          test(Object.assign({
+            code: 'import { foo } from\nalert()',
+          }, parserConfig)),
+          test(Object.assign({
+            code: 'import foo from\nalert()',
+          }, parserConfig)),
+        ],
+        invalid: [],
+      });
+    }
   });
 });

From 0ded887a6ac57913724799b403e021b0eef76f70 Mon Sep 17 00:00:00 2001
From: Stephan Troyer <stephantroyer@live.at>
Date: Sat, 18 Dec 2021 21:45:11 +0100
Subject: [PATCH 449/767] [Docs] `no-unresolved`: Fix RegExp escaping in readme

In the `ignore` example the backslash in `'\.img$'` was escaping the "." as a string character, not in the RegExp sense.
---
 CHANGELOG.md                | 3 +++
 docs/rules/no-unresolved.md | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63de41cd73..2d1b0b4ac9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
 - [Tests] `default`, `no-anonymous-default-export`, `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [Docs] [`no-unresolved`]: Fix RegExp escaping in readme ([#2332], thanks [@stephtr])
 
 ## [2.25.4] - 2022-01-02
 
@@ -963,6 +964,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
+[#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
 [#2358]: https://github.com/import-js/eslint-plugin-import/pull/2358
 [#2341]: https://github.com/import-js/eslint-plugin-import/pull/2341
 [#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
@@ -1631,6 +1633,7 @@ for info on changes for earlier releases.
 [@spalger]: https://github.com/spalger
 [@st-sloth]: https://github.com/st-sloth
 [@stekycz]: https://github.com/stekycz
+[@stephtr]: https://github.com/stephtr
 [@straub]: https://github.com/straub
 [@strawbrary]: https://github.com/strawbrary
 [@stropho]: https://github.com/stropho
diff --git a/docs/rules/no-unresolved.md b/docs/rules/no-unresolved.md
index 89d00b9301..1d18a3693a 100644
--- a/docs/rules/no-unresolved.md
+++ b/docs/rules/no-unresolved.md
@@ -60,7 +60,7 @@ This rule has its own ignore list, separate from [`import/ignore`]. This is beca
 To suppress errors from files that may not be properly resolved by your [resolver settings](../../README.md#resolver-plugins), you may add an `ignore` key with an array of `RegExp` pattern strings:
 
 ```js
-/*eslint import/no-unresolved: [2, { ignore: ['\.img$'] }]*/
+/*eslint import/no-unresolved: [2, { ignore: ['\\.img$'] }]*/
 
 import { x } from './mod' // may be reported, if not resolved to a module
 

From a929394cb76c4550faf33d1eeca29e2d9f127962 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Wed, 26 Jan 2022 09:04:03 +0900
Subject: [PATCH 450/767] [Tests] export resolved `espree` path

---
 tests/src/utils.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/src/utils.js b/tests/src/utils.js
index 49ba6b4702..b66ecf9c66 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -6,6 +6,7 @@ import semver from 'semver';
 import 'babel-eslint';
 
 export const parsers = {
+  ESPREE: require.resolve('espree'),
   TS_OLD: semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0') && require.resolve('typescript-eslint-parser'),
   TS_NEW: semver.satisfies(eslintPkg.version, '>5.0.0') && require.resolve('@typescript-eslint/parser'),
   BABEL_OLD: require.resolve('babel-eslint'),

From 3d02b662dd3dcdf1196aa69a26464c753ef9dfd0 Mon Sep 17 00:00:00 2001
From: sosukesuzuki <aosukeke@gmail.com>
Date: Tue, 25 Jan 2022 22:21:00 +0900
Subject: [PATCH 451/767] [New] `no-dynamic-require`: support dynamic import
 with espree

---
 CHANGELOG.md                          |   2 +
 src/rules/no-dynamic-require.js       |  13 +-
 tests/src/rules/no-dynamic-require.js | 206 +++++++++++++++++---------
 3 files changed, 146 insertions(+), 75 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d1b0b4ac9..52777b296a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Added
 - [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
@@ -963,6 +964,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
 [#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
 [#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
 [#2358]: https://github.com/import-js/eslint-plugin-import/pull/2358
diff --git a/src/rules/no-dynamic-require.js b/src/rules/no-dynamic-require.js
index 8267fd26e9..27e9a957a7 100644
--- a/src/rules/no-dynamic-require.js
+++ b/src/rules/no-dynamic-require.js
@@ -19,6 +19,8 @@ function isStaticValue(arg) {
     (arg.type === 'TemplateLiteral' && arg.expressions.length === 0);
 }
 
+const dynamicImportErrorMessage = 'Calls to import() should use string literals';
+
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -55,10 +57,19 @@ module.exports = {
         if (options.esmodule && isDynamicImport(node)) {
           return context.report({
             node,
-            message: 'Calls to import() should use string literals',
+            message: dynamicImportErrorMessage,
           });
         }
       },
+      ImportExpression(node) {
+        if (!options.esmodule || isStaticValue(node.source)) {
+          return;
+        }
+        return context.report({
+          node,
+          message: dynamicImportErrorMessage,
+        });
+      },
     };
   },
 };
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index 368ec11935..0b141ccd76 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -1,6 +1,7 @@
-import { parsers, test } from '../utils';
+import { parsers, test, testVersion } from '../utils';
 
 import { RuleTester } from 'eslint';
+import flatMap from 'array.prototype.flatmap';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-dynamic-require');
@@ -28,56 +29,93 @@ ruleTester.run('no-dynamic-require', rule, {
     test({ code: 'var foo = require("@scope/foo")' }),
 
     //dynamic import
-    test({
-      code: 'import("foo")',
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'import(`foo`)',
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'import("./foo")',
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'import("@scope/foo")',
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'var foo = import("foo")',
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'var foo = import(`foo`)',
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'var foo = import("./foo")',
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'var foo = import("@scope/foo")',
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'import("../" + name)',
-      errors: [dynamicImportError],
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: false }],
-    }),
-    test({
-      code: 'import(`../${name}`)',
-      errors: [dynamicImportError],
-      parser: parsers.BABEL_OLD,
+    ...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => {
+      const _test =
+        parser === parsers.ESPREE
+          ? (testObj) => testVersion('>= 6.2.0', () => testObj)
+          : (testObj) => test(testObj);
+      return [].concat(
+        _test({
+          code: 'import("foo")',
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'import(`foo`)',
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'import("./foo")',
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'import("@scope/foo")',
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'var foo = import("foo")',
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'var foo = import(`foo`)',
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'var foo = import("./foo")',
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'var foo = import("@scope/foo")',
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'import("../" + name)',
+          errors: [dynamicImportError],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'import(`../${name}`)',
+          errors: [dynamicImportError],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+      );
     }),
   ],
   invalid: [
@@ -104,29 +142,49 @@ ruleTester.run('no-dynamic-require', rule, {
     }),
 
     // dynamic import
-    test({
-      code: 'import("../" + name)',
-      errors: [dynamicImportError],
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'import(`../${name}`)',
-      errors: [dynamicImportError],
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'import(name)',
-      errors: [dynamicImportError],
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
-    }),
-    test({
-      code: 'import(name())',
-      errors: [dynamicImportError],
-      parser: parsers.BABEL_OLD,
-      options: [{ esmodule: true }],
+    ...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => {
+      const _test =
+        parser === parsers.ESPREE
+          ? (testObj) => testVersion('>= 6.2.0', () => testObj)
+          : (testObj) => test(testObj);
+      return [].concat(
+        _test({
+          code: 'import("../" + name)',
+          errors: [dynamicImportError],
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'import(`../${name}`)',
+          errors: [dynamicImportError],
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'import(name)',
+          errors: [dynamicImportError],
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+        _test({
+          code: 'import(name())',
+          errors: [dynamicImportError],
+          options: [{ esmodule: true }],
+          parser,
+          parserOptions: {
+            ecmaVersion: 2020,
+          },
+        }),
+      );
     }),
     test({
       code: 'require(`foo${x}`)',

From fc98de271bcd512b6e2ce3211165e6c40b22cdde Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jan 2022 10:31:03 -0800
Subject: [PATCH 452/767] utils: v2.7.3

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 7e36bb9fd6..193fc141e0 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.7.3 - 2022-01-26
+
 ### Fixed
 - [Fix] `parse`: restore compatibility by making the return value `ast` again ([#2350], thanks [@ljharb])
 
diff --git a/utils/package.json b/utils/package.json
index 97f95162f1..2e348d07f2 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.7.2",
+  "version": "2.7.3",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From ad18a620d54fea111c8d385029a3c95770c22ddd Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 28 Jan 2022 14:36:58 -0800
Subject: [PATCH 453/767] [Fix] `default`: `typescript-eslint-parser`: avoid a
 crash on exporting as namespace

 - test on more versions of `typescript-eslint-parser`
---
 CHANGELOG.md                             |  4 ++++
 package.json                             |  2 +-
 src/ExportMap.js                         |  2 +-
 tests/dep-time-travel.sh                 |  3 +++
 tests/src/rules/default.js               | 10 ++++++----
 tests/src/rules/export.js                | 17 +++++++++--------
 tests/src/rules/newline-after-import.js  | 18 ++++++++++--------
 tests/src/rules/prefer-default-export.js | 18 ++++++++----------
 8 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 52777b296a..9d339757ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,10 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
 
+
+### Fixed
+- [`default`]: `typescript-eslint-parser`: avoid a crash on exporting as namespace (thanks [@ljharb])
+
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
 - [Tests] `default`, `no-anonymous-default-export`, `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
diff --git a/package.json b/package.json
index 1e003ec6b8..2ebaf62402 100644
--- a/package.json
+++ b/package.json
@@ -93,7 +93,7 @@
     "semver": "^6.3.0",
     "sinon": "^2.4.1",
     "typescript": "^2.8.1 || ~3.9.5",
-    "typescript-eslint-parser": "^15 || ^22.0.0"
+    "typescript-eslint-parser": "^15 || ^20 || ^22"
   },
   "peerDependencies": {
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 7425dce44a..d75c7ecd47 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -645,7 +645,7 @@ ExportMap.parse = function (path, content, context) {
     // This doesn't declare anything, but changes what's being exported.
     if (includes(exports, n.type)) {
       const exportedName = n.type === 'TSNamespaceExportDeclaration'
-        ? n.id.name
+        ? (n.id || n.name).name
         : (n.expression && n.expression.name || (n.expression.id && n.expression.id.name) || null);
       const declTypes = [
         'VariableDeclaration',
diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh
index 6ee500fe2c..665ca1ccf1 100755
--- a/tests/dep-time-travel.sh
+++ b/tests/dep-time-travel.sh
@@ -32,6 +32,9 @@ if [[ "$ESLINT_VERSION" -lt "4" ]]; then
 
   echo "Downgrading TypeScript dependencies..."
   npm i --no-save typescript-eslint-parser@15 typescript@2.8.1
+elif [[ "$ESLINT_VERSION" -lt "7" ]]; then
+  echo "Downgrading TypeScript dependencies..."
+  npm i --no-save typescript-eslint-parser@20
 fi
 
 # typescript-eslint-parser 1.1.1+ is not compatible with node 6
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index 9eab9a5a35..eb2028c71a 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -1,6 +1,8 @@
 import path from 'path';
 import { test, testVersion, SYNTAX_CASES, getTSParsers, parsers } from '../utils';
 import { RuleTester } from 'eslint';
+import semver from 'semver';
+import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
@@ -165,7 +167,7 @@ if (!CASE_SENSITIVE_FS) {
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     ruleTester.run(`default`, rule, {
-      valid: [
+      valid: [].concat(
         test({
           code: `import foobar from "./typescript-default"`,
           parser,
@@ -190,14 +192,14 @@ context('TypeScript', function () {
             'import/resolver': { 'eslint-import-resolver-typescript': true },
           },
         }),
-        test({
+        semver.satisfies(tsEslintVersion, '>= 22') ? test({
           code: `import foobar from "./typescript-export-assign-mixed"`,
           parser,
           settings: {
             'import/parsers': { [parser]: ['.ts'] },
             'import/resolver': { 'eslint-import-resolver-typescript': true },
           },
-        }),
+        }) : [],
         test({
           code: `import foobar from "./typescript-export-assign-default-reexport"`,
           parser,
@@ -258,7 +260,7 @@ context('TypeScript', function () {
             'import/resolver': { 'eslint-import-resolver-typescript': true },
           },
         }),
-      ],
+      ),
 
       invalid: [
         test({
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index d075aea6bd..e95efa0329 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -3,6 +3,7 @@ import { test, testFilePath, SYNTAX_CASES, getTSParsers, testVersion } from '../
 import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
+import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/export');
@@ -149,7 +150,7 @@ context('TypeScript', function () {
     };
 
     ruleTester.run('export', rule, {
-      valid: [
+      valid: [].concat(
         // type/value name clash
         test(Object.assign({
           code: `
@@ -164,20 +165,20 @@ context('TypeScript', function () {
           `,
         }, parserConfig)),
 
-        test(Object.assign({
+        semver.satisfies(tsEslintVersion, '>= 22') ? test(Object.assign({
           code: `
             export function fff(a: string);
             export function fff(a: number);
           `,
-        }, parserConfig)),
+        }, parserConfig)) : [],
 
-        test(Object.assign({
+        semver.satisfies(tsEslintVersion, '>= 22') ? test(Object.assign({
           code: `
             export function fff(a: string);
             export function fff(a: number);
             export function fff(a: string|number) {};
           `,
-        }, parserConfig)),
+        }, parserConfig)) : [],
 
         // namespace
         test(Object.assign({
@@ -224,7 +225,7 @@ context('TypeScript', function () {
           filename: testFilePath('typescript-d-ts/file-2.ts'),
         }, parserConfig)),
 
-        ...(semver.satisfies(eslintPkg.version, '< 6') ? [] : [
+        (semver.satisfies(eslintPkg.version, '< 6') ? [] : [
           test({
             code: `
               export * as A from './named-export-collision/a';
@@ -258,7 +259,7 @@ context('TypeScript', function () {
           `,
         }, parserConfig)),
 
-        ...(semver.satisfies(process.version, '< 8') && semver.satisfies(eslintPkg.version, '< 6') ? [] : test({
+        (semver.satisfies(process.version, '< 8') && semver.satisfies(eslintPkg.version, '< 6') ? [] : test({
           ...parserConfig,
           code: `
             export * from './module';
@@ -269,7 +270,7 @@ context('TypeScript', function () {
             'import/extensions': ['.js', '.ts', '.jsx'],
           },
         })),
-      ],
+      ),
       invalid: [
         // type/value name clash
         test(Object.assign({
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 9ad18cbff8..80cc076ced 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -1,5 +1,7 @@
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
+import semver from 'semver';
+import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
 
 import { getTSParsers, parsers, testVersion } from '../utils';
 
@@ -12,7 +14,7 @@ const REQUIRE_ERROR_MESSAGE = 'Expected 1 empty line after require statement not
 const ruleTester = new RuleTester();
 
 ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
-  valid: [
+  valid: [].concat(
     `var path = require('path');\nvar foo = require('foo');\n`,
     `require('foo');`,
     `switch ('foo') { case 'bar': require('baz'); }`,
@@ -178,7 +180,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { sourceType: 'module' },
       parser: parsers.BABEL_OLD,
     },
-    ...flatMap(getTSParsers(), (parser) => [
+    flatMap(getTSParsers(), (parser) => [].concat(
       {
         code: `
           import { ExecaReturnValue } from 'execa';
@@ -213,14 +215,14 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
-      {
+      parser !== parsers.TS_OLD || semver.satisfies(tsEslintVersion, '>= 22') ? {
         code: `
           export import a = obj;\nf(a);
         `,
         parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      },
-      {
+      } : [],
+      parser !== parsers.TS_OLD || semver.satisfies(tsEslintVersion, '>= 22') ? {
         code: `
           import { a } from "./a";
 
@@ -230,7 +232,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
           }`,
         parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      },
+      } : [],
       {
         code: `
           import stub from './stub';
@@ -242,7 +244,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
-    ]),
+    )),
     {
       code: `
         import stub from './stub';
@@ -253,7 +255,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       `,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
-  ],
+  ),
 
   invalid: [].concat(
     {
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 23b6e244ea..6a36f08bbf 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -1,6 +1,8 @@
 import { test, testVersion, getNonDefaultParsers, parsers } from '../utils';
 
 import { RuleTester } from 'eslint';
+import semver from 'semver';
+import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
 
 const ruleTester = new RuleTester();
 const rule = require('../../../src/rules/prefer-default-export');
@@ -164,28 +166,24 @@ context('TypeScript', function () {
     };
 
     ruleTester.run('prefer-default-export', rule, {
-      valid: [
+      valid: [].concat(
         // Exporting types
-        test({
+        semver.satisfies(tsEslintVersion, '>= 22') ? test({
           code: `
           export type foo = string;
           export type bar = number;`,
           ...parserConfig,
-        }),
+        }) : [],
         test({
           code: `
           export type foo = string;
           export type bar = number;`,
           ...parserConfig,
         }),
-        test({
-          code: 'export type foo = string',
-          ...parserConfig,
-        }),
-        test({
+        semver.satisfies(tsEslintVersion, '>= 22') ? test({
           code: 'export type foo = string',
           ...parserConfig,
-        }),
+        }) : [],
         test({
           code: 'export interface foo { bar: string; }',
           ...parserConfig,
@@ -194,7 +192,7 @@ context('TypeScript', function () {
           code: 'export interface foo { bar: string; }; export function goo() {}',
           ...parserConfig,
         }),
-      ],
+      ),
       invalid: [],
     });
   });

From 128d505642312cfeca4180a0ce702c23e982ca2e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 28 Jan 2022 15:01:53 -0800
Subject: [PATCH 454/767] [Tests] handle eslint v8.8 adding
 `suppressedMessages` property

---
 tests/src/cli.js | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tests/src/cli.js b/tests/src/cli.js
index 5b7e705b0e..e6afd8e441 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -104,6 +104,9 @@ describe('CLI regression tests', function () {
                 fixableErrorCount: 0,
                 fixableWarningCount: 0,
                 source: results[0].source, // NewLine-characters might differ depending on git-settings
+                ...(semver.satisfies(eslintPkg.version, '>= 8.8') && {
+                  suppressedMessages: [],
+                }),
                 usedDeprecatedRules: results[0].usedDeprecatedRules, // we don't care about this one
               },
             ],

From eef7487368e9cba476c6095499f30d3c654631ce Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 30 Jan 2022 23:28:20 -0800
Subject: [PATCH 455/767] [Tests] consolidate eslint config

---
 .eslintrc                   | 20 ++++++++++++++++++++
 memo-parser/.eslintrc.yml   |  3 ---
 resolvers/webpack/.eslintrc |  9 ---------
 tests/.eslintrc             |  9 ---------
 4 files changed, 20 insertions(+), 21 deletions(-)
 delete mode 100644 memo-parser/.eslintrc.yml
 delete mode 100644 resolvers/webpack/.eslintrc
 delete mode 100644 tests/.eslintrc

diff --git a/.eslintrc b/.eslintrc
index 12fb8b7a23..2cbfd59cea 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -102,6 +102,16 @@
                 "es6": false,
             },
         },
+        {
+            "files": "resolvers/webpack/**",
+            "rules": {
+                "import/no-extraneous-dependencies": 1,
+                "no-console": 1,
+            },
+            "env": {
+                "es6": true,
+            },
+        },
         {
             "files": [
                 "resolvers/*/test/**/*",
@@ -127,5 +137,15 @@
                 "no-console": 1,
             },
         },
+        {
+            "files": "tests/**",
+            "env": {
+                "mocha": true,
+            },
+            "rules": {
+                "max-len": 0,
+                "import/default": 0,
+            },
+        },
     ],
 }
diff --git a/memo-parser/.eslintrc.yml b/memo-parser/.eslintrc.yml
deleted file mode 100644
index e7e6b3d341..0000000000
--- a/memo-parser/.eslintrc.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-rules:
-  import/no-extraneous-dependencies: 1
diff --git a/resolvers/webpack/.eslintrc b/resolvers/webpack/.eslintrc
deleted file mode 100644
index 544167c4bb..0000000000
--- a/resolvers/webpack/.eslintrc
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "rules": {
-    "import/no-extraneous-dependencies": 1,
-    "no-console": 1,
-  },
-  "env": {
-    "es6": true,
-  },
-}
diff --git a/tests/.eslintrc b/tests/.eslintrc
deleted file mode 100644
index 5720f3fcac..0000000000
--- a/tests/.eslintrc
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "env": {
-    "mocha": true,
-  },
-  "rules": {
-    "max-len": 0,
-    "import/default": 0,
-  },
-}

From 41d4500d83e969a0b24be837625f754b9eadada6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 30 Jan 2022 23:28:57 -0800
Subject: [PATCH 456/767] [Deps] update `eslint-module-utils`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 2ebaf62402..0462f9cb33 100644
--- a/package.json
+++ b/package.json
@@ -104,7 +104,7 @@
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
-    "eslint-module-utils": "^2.7.2",
+    "eslint-module-utils": "^2.7.3",
     "has": "^1.0.3",
     "is-core-module": "^2.8.1",
     "is-glob": "^4.0.3",

From ade33a49b1679a4ff7ba8fe472fab6a8a52fef4e Mon Sep 17 00:00:00 2001
From: Martin Garcia <newluxfero@gmail.com>
Date: Thu, 27 Jan 2022 17:10:07 +0100
Subject: [PATCH 457/767] [Fix] `export`: false positive for typescript
 namespace merging

---
 CHANGELOG.md              |   5 +-
 src/rules/export.js       |  64 +++++++++++++--
 tests/src/rules/export.js | 166 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 221 insertions(+), 14 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d339757ef..39401934c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,9 +10,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
 
-
 ### Fixed
 - [`default`]: `typescript-eslint-parser`: avoid a crash on exporting as namespace (thanks [@ljharb])
+- [`export`]/TypeScript: false positive for typescript namespace merging ([#1964], thanks [@magarcia])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
@@ -1575,6 +1575,7 @@ for info on changes for earlier releases.
 [@ludofischer]: https://github.com/ludofischer
 [@lukeapage]: https://github.com/lukeapage
 [@lydell]: https://github.com/lydell
+[@magarcia]: https://github.com/magarcia
 [@Mairu]: https://github.com/Mairu
 [@malykhinvi]: https://github.com/malykhinvi
 [@manovotny]: https://github.com/manovotny
@@ -1665,4 +1666,4 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xpl]: https://github.com/xpl
 [@yordis]: https://github.com/yordis
-[@zloirock]: https://github.com/zloirock
\ No newline at end of file
+[@zloirock]: https://github.com/zloirock
diff --git a/src/rules/export.js b/src/rules/export.js
index b9378f0910..3c998ec2c6 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -36,13 +36,59 @@ const tsTypePrefix = 'type:';
  */
 function isTypescriptFunctionOverloads(nodes) {
   const types = new Set(Array.from(nodes, node => node.parent.type));
-  return (
-    types.has('TSDeclareFunction') &&
-    (
-      types.size === 1 ||
-      (types.size === 2 && types.has('FunctionDeclaration'))
-    )
-  );
+  return types.has('TSDeclareFunction')
+    && (
+      types.size === 1
+      || (types.size === 2 && types.has('FunctionDeclaration'))
+    );
+}
+
+/**
+ * Detect merging Namespaces with Classes, Functions, or Enums like:
+ * ```ts
+ * export class Foo { }
+ * export namespace Foo { }
+ * ```
+ * @param {Set<Object>} nodes
+ * @returns {boolean}
+ */
+function isTypescriptNamespaceMerging(nodes) {
+  const types = new Set(Array.from(nodes, node => node.parent.type));
+  const noNamespaceNodes = Array.from(nodes).filter((node) => node.parent.type !== 'TSModuleDeclaration');
+
+  return types.has('TSModuleDeclaration')
+    && (
+      types.size === 1
+      // Merging with functions
+      || (types.size === 2 && (types.has('FunctionDeclaration') || types.has('TSDeclareFunction')))
+      || (types.size === 3 && types.has('FunctionDeclaration') && types.has('TSDeclareFunction'))
+      // Merging with classes or enums
+      || (types.size === 2 && (types.has('ClassDeclaration') || types.has('TSEnumDeclaration')) && noNamespaceNodes.length === 1)
+    );
+}
+
+/**
+ * Detect if a typescript namespace node should be reported as multiple export:
+ * ```ts
+ * export class Foo { }
+ * export function Foo();
+ * export namespace Foo { }
+ * ```
+ * @param {Object} node
+ * @param {Set<Object>} nodes
+ * @returns {boolean}
+ */
+function shouldSkipTypescriptNamespace(node, nodes) {
+  const types = new Set(Array.from(nodes, node => node.parent.type));
+
+  return !isTypescriptNamespaceMerging(nodes)
+    && node.parent.type === 'TSModuleDeclaration'
+    && (
+      types.has('TSEnumDeclaration')
+      || types.has('ClassDeclaration')
+      || types.has('FunctionDeclaration')
+      || types.has('TSDeclareFunction')
+    );
 }
 
 module.exports = {
@@ -156,9 +202,11 @@ module.exports = {
           for (const [name, nodes] of named) {
             if (nodes.size <= 1) continue;
 
-            if (isTypescriptFunctionOverloads(nodes)) continue;
+            if (isTypescriptFunctionOverloads(nodes) || isTypescriptNamespaceMerging(nodes)) continue;
 
             for (const node of nodes) {
+              if (shouldSkipTypescriptNamespace(node, nodes)) continue;
+
               if (name === 'default') {
                 context.report(node, 'Multiple default exports.');
               } else {
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index e95efa0329..53a7689a87 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -220,12 +220,50 @@ context('TypeScript', function () {
             }
           `,
         }, parserConfig)),
+
+        semver.satisfies(eslintPkg.version, '>= 6') ? [
+          test(Object.assign({
+            code: `
+              export class Foo { }
+              export namespace Foo { }
+              export namespace Foo {
+                export class Bar {}
+              }
+            `,
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export function Foo();
+              export namespace Foo { }
+            `,
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export function Foo(a: string);
+              export namespace Foo { }
+            `,
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export function Foo(a: string);
+              export function Foo(a: number);
+              export namespace Foo { }
+            `,
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export enum Foo { }
+              export namespace Foo { }
+            `,
+          }, parserConfig)),
+        ] : [],
+
         test(Object.assign({
           code: 'export * from "./file1.ts"',
           filename: testFilePath('typescript-d-ts/file-2.ts'),
         }, parserConfig)),
 
-        (semver.satisfies(eslintPkg.version, '< 6') ? [] : [
+        semver.satisfies(eslintPkg.version, '>= 6') ? [
           test({
             code: `
               export * as A from './named-export-collision/a';
@@ -233,7 +271,7 @@ context('TypeScript', function () {
             `,
             parser,
           }),
-        ]),
+        ] : [],
 
         // Exports in ambient modules
         test(Object.assign({
@@ -271,7 +309,7 @@ context('TypeScript', function () {
           },
         })),
       ),
-      invalid: [
+      invalid: [].concat(
         // type/value name clash
         test(Object.assign({
           code: `
@@ -361,6 +399,126 @@ context('TypeScript', function () {
             },
           ],
         }, parserConfig)),
+        semver.satisfies(eslintPkg.version, '< 6') ? [] : [
+          test(Object.assign({
+            code: `
+              export class Foo { }
+              export class Foo { }
+              export namespace Foo { }
+            `,
+            errors: [
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 2,
+              },
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 3,
+              },
+            ],
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export enum Foo { }
+              export enum Foo { }
+              export namespace Foo { }
+            `,
+            errors: [
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 2,
+              },
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 3,
+              },
+            ],
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export enum Foo { }
+              export class Foo { }
+              export namespace Foo { }
+            `,
+            errors: [
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 2,
+              },
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 3,
+              },
+            ],
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export const Foo = 'bar';
+              export class Foo { }
+              export namespace Foo { }
+            `,
+            errors: [
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 2,
+              },
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 3,
+              },
+            ],
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export function Foo();
+              export class Foo { }
+              export namespace Foo { }
+            `,
+            errors: [
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 2,
+              },
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 3,
+              },
+            ],
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export const Foo = 'bar';
+              export function Foo();
+              export namespace Foo { }
+            `,
+            errors: [
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 2,
+              },
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 3,
+              },
+            ],
+          }, parserConfig)),
+          test(Object.assign({
+            code: `
+              export const Foo = 'bar';
+              export namespace Foo { }
+            `,
+            errors: [
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 2,
+              },
+              {
+                message: `Multiple exports of name 'Foo'.`,
+                line: 3,
+              },
+            ],
+          }, parserConfig)),
+        ],
 
         // Exports in ambient modules
         test(Object.assign({
@@ -385,7 +543,7 @@ context('TypeScript', function () {
             },
           ],
         }, parserConfig)),
-      ],
+      ),
     });
   });
 });

From 3603428771f3ad81370b85ec3d9a81b525bb65e6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 1 Feb 2022 15:07:03 -0800
Subject: [PATCH 458/767] [Refactor] `export`: clean up rule, tests

---
 src/rules/export.js       |  20 +++--
 tests/src/rules/export.js | 177 +++++++++++++++++++++++---------------
 2 files changed, 118 insertions(+), 79 deletions(-)

diff --git a/src/rules/export.js b/src/rules/export.js
index 3c998ec2c6..4cae107402 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -131,15 +131,19 @@ module.exports = {
     }
 
     return {
-      'ExportDefaultDeclaration': (node) => addNamed('default', node, getParent(node)),
+      ExportDefaultDeclaration(node) {
+        addNamed('default', node, getParent(node));
+      },
 
-      'ExportSpecifier': (node) => addNamed(
-        node.exported.name || node.exported.value,
-        node.exported,
-        getParent(node.parent),
-      ),
+      ExportSpecifier(node) {
+        addNamed(
+          node.exported.name || node.exported.value,
+          node.exported,
+          getParent(node.parent),
+        );
+      },
 
-      'ExportNamedDeclaration': function (node) {
+      ExportNamedDeclaration(node) {
         if (node.declaration == null) return;
 
         const parent = getParent(node);
@@ -165,7 +169,7 @@ module.exports = {
         }
       },
 
-      'ExportAllDeclaration': function (node) {
+      ExportAllDeclaration(node) {
         if (node.source == null) return; // not sure if this is ever true
 
         // `export * as X from 'path'` does not conflict
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 53a7689a87..5996e9fa3f 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -26,7 +26,7 @@ ruleTester.run('export', rule, {
     // #328: "export * from" does not export a default
     test({ code: 'export default foo; export * from "./bar"' }),
 
-    ...SYNTAX_CASES,
+    SYNTAX_CASES,
 
     test({
       code: `
@@ -82,22 +82,31 @@ ruleTester.run('export', rule, {
     // }),
     test({
       code: 'let foo; export { foo }; export * from "./export-all"',
-      errors: ['Multiple exports of name \'foo\'.',
-        'Multiple exports of name \'foo\'.'],
+      errors: [
+        'Multiple exports of name \'foo\'.',
+        'Multiple exports of name \'foo\'.',
+      ],
     }),
-    // test({ code: 'export * from "./default-export"'
-    //      , errors: [{ message: 'No named exports found in module ' +
-    //                            '\'./default-export\'.'
-    //                 , type: 'Literal' }] }),
+    // test({
+    //   code: 'export * from "./default-export"',
+    //   errors: [
+    //     {
+    //       message: 'No named exports found in module \'./default-export\'.',
+    //       type: 'Literal',
+    //     },
+    //   ],
+    // }),
 
     // note: Espree bump to Acorn 4+ changed this test's error message.
     //       `npm up` first if it's failing.
     test({
       code: 'export * from "./malformed.js"',
-      errors: [{
-        message: "Parse errors in imported module './malformed.js': 'return' outside of function (1:1)",
-        type: 'Literal',
-      }],
+      errors: [
+        {
+          message: "Parse errors in imported module './malformed.js': 'return' outside of function (1:1)",
+          type: 'Literal',
+        },
+      ],
     }),
 
     // test({
@@ -152,52 +161,58 @@ context('TypeScript', function () {
     ruleTester.run('export', rule, {
       valid: [].concat(
         // type/value name clash
-        test(Object.assign({
+        test({
           code: `
             export const Foo = 1;
             export type Foo = number;
           `,
-        }, parserConfig)),
-        test(Object.assign({
+          ...parserConfig,
+        }),
+        test({
           code: `
             export const Foo = 1;
             export interface Foo {}
           `,
-        }, parserConfig)),
+          ...parserConfig,
+        }),
 
-        semver.satisfies(tsEslintVersion, '>= 22') ? test(Object.assign({
+        semver.satisfies(tsEslintVersion, '>= 22') ? test({
           code: `
             export function fff(a: string);
             export function fff(a: number);
           `,
-        }, parserConfig)) : [],
+          ...parserConfig,
+        }) : [],
 
-        semver.satisfies(tsEslintVersion, '>= 22') ? test(Object.assign({
+        semver.satisfies(tsEslintVersion, '>= 22') ? test({
           code: `
             export function fff(a: string);
             export function fff(a: number);
             export function fff(a: string|number) {};
           `,
-        }, parserConfig)) : [],
+          ...parserConfig,
+        }) : [],
 
         // namespace
-        test(Object.assign({
+        test({
           code: `
             export const Bar = 1;
             export namespace Foo {
               export const Bar = 1;
             }
           `,
-        }, parserConfig)),
-        test(Object.assign({
+          ...parserConfig,
+        }),
+        test({
           code: `
             export type Bar = string;
             export namespace Foo {
               export type Bar = string;
             }
           `,
-        }, parserConfig)),
-        test(Object.assign({
+          ...parserConfig,
+        }),
+        test({
           code: `
             export const Bar = 1;
             export type Bar = string;
@@ -206,8 +221,9 @@ context('TypeScript', function () {
               export type Bar = string;
             }
           `,
-        }, parserConfig)),
-        test(Object.assign({
+          ...parserConfig,
+        }),
+        test({
           code: `
             export namespace Foo {
               export const Foo = 1;
@@ -219,10 +235,10 @@ context('TypeScript', function () {
               }
             }
           `,
-        }, parserConfig)),
-
+          ...parserConfig,
+        }),
         semver.satisfies(eslintPkg.version, '>= 6') ? [
-          test(Object.assign({
+          test({
             code: `
               export class Foo { }
               export namespace Foo { }
@@ -230,38 +246,43 @@ context('TypeScript', function () {
                 export class Bar {}
               }
             `,
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export function Foo();
               export namespace Foo { }
             `,
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export function Foo(a: string);
               export namespace Foo { }
             `,
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export function Foo(a: string);
               export function Foo(a: number);
               export namespace Foo { }
             `,
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export enum Foo { }
               export namespace Foo { }
             `,
-          }, parserConfig)),
+            ...parserConfig,
+          }),
         ] : [],
-
-        test(Object.assign({
+        test({
           code: 'export * from "./file1.ts"',
           filename: testFilePath('typescript-d-ts/file-2.ts'),
-        }, parserConfig)),
+          ...parserConfig,
+        }),
 
         semver.satisfies(eslintPkg.version, '>= 6') ? [
           test({
@@ -274,7 +295,7 @@ context('TypeScript', function () {
         ] : [],
 
         // Exports in ambient modules
-        test(Object.assign({
+        test({
           code: `
             declare module "a" {
               const Foo = 1;
@@ -285,8 +306,9 @@ context('TypeScript', function () {
               export {Bar as default};
             }
           `,
-        }, parserConfig)),
-        test(Object.assign({
+          ...parserConfig,
+        }),
+        test({
           code: `
             declare module "a" {
               const Foo = 1;
@@ -295,9 +317,10 @@ context('TypeScript', function () {
             const Bar = 2;
             export {Bar as default};
           `,
-        }, parserConfig)),
+          ...parserConfig,
+        }),
 
-        (semver.satisfies(process.version, '< 8') && semver.satisfies(eslintPkg.version, '< 6') ? [] : test({
+        semver.satisfies(process.version, '< 8') && semver.satisfies(eslintPkg.version, '< 6') ? [] : test({
           ...parserConfig,
           code: `
             export * from './module';
@@ -307,11 +330,11 @@ context('TypeScript', function () {
             ...parserConfig.settings,
             'import/extensions': ['.js', '.ts', '.jsx'],
           },
-        })),
+        }),
       ),
       invalid: [].concat(
         // type/value name clash
-        test(Object.assign({
+        test({
           code: `
             export type Foo = string;
             export type Foo = number;
@@ -326,10 +349,11 @@ context('TypeScript', function () {
               line: 3,
             },
           ],
-        }, parserConfig)),
+          ...parserConfig,
+        }),
 
         // namespace
-        test(Object.assign({
+        test({
           code: `
             export const a = 1
             export namespace Foo {
@@ -347,8 +371,9 @@ context('TypeScript', function () {
               line: 5,
             },
           ],
-        }, parserConfig)),
-        test(Object.assign({
+          ...parserConfig,
+        }),
+        test({
           code: `
             declare module 'foo' {
               const Foo = 1;
@@ -366,8 +391,9 @@ context('TypeScript', function () {
               line: 5,
             },
           ],
-        }, parserConfig)),
-        test(Object.assign({
+          ...parserConfig,
+        }),
+        test({
           code: `
             export namespace Foo {
               export namespace Bar {
@@ -398,9 +424,10 @@ context('TypeScript', function () {
               line: 9,
             },
           ],
-        }, parserConfig)),
+          ...parserConfig,
+        }),
         semver.satisfies(eslintPkg.version, '< 6') ? [] : [
-          test(Object.assign({
+          test({
             code: `
               export class Foo { }
               export class Foo { }
@@ -416,8 +443,9 @@ context('TypeScript', function () {
                 line: 3,
               },
             ],
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export enum Foo { }
               export enum Foo { }
@@ -433,8 +461,9 @@ context('TypeScript', function () {
                 line: 3,
               },
             ],
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export enum Foo { }
               export class Foo { }
@@ -450,8 +479,9 @@ context('TypeScript', function () {
                 line: 3,
               },
             ],
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export const Foo = 'bar';
               export class Foo { }
@@ -467,8 +497,9 @@ context('TypeScript', function () {
                 line: 3,
               },
             ],
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export function Foo();
               export class Foo { }
@@ -484,8 +515,9 @@ context('TypeScript', function () {
                 line: 3,
               },
             ],
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export const Foo = 'bar';
               export function Foo();
@@ -501,8 +533,9 @@ context('TypeScript', function () {
                 line: 3,
               },
             ],
-          }, parserConfig)),
-          test(Object.assign({
+            ...parserConfig,
+          }),
+          test({
             code: `
               export const Foo = 'bar';
               export namespace Foo { }
@@ -517,11 +550,12 @@ context('TypeScript', function () {
                 line: 3,
               },
             ],
-          }, parserConfig)),
+            ...parserConfig,
+          }),
         ],
 
         // Exports in ambient modules
-        test(Object.assign({
+        test({
           code: `
             declare module "a" {
               const Foo = 1;
@@ -542,7 +576,8 @@ context('TypeScript', function () {
               line: 9,
             },
           ],
-        }, parserConfig)),
+          ...parserConfig,
+        }),
       ),
     });
   });

From 0595a2f1c5b23680fbe5d234e4f30708ce1396e9 Mon Sep 17 00:00:00 2001
From: Remco Haszing <remcohaszing@gmail.com>
Date: Sat, 29 Jan 2022 13:15:22 +0100
Subject: [PATCH 459/767] [Fix] `no-duplicates`: Ignore duplicate modules in
 different TypeScript module declarations

Without this the `import/no-duplicates` rule reports imports of the same
module inside different module declarations in the same file. It even
autofixed them, which break the code.

Closes #2273
---
 CHANGELOG.md                     |  2 ++
 src/rules/no-duplicates.js       | 28 ++++++++++++++++++----------
 tests/src/rules/no-duplicates.js | 14 ++++++++++++++
 3 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 39401934c9..c8361895b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [`default`]: `typescript-eslint-parser`: avoid a crash on exporting as namespace (thanks [@ljharb])
 - [`export`]/TypeScript: false positive for typescript namespace merging ([#1964], thanks [@magarcia])
+- [`no-duplicates`]: ignore duplicate modules in different TypeScript module declarations ([#2378], thanks [@remcohaszing])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
@@ -968,6 +969,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2378]: https://github.com/import-js/eslint-plugin-import/pull/2378
 [#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
 [#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
 [#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 43c2c5b201..efd9583fbc 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -274,17 +274,23 @@ module.exports = {
       return defaultResolver(parts[1]) + '?' + parts[2];
     }) : defaultResolver;
 
-    const imported = new Map();
-    const nsImported = new Map();
-    const defaultTypesImported = new Map();
-    const namedTypesImported = new Map();
+    const moduleMaps = new Map();
 
     function getImportMap(n) {
+      if (!moduleMaps.has(n.parent)) {
+        moduleMaps.set(n.parent, {
+          imported: new Map(),
+          nsImported: new Map(),
+          defaultTypesImported: new Map(),
+          namedTypesImported: new Map(),
+        });
+      }
+      const map = moduleMaps.get(n.parent);
       if (n.importKind === 'type') {
-        return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? defaultTypesImported : namedTypesImported;
+        return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? map.defaultTypesImported : map.namedTypesImported;
       }
 
-      return hasNamespace(n) ? nsImported : imported;
+      return hasNamespace(n) ? map.nsImported : map.imported;
     }
 
     return {
@@ -301,10 +307,12 @@ module.exports = {
       },
 
       'Program:exit': function () {
-        checkImports(imported, context);
-        checkImports(nsImported, context);
-        checkImports(defaultTypesImported, context);
-        checkImports(namedTypesImported, context);
+        for (const map of moduleMaps.values()) {
+          checkImports(map.imported, context);
+          checkImports(map.nsImported, context);
+          checkImports(map.defaultTypesImported, context);
+          checkImports(map.namedTypesImported, context);
+        }
       },
     };
   },
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index b481e6c823..cde41b3a07 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -454,6 +454,20 @@ context('TypeScript', function () {
             `,
             ...parserConfig,
           }),
+          test({
+            code: `
+              import type { Identifier } from 'module';
+
+              declare module 'module2' {
+                import type { Identifier } from 'module';
+              }
+
+              declare module 'module3' {
+                import type { Identifier } from 'module';
+              }
+            `,
+            ...parserConfig,
+          }),
         ],
         invalid: [
           test({

From 02ccbc1a30098822b7a6e7d84d8594b387495361 Mon Sep 17 00:00:00 2001
From: Emily Marigold Klassen <forivall@gmail.com>
Date: Thu, 3 Feb 2022 19:03:21 -0800
Subject: [PATCH 460/767] [New] `no-relative-packages`: add fixer

---
 CHANGELOG.md                            | 2 ++
 docs/rules/no-relative-packages.md      | 1 +
 src/rules/no-relative-packages.js       | 8 ++++++++
 tests/src/rules/no-relative-packages.js | 4 ++++
 4 files changed, 15 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c8361895b0..5c14fd3484 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
 - [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
+- [`no-relative-packages`]: add fixer ([#2381], thanks [@forivall])
 
 ### Fixed
 - [`default`]: `typescript-eslint-parser`: avoid a crash on exporting as namespace (thanks [@ljharb])
@@ -969,6 +970,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2381]: https://github.com/import-js/eslint-plugin-import/pull/2381
 [#2378]: https://github.com/import-js/eslint-plugin-import/pull/2378
 [#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
 [#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
diff --git a/docs/rules/no-relative-packages.md b/docs/rules/no-relative-packages.md
index d5a0684932..a989c12a23 100644
--- a/docs/rules/no-relative-packages.md
+++ b/docs/rules/no-relative-packages.md
@@ -5,6 +5,7 @@ Use this rule to prevent importing packages through relative paths.
 It's useful in Yarn/Lerna workspaces, were it's possible to import a sibling
 package using `../package` relative path, while direct `package` is the correct one.
 
++(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule.
 
 ### Examples
 
diff --git a/src/rules/no-relative-packages.js b/src/rules/no-relative-packages.js
index 17406e80eb..7bf1ce5cea 100644
--- a/src/rules/no-relative-packages.js
+++ b/src/rules/no-relative-packages.js
@@ -6,6 +6,11 @@ import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisi
 import importType from '../core/importType';
 import docsUrl from '../docsUrl';
 
+/** @param {string} filePath */
+function toPosixPath(filePath) {
+  return filePath.replace(/\\/g, '/');
+}
+
 function findNamedPackage(filePath) {
   const found = readPkgUp({ cwd: filePath });
   if (found.pkg && !found.pkg.name) {
@@ -42,6 +47,8 @@ function checkImportForRelativePackage(context, importPath, node) {
     context.report({
       node,
       message: `Relative import from another package is not allowed. Use \`${properImport}\` instead of \`${importPath}\``,
+      fix: fixer => fixer.replaceText(node, JSON.stringify(toPosixPath(properImport)))
+      ,
     });
   }
 }
@@ -52,6 +59,7 @@ module.exports = {
     docs: {
       url: docsUrl('no-relative-packages'),
     },
+    fixable: 'code',
     schema: [makeOptionsSchema()],
   },
 
diff --git a/tests/src/rules/no-relative-packages.js b/tests/src/rules/no-relative-packages.js
index 1a706387c0..2d27bcc91e 100644
--- a/tests/src/rules/no-relative-packages.js
+++ b/tests/src/rules/no-relative-packages.js
@@ -47,6 +47,7 @@ ruleTester.run('no-relative-packages', rule, {
         line: 1,
         column: 17,
       } ],
+      output: 'import foo from "package-named"',
     }),
     test({
       code: 'import foo from "../package-named"',
@@ -56,6 +57,7 @@ ruleTester.run('no-relative-packages', rule, {
         line: 1,
         column: 17,
       } ],
+      output: 'import foo from "package-named"',
     }),
     test({
       code: 'import foo from "../package-scoped"',
@@ -65,6 +67,7 @@ ruleTester.run('no-relative-packages', rule, {
         line: 1,
         column: 17,
       } ],
+      output: `import foo from "@scope/package-named"`,
     }),
     test({
       code: 'import bar from "../bar"',
@@ -74,6 +77,7 @@ ruleTester.run('no-relative-packages', rule, {
         line: 1,
         column: 17,
       } ],
+      output: `import bar from "eslint-plugin-import/tests/files/bar"`,
     }),
   ],
 });

From 35bd3a576c20005579cfbaa443a3a5f9d62250f6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 20 Feb 2022 23:04:54 -0800
Subject: [PATCH 461/767] [Dev Deps] update `@angular-eslint/template-parser`,
 `chai`

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 0462f9cb33..1ddf93c87a 100644
--- a/package.json
+++ b/package.json
@@ -53,7 +53,7 @@
   },
   "homepage": "https://github.com/import-js/eslint-plugin-import",
   "devDependencies": {
-    "@angular-eslint/template-parser": "^13.0.1",
+    "@angular-eslint/template-parser": "^13.1.0",
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3 || ^5.10.0",
@@ -67,7 +67,7 @@
     "babel-preset-flow": "^6.23.0",
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
-    "chai": "^4.3.4",
+    "chai": "^4.3.6",
     "cross-env": "^4.0.0",
     "escope": "^3.6.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8",

From 00a4edee3501d65ada7f9f98f04ad2ada46ad86f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 22 Feb 2022 13:18:12 -0800
Subject: [PATCH 462/767] [Deps] update `minimatch`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 1ddf93c87a..9a55575143 100644
--- a/package.json
+++ b/package.json
@@ -108,7 +108,7 @@
     "has": "^1.0.3",
     "is-core-module": "^2.8.1",
     "is-glob": "^4.0.3",
-    "minimatch": "^3.0.4",
+    "minimatch": "^3.1.2",
     "object.values": "^1.1.5",
     "resolve": "^1.22.0",
     "tsconfig-paths": "^3.12.0"

From b0e6f7f48945e2533e96d513248bf3e54e0c1aac Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 22 Feb 2022 13:27:43 -0800
Subject: [PATCH 463/767] [Refactor] `namespace`: try to improve performance

See #2340
---
 CHANGELOG.md           |  2 ++
 src/rules/namespace.js | 79 +++++++++++++++++++++---------------------
 2 files changed, 41 insertions(+), 40 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5c14fd3484..84b1b4aa2f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
 - [Tests] `default`, `no-anonymous-default-export`, `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [Docs] [`no-unresolved`]: Fix RegExp escaping in readme ([#2332], thanks [@stephtr])
+- [Refactor] `namespace`: try to improve performance ([#2340], thanks [@ljharb])
 
 ## [2.25.4] - 2022-01-02
 
@@ -1255,6 +1256,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2340]: https://github.com/import-js/eslint-plugin-import/issues/2340
 [#2255]: https://github.com/import-js/eslint-plugin-import/issues/2255
 [#2210]: https://github.com/import-js/eslint-plugin-import/issues/2210
 [#2201]: https://github.com/import-js/eslint-plugin-import/issues/2201
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 8a7099df61..405c415cea 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -3,6 +3,44 @@ import Exports from '../ExportMap';
 import importDeclaration from '../importDeclaration';
 import docsUrl from '../docsUrl';
 
+function processBodyStatement(context, namespaces, declaration) {
+  if (declaration.type !== 'ImportDeclaration') return;
+
+  if (declaration.specifiers.length === 0) return;
+
+  const imports = Exports.get(declaration.source.value, context);
+  if (imports == null) return null;
+
+  if (imports.errors.length > 0) {
+    imports.reportErrors(context, declaration);
+    return;
+  }
+
+  declaration.specifiers.forEach((specifier) => {
+    switch (specifier.type) {
+    case 'ImportNamespaceSpecifier':
+      if (!imports.size) {
+        context.report(
+          specifier,
+          `No exported names found in module '${declaration.source.value}'.`,
+        );
+      }
+      namespaces.set(specifier.local.name, imports);
+      break;
+    case 'ImportDefaultSpecifier':
+    case 'ImportSpecifier': {
+      const meta = imports.get(
+        // default to 'default' for default https://i.imgur.com/nj6qAWy.jpg
+        specifier.imported ? (specifier.imported.name || specifier.imported.value) : 'default',
+      );
+      if (!meta || !meta.namespace) { break; }
+      namespaces.set(specifier.local.name, meta.namespace);
+      break;
+    }
+    }
+  });
+}
+
 module.exports = {
   meta: {
     type: 'problem',
@@ -41,44 +79,7 @@ module.exports = {
     return {
       // pick up all imports at body entry time, to properly respect hoisting
       Program({ body }) {
-        function processBodyStatement(declaration) {
-          if (declaration.type !== 'ImportDeclaration') return;
-
-          if (declaration.specifiers.length === 0) return;
-
-          const imports = Exports.get(declaration.source.value, context);
-          if (imports == null) return null;
-
-          if (imports.errors.length) {
-            imports.reportErrors(context, declaration);
-            return;
-          }
-
-          for (const specifier of declaration.specifiers) {
-            switch (specifier.type) {
-            case 'ImportNamespaceSpecifier':
-              if (!imports.size) {
-                context.report(
-                  specifier,
-                  `No exported names found in module '${declaration.source.value}'.`,
-                );
-              }
-              namespaces.set(specifier.local.name, imports);
-              break;
-            case 'ImportDefaultSpecifier':
-            case 'ImportSpecifier': {
-              const meta = imports.get(
-                // default to 'default' for default https://i.imgur.com/nj6qAWy.jpg
-                specifier.imported ? (specifier.imported.name || specifier.imported.value) : 'default',
-              );
-              if (!meta || !meta.namespace) { break; }
-              namespaces.set(specifier.local.name, meta.namespace);
-              break;
-            }
-            }
-          }
-        }
-        body.forEach(processBodyStatement);
+        body.forEach(x => processBodyStatement(context, namespaces, x));
       },
 
       // same as above, but does not add names to local map
@@ -120,7 +121,6 @@ module.exports = {
         const namepath = [dereference.object.name];
         // while property is namespace and parent is member expression, keep validating
         while (namespace instanceof Exports && dereference.type === 'MemberExpression') {
-
           if (dereference.computed) {
             if (!allowComputed) {
               context.report(
@@ -147,7 +147,6 @@ module.exports = {
           namespace = exported.namespace;
           dereference = dereference.parent;
         }
-
       },
 
       VariableDeclarator({ id, init }) {

From 747d6dc5b905a718c89f10aad04cb2bcdbed7068 Mon Sep 17 00:00:00 2001
From: The Jared Wilcurt <TheJaredWilcurt@users.noreply.github.com>
Date: Wed, 2 Mar 2022 18:26:46 -0500
Subject: [PATCH 464/767] [Docs] make rule doc titles consistent

matches other docs pages now, easier for copy/pasting the rule
---
 CHANGELOG.md                           | 3 +++
 docs/rules/dynamic-import-chunkname.md | 2 +-
 docs/rules/imports-first.md            | 2 +-
 docs/rules/no-import-module-exports.md | 2 +-
 4 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 84b1b4aa2f..2c9357bf18 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Tests] `default`, `no-anonymous-default-export`, `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [Docs] [`no-unresolved`]: Fix RegExp escaping in readme ([#2332], thanks [@stephtr])
 - [Refactor] `namespace`: try to improve performance ([#2340], thanks [@ljharb])
+- [Docs] make rule doc titles consistent ([#2393], thanks [@TheJaredWilcurt])
 
 ## [2.25.4] - 2022-01-02
 
@@ -971,6 +972,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
 [#2381]: https://github.com/import-js/eslint-plugin-import/pull/2381
 [#2378]: https://github.com/import-js/eslint-plugin-import/pull/2378
 [#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
@@ -1659,6 +1661,7 @@ for info on changes for earlier releases.
 [@Taranys]: https://github.com/Taranys
 [@taye]: https://github.com/taye
 [@TheCrueltySage]: https://github.com/TheCrueltySage
+[@TheJaredWilcurt]: https://github.com/TheJaredWilcurt
 [@tihonove]: https://github.com/tihonove
 [@timkraut]: https://github.com/timkraut
 [@tizmagik]: https://github.com/tizmagik
diff --git a/docs/rules/dynamic-import-chunkname.md b/docs/rules/dynamic-import-chunkname.md
index d29c06bbaa..6b43074f19 100644
--- a/docs/rules/dynamic-import-chunkname.md
+++ b/docs/rules/dynamic-import-chunkname.md
@@ -1,4 +1,4 @@
-# dynamic imports require a leading comment with a webpackChunkName (dynamic-import-chunkname)
+# import/dynamic-import-chunkname
 
 This rule reports any dynamic imports without a webpackChunkName specified in a leading block comment in the proper format.
 
diff --git a/docs/rules/imports-first.md b/docs/rules/imports-first.md
index 7dadffa684..4b90f04ea8 100644
--- a/docs/rules/imports-first.md
+++ b/docs/rules/imports-first.md
@@ -1,3 +1,3 @@
-# imports-first
+# import/imports-first
 
 This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/import-js/eslint-plugin-import/blob/HEAD/docs/rules/first.md).
diff --git a/docs/rules/no-import-module-exports.md b/docs/rules/no-import-module-exports.md
index 8131fd5f78..d658deb566 100644
--- a/docs/rules/no-import-module-exports.md
+++ b/docs/rules/no-import-module-exports.md
@@ -1,4 +1,4 @@
-# no-import-module-exports
+# import/no-import-module-exports
 
 Reports the use of import declarations with CommonJS exports in any module
 except for the [main module](https://docs.npmjs.com/files/package.json#main).

From 8b7000ec75968c1bd94f3099d67995a699286cf0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 13 Mar 2022 13:37:07 -0700
Subject: [PATCH 465/767] [Fix] `no-unused-modules`: avoid a crash when
 processing re-exports

Fixes #2388.
---
 CHANGELOG.md                                        |  2 ++
 src/rules/no-unused-modules.js                      |  6 ++++--
 .../files/unused-modules-reexport-crash/src/App.tsx |  5 +++++
 .../unused-modules-reexport-crash/src/index.tsx     |  3 +++
 .../src/magic/index.js                              |  1 +
 .../unused-modules-reexport-crash/src/magic/test.js |  7 +++++++
 tests/src/rules/no-unused-modules.js                | 13 ++++++++++++-
 7 files changed, 34 insertions(+), 3 deletions(-)
 create mode 100644 tests/files/unused-modules-reexport-crash/src/App.tsx
 create mode 100644 tests/files/unused-modules-reexport-crash/src/index.tsx
 create mode 100644 tests/files/unused-modules-reexport-crash/src/magic/index.js
 create mode 100644 tests/files/unused-modules-reexport-crash/src/magic/test.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c9357bf18..59ab25da95 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`default`]: `typescript-eslint-parser`: avoid a crash on exporting as namespace (thanks [@ljharb])
 - [`export`]/TypeScript: false positive for typescript namespace merging ([#1964], thanks [@magarcia])
 - [`no-duplicates`]: ignore duplicate modules in different TypeScript module declarations ([#2378], thanks [@remcohaszing])
+- [`no-unused-modules`]: avoid a crash when processing re-exports ([#2388], thanks [@ljharb])
 
 ### Changed
 - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
@@ -973,6 +974,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
+[#2388]: https://github.com/import-js/eslint-plugin-import/pull/2388
 [#2381]: https://github.com/import-js/eslint-plugin-import/pull/2381
 [#2378]: https://github.com/import-js/eslint-plugin-import/pull/2378
 [#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index efc2169946..5feb319036 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -273,8 +273,10 @@ const prepareImportsAndExports = (srcFiles, context) => {
   exportAll.forEach((value, key) => {
     value.forEach(val => {
       const currentExports = exportList.get(val);
-      const currentExport = currentExports.get(EXPORT_ALL_DECLARATION);
-      currentExport.whereUsed.add(key);
+      if (currentExports) {
+        const currentExport = currentExports.get(EXPORT_ALL_DECLARATION);
+        currentExport.whereUsed.add(key);
+      }
     });
   });
 };
diff --git a/tests/files/unused-modules-reexport-crash/src/App.tsx b/tests/files/unused-modules-reexport-crash/src/App.tsx
new file mode 100644
index 0000000000..c797a976cb
--- /dev/null
+++ b/tests/files/unused-modules-reexport-crash/src/App.tsx
@@ -0,0 +1,5 @@
+import { hello } from './magic/test'
+
+hello();
+
+export default function App() {};
diff --git a/tests/files/unused-modules-reexport-crash/src/index.tsx b/tests/files/unused-modules-reexport-crash/src/index.tsx
new file mode 100644
index 0000000000..124b1745d2
--- /dev/null
+++ b/tests/files/unused-modules-reexport-crash/src/index.tsx
@@ -0,0 +1,3 @@
+import App from './App';
+
+export const x = App
\ No newline at end of file
diff --git a/tests/files/unused-modules-reexport-crash/src/magic/index.js b/tests/files/unused-modules-reexport-crash/src/magic/index.js
new file mode 100644
index 0000000000..ac3f46bb1b
--- /dev/null
+++ b/tests/files/unused-modules-reexport-crash/src/magic/index.js
@@ -0,0 +1 @@
+export * from './test'
diff --git a/tests/files/unused-modules-reexport-crash/src/magic/test.js b/tests/files/unused-modules-reexport-crash/src/magic/test.js
new file mode 100644
index 0000000000..a6d74afd9b
--- /dev/null
+++ b/tests/files/unused-modules-reexport-crash/src/magic/test.js
@@ -0,0 +1,7 @@
+export function hello() {
+	console.log('hello!!');
+}
+
+export function unused() {
+	console.log('im unused!!');
+}
\ No newline at end of file
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index aa0e123c2b..38db2ef43d 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -105,7 +105,7 @@ ruleTester.run('no-unused-modules', rule, {
 });
 
 
-// tests for  exports
+// tests for exports
 ruleTester.run('no-unused-modules', rule, {
   valid: [
     test({
@@ -301,6 +301,17 @@ describe('dynamic imports', () => {
         parser: parsers.TS_NEW,
         filename: testFilePath('./no-unused-modules/typescript/exports-for-dynamic-ts.ts'),
       }),
+      test({
+        code: `
+        import App from './App';
+      `,
+        filename: testFilePath('./unused-modules-reexport-crash/src/index.tsx'),
+        parser: parsers.TS_NEW,
+        options: [{        
+          unusedExports: true,
+          ignoreExports: ['**/magic/**'],
+        }],
+      }),
     ],
     invalid: [
     ],

From 21304bdf0124be1db8e6b152b072661b50fa931c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 13 Mar 2022 13:52:48 -0700
Subject: [PATCH 466/767] [Deps] update `tsconfig-paths`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 9a55575143..186c5cb57e 100644
--- a/package.json
+++ b/package.json
@@ -111,6 +111,6 @@
     "minimatch": "^3.1.2",
     "object.values": "^1.1.5",
     "resolve": "^1.22.0",
-    "tsconfig-paths": "^3.12.0"
+    "tsconfig-paths": "^3.13.0"
   }
 }

From 98bbb2cb30f90eaba91ff29bf1c1a21553886302 Mon Sep 17 00:00:00 2001
From: Seyyed MohammadMahdi Zamanian
 <76493524+MM25Zamanian@users.noreply.github.com>
Date: Wed, 23 Mar 2022 02:23:33 +0430
Subject: [PATCH 467/767] [Docs] `order`: TS code examples should use TS code
 blocks

---
 CHANGELOG.md        |  2 ++
 docs/rules/order.md | 32 ++++++++++++++++----------------
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 59ab25da95..7b97514f59 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] [`no-unresolved`]: Fix RegExp escaping in readme ([#2332], thanks [@stephtr])
 - [Refactor] `namespace`: try to improve performance ([#2340], thanks [@ljharb])
 - [Docs] make rule doc titles consistent ([#2393], thanks [@TheJaredWilcurt])
+- [Docs] `order`: TS code examples should use TS code blocks ([#2411], thanks [@MM25Zamanian])
 
 ## [2.25.4] - 2022-01-02
 
@@ -973,6 +974,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
 [#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
 [#2388]: https://github.com/import-js/eslint-plugin-import/pull/2388
 [#2381]: https://github.com/import-js/eslint-plugin-import/pull/2381
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 437467e244..f6e1ddbeb1 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -5,7 +5,7 @@ Enforce a convention in the order of `require()` / `import` statements.
 
 With the [`groups`](#groups-array) option set to `["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"]` the order is as shown in the following example:
 
-```js
+```ts
 // 1. node "builtin" modules
 import fs from 'fs';
 import path from 'path';
@@ -36,7 +36,7 @@ Statements using the ES6 `import` syntax must appear before any `require()` stat
 
 ## Fail
 
-```js
+```ts
 import _ from 'lodash';
 import path from 'path'; // `path` import should occur before import of `lodash`
 
@@ -54,7 +54,7 @@ import foo from './foo'; // `import` statements must be before `require` stateme
 
 ## Pass
 
-```js
+```ts
 import path from 'path';
 import _ from 'lodash';
 
@@ -85,7 +85,7 @@ This rule supports the following options:
 How groups are defined, and the order to respect. `groups` must be an array of `string` or [`string`]. The only allowed `string`s are:
 `"builtin"`, `"external"`, `"internal"`, `"unknown"`, `"parent"`, `"sibling"`, `"index"`, `"object"`, `"type"`.
 The enforced order is the same as the order of each element in a group. Omitted types are implicitly grouped together as the last element. Example:
-```js
+```ts
 [
   'builtin', // Built-in types are first
   ['sibling', 'parent'], // Then sibling and parent types. They can be mingled together
@@ -98,7 +98,7 @@ The default value is `["builtin", "external", "parent", "sibling", "index"]`.
 
 You can set the options like this:
 
-```js
+```ts
 "import/order": ["error", {"groups": ["index", "sibling", "parent", "internal", "external", "builtin", "object", "type"]}]
 ```
 
@@ -184,7 +184,7 @@ The default value is `"ignore"`.
 
 With the default group setting, the following will be invalid:
 
-```js
+```ts
 /* eslint import/order: ["error", {"newlines-between": "always"}] */
 import fs from 'fs';
 import path from 'path';
@@ -192,7 +192,7 @@ import index from './';
 import sibling from './foo';
 ```
 
-```js
+```ts
 /* eslint import/order: ["error", {"newlines-between": "always-and-inside-groups"}] */
 import fs from 'fs';
 
@@ -201,7 +201,7 @@ import index from './';
 import sibling from './foo';
 ```
 
-```js
+```ts
 /* eslint import/order: ["error", {"newlines-between": "never"}] */
 import fs from 'fs';
 import path from 'path';
@@ -213,7 +213,7 @@ import sibling from './foo';
 
 while those will be valid:
 
-```js
+```ts
 /* eslint import/order: ["error", {"newlines-between": "always"}] */
 import fs from 'fs';
 import path from 'path';
@@ -223,7 +223,7 @@ import index from './';
 import sibling from './foo';
 ```
 
-```js
+```ts
 /* eslint import/order: ["error", {"newlines-between": "always-and-inside-groups"}] */
 import fs from 'fs';
 
@@ -234,7 +234,7 @@ import index from './';
 import sibling from './foo';
 ```
 
-```js
+```ts
 /* eslint import/order: ["error", {"newlines-between": "never"}] */
 import fs from 'fs';
 import path from 'path';
@@ -250,7 +250,7 @@ Sort the order within each group in alphabetical manner based on **import path**
 - `caseInsensitive`: use `true` to ignore case, and `false` to consider case (default: `false`).
 
 Example setting:
-```js
+```ts
 alphabetize: {
   order: 'asc', /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */
   caseInsensitive: true /* ignore case. Options: [true, false] */
@@ -259,7 +259,7 @@ alphabetize: {
 
 This will fail the rule check:
 
-```js
+```ts
 /* eslint import/order: ["error", {"alphabetize": {"order": "asc", "caseInsensitive": true}}] */
 import React, { PureComponent } from 'react';
 import aTypes from 'prop-types';
@@ -270,7 +270,7 @@ import blist from 'BList';
 
 While this will pass:
 
-```js
+```ts
 /* eslint import/order: ["error", {"alphabetize": {"order": "asc", "caseInsensitive": true}}] */
 import blist from 'BList';
 import * as classnames from 'classnames';
@@ -290,7 +290,7 @@ way that is safe.
 
 This will fail the rule check:
 
-```js
+```ts
 /* eslint import/order: ["error", {"warnOnUnassignedImports": true}] */
 import fs from 'fs';
 import './styles.css';
@@ -299,7 +299,7 @@ import path from 'path';
 
 While this will pass:
 
-```js
+```ts
 /* eslint import/order: ["error", {"warnOnUnassignedImports": true}] */
 import fs from 'fs';
 import path from 'path';

From d8633c35ba7031eb49b2a36b27c82b289f8f85ce Mon Sep 17 00:00:00 2001
From: Kyle Holmberg <inbox@kylemh.com>
Date: Mon, 28 Mar 2022 21:16:42 -0600
Subject: [PATCH 468/767] [Docs] `no-unresolved`: fix link

---
 CHANGELOG.md                | 3 +++
 docs/rules/no-unresolved.md | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b97514f59..3a8963de1a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Refactor] `namespace`: try to improve performance ([#2340], thanks [@ljharb])
 - [Docs] make rule doc titles consistent ([#2393], thanks [@TheJaredWilcurt])
 - [Docs] `order`: TS code examples should use TS code blocks ([#2411], thanks [@MM25Zamanian])
+- [Docs] `no-unresolved`: fix link ([#2417], thanks [@kylemh])
 
 ## [2.25.4] - 2022-01-02
 
@@ -974,6 +975,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2417]: https://github.com/import-js/eslint-plugin-import/pull/2417
 [#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
 [#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
 [#2388]: https://github.com/import-js/eslint-plugin-import/pull/2388
@@ -1571,6 +1573,7 @@ for info on changes for earlier releases.
 [@kmui2]: https://github.com/kmui2
 [@knpwrs]: https://github.com/knpwrs
 [@KostyaZgara]: https://github.com/KostyaZgara
+[@kylemh]: https://github.com/kylemh
 [@laysent]: https://github.com/laysent
 [@le0nik]: https://github.com/le0nik
 [@lemonmade]: https://github.com/lemonmade
diff --git a/docs/rules/no-unresolved.md b/docs/rules/no-unresolved.md
index 1d18a3693a..08522deb4c 100644
--- a/docs/rules/no-unresolved.md
+++ b/docs/rules/no-unresolved.md
@@ -98,7 +98,7 @@ If you're using a module bundler other than Node or Webpack, you may end up with
 
 ## Further Reading
 
-- [Resolver plugins](../../README.md#resolver-plugins)
+- [Resolver plugins](../../README.md#resolvers)
 - [Node resolver](https://npmjs.com/package/eslint-import-resolver-node) (default)
 - [Webpack resolver](https://npmjs.com/package/eslint-import-resolver-webpack)
 - [`import/ignore`] global setting

From 0e80ee37cc5e4941c90b781f916b6676bb132da7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 5 Apr 2022 09:39:19 -0700
Subject: [PATCH 469/767] [Deps] update `tsconfig-paths`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 186c5cb57e..cfb2fb43ad 100644
--- a/package.json
+++ b/package.json
@@ -111,6 +111,6 @@
     "minimatch": "^3.1.2",
     "object.values": "^1.1.5",
     "resolve": "^1.22.0",
-    "tsconfig-paths": "^3.13.0"
+    "tsconfig-paths": "^3.14.1"
   }
 }

From d1602854ea9842082f48c51da869f3e3b70d1ef9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 5 Apr 2022 09:46:05 -0700
Subject: [PATCH 470/767] Bump to 2.26.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a8963de1a..18572d61a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.26.0] - 2022-04-05
+
 ### Added
 - [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
@@ -1378,7 +1380,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.4...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.26.0...HEAD
+[2.26.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.4...v2.26.0
 [2.25.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.3...v2.25.4
 [2.25.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.2...v2.25.3
 [2.25.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.1...v2.25.2
diff --git a/package.json b/package.json
index cfb2fb43ad..fcfa9b1efa 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.25.4",
+  "version": "2.26.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 517fcb768df62fe35208af07ded4a8f8dbce23b6 Mon Sep 17 00:00:00 2001
From: Michael Busby <michael.busby@helloagora.com>
Date: Thu, 7 Apr 2022 09:02:14 -0500
Subject: [PATCH 471/767] [Tests] `named`: Run all TypeScript tests; fix
 failing tests

---
 CHANGELOG.md                             |  5 +++
 tests/src/rules/named.js                 | 42 ++++++++++++++++--------
 tests/src/rules/no-unused-modules.js     |  4 +--
 tests/src/rules/prefer-default-export.js | 22 ++++++++-----
 tests/src/utils.js                       |  2 +-
 5 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 18572d61a3..db482f619f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Changed
+- [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
+
 ## [2.26.0] - 2022-04-05
 
 ### Added
@@ -977,6 +980,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
 [#2417]: https://github.com/import-js/eslint-plugin-import/pull/2417
 [#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
 [#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
@@ -1624,6 +1628,7 @@ for info on changes for earlier releases.
 [@Pessimistress]: https://github.com/Pessimistress
 [@pmcelhaney]: https://github.com/pmcelhaney
 [@preco21]: https://github.com/preco21
+[@ProdigySim]: https://github.com/ProdigySim
 [@pzhine]: https://github.com/pzhine
 [@ramasilveyra]: https://github.com/ramasilveyra
 [@randallreedjr]: https://github.com/randallreedjr
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index b5500a6d31..0361983979 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -388,14 +388,18 @@ context('TypeScript', function () {
       'import/resolver': { 'eslint-import-resolver-typescript': true },
     };
 
-    const valid = [];
+    let valid = [];
     const invalid = [
-      test({
-        code: `import {a} from './export-star-3/b';`,
-        filename: testFilePath('./export-star-3/a.js'),
-        parser,
-        settings,
-      }),
+      // TODO: uncomment this test
+      // test({
+      //   code: `import {a} from './export-star-3/b';`,
+      //   filename: testFilePath('./export-star-3/a.js'),
+      //   parser,
+      //   settings,
+      //   errors: [
+      //     { message: 'a not found in ./export-star-3/b' },
+      //   ],
+      // }),
     ];
 
     [
@@ -404,7 +408,7 @@ context('TypeScript', function () {
       'typescript-export-assign-namespace',
       'typescript-export-assign-namespace-merged',
     ].forEach((source) => {
-      valid.push(
+      valid = valid.concat(
         test({
           code: `import { MyType } from "./${source}"`,
           parser,
@@ -420,11 +424,18 @@ context('TypeScript', function () {
           parser,
           settings,
         }),
-        test({
-          code: `import { getFoo } from "./${source}"`,
-          parser,
-          settings,
-        }),
+        (source === 'typescript-declare'
+          ? testVersion('> 5', () => ({
+            code: `import { getFoo } from "./${source}"`,
+            parser,
+            settings,
+          }))
+          : test({
+            code: `import { getFoo } from "./${source}"`,
+            parser,
+            settings,
+          })
+        ),
         test({
           code: `import { MyEnum } from "./${source}"`,
           parser,
@@ -469,5 +480,10 @@ context('TypeScript', function () {
         }),
       );
     });
+
+    ruleTester.run(`named [TypeScript]`, rule, {
+      valid,
+      invalid,
+    });
   });
 });
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 38db2ef43d..485400ece2 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -7,8 +7,8 @@ import fs from 'fs';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
-// TODO: figure out why these tests fail in eslint 4
-const isESLint4TODO = semver.satisfies(eslintPkg.version, '^4');
+// TODO: figure out why these tests fail in eslint 4 and 5
+const isESLint4TODO = semver.satisfies(eslintPkg.version, '^4 || ^5');
 
 const ruleTester = new RuleTester();
 const typescriptRuleTester = new RuleTester(typescriptConfig);
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 6a36f08bbf..6ecd2e3afd 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -170,26 +170,30 @@ context('TypeScript', function () {
         // Exporting types
         semver.satisfies(tsEslintVersion, '>= 22') ? test({
           code: `
-          export type foo = string;
-          export type bar = number;`,
+            export type foo = string;
+            export type bar = number;
+            /* ${parser.replace(process.cwd(), '$$PWD')} */
+          `,
           ...parserConfig,
         }) : [],
         test({
           code: `
-          export type foo = string;
-          export type bar = number;`,
+            export type foo = string;
+            export type bar = number;
+            /* ${parser.replace(process.cwd(), '$$PWD')} */
+          `,
           ...parserConfig,
         }),
         semver.satisfies(tsEslintVersion, '>= 22') ? test({
-          code: 'export type foo = string',
+          code: 'export type foo = string /* ' + parser.replace(process.cwd(), '$$PWD') + '*/',
           ...parserConfig,
         }) : [],
-        test({
-          code: 'export interface foo { bar: string; }',
+        semver.satisfies(tsEslintVersion, '> 20') ? test({
+          code: 'export interface foo { bar: string; } /* ' + parser.replace(process.cwd(), '$$PWD') + '*/',
           ...parserConfig,
-        }),
+        }) : [],
         test({
-          code: 'export interface foo { bar: string; }; export function goo() {}',
+          code: 'export interface foo { bar: string; }; export function goo() {} /* ' + parser.replace(process.cwd(), '$$PWD') + '*/',
           ...parserConfig,
         }),
       ),
diff --git a/tests/src/utils.js b/tests/src/utils.js
index b66ecf9c66..ed04aa9678 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -8,7 +8,7 @@ import 'babel-eslint';
 export const parsers = {
   ESPREE: require.resolve('espree'),
   TS_OLD: semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0') && require.resolve('typescript-eslint-parser'),
-  TS_NEW: semver.satisfies(eslintPkg.version, '>5.0.0') && require.resolve('@typescript-eslint/parser'),
+  TS_NEW: semver.satisfies(eslintPkg.version, '> 5') && require.resolve('@typescript-eslint/parser'),
   BABEL_OLD: require.resolve('babel-eslint'),
 };
 

From a49e72a84fb48267efc3cf230a8194aab7003bff Mon Sep 17 00:00:00 2001
From: Michael Busby <michael.busby@helloagora.com>
Date: Thu, 7 Apr 2022 08:32:52 -0500
Subject: [PATCH 472/767] [Tests] `named`: Add direct test for `export =`
 assignment in TS

---
 .../files/typescript-export-assign-object.ts  |  5 +++++
 tests/src/rules/named.js                      | 19 +++++++++++++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 tests/files/typescript-export-assign-object.ts

diff --git a/tests/files/typescript-export-assign-object.ts b/tests/files/typescript-export-assign-object.ts
new file mode 100644
index 0000000000..8899e3fbad
--- /dev/null
+++ b/tests/files/typescript-export-assign-object.ts
@@ -0,0 +1,5 @@
+const someObj = {
+  FooBar: 12,
+};
+
+export = someObj;
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 0361983979..4194ce266c 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -388,7 +388,13 @@ context('TypeScript', function () {
       'import/resolver': { 'eslint-import-resolver-typescript': true },
     };
 
-    let valid = [];
+    let valid = [
+      test({
+        code: `import { FooBar } from './typescript-export-assign-object'`,
+        parser,
+        settings,
+      }),
+    ];
     const invalid = [
       // TODO: uncomment this test
       // test({
@@ -400,8 +406,17 @@ context('TypeScript', function () {
       //     { message: 'a not found in ./export-star-3/b' },
       //   ],
       // }),
+      test({
+        code: `import { NotExported } from './typescript-export-assign-object'`,
+        parser,
+        settings,
+        errors: [{
+          message: `NotExported not found in './typescript-export-assign-object'`,
+          type: 'Identifier',
+        }],
+      }),
     ];
-
+    
     [
       'typescript',
       'typescript-declare',

From ec7e463e14d730c96c87c17fb576a647932a31e6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 11 Apr 2022 23:33:18 -0700
Subject: [PATCH 473/767] Revert "[Tests] `named`: Add direct test for `export
 =` assignment in TS"

This reverts commit a49e72a84fb48267efc3cf230a8194aab7003bff.
---
 .../files/typescript-export-assign-object.ts  |  5 -----
 tests/src/rules/named.js                      | 19 ++-----------------
 2 files changed, 2 insertions(+), 22 deletions(-)
 delete mode 100644 tests/files/typescript-export-assign-object.ts

diff --git a/tests/files/typescript-export-assign-object.ts b/tests/files/typescript-export-assign-object.ts
deleted file mode 100644
index 8899e3fbad..0000000000
--- a/tests/files/typescript-export-assign-object.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-const someObj = {
-  FooBar: 12,
-};
-
-export = someObj;
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 4194ce266c..0361983979 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -388,13 +388,7 @@ context('TypeScript', function () {
       'import/resolver': { 'eslint-import-resolver-typescript': true },
     };
 
-    let valid = [
-      test({
-        code: `import { FooBar } from './typescript-export-assign-object'`,
-        parser,
-        settings,
-      }),
-    ];
+    let valid = [];
     const invalid = [
       // TODO: uncomment this test
       // test({
@@ -406,17 +400,8 @@ context('TypeScript', function () {
       //     { message: 'a not found in ./export-star-3/b' },
       //   ],
       // }),
-      test({
-        code: `import { NotExported } from './typescript-export-assign-object'`,
-        parser,
-        settings,
-        errors: [{
-          message: `NotExported not found in './typescript-export-assign-object'`,
-          type: 'Identifier',
-        }],
-      }),
     ];
-    
+
     [
       'typescript',
       'typescript-declare',

From 995c12c80016e9d2cc5b3026884c34b5d4b1ad13 Mon Sep 17 00:00:00 2001
From: pri1311 <nagdapriya13@gmail.com>
Date: Tue, 8 Mar 2022 17:19:58 +0530
Subject: [PATCH 474/767] [New] `newline-after-import`: add `considerComments`
 option

---
 CHANGELOG.md                            |   5 +
 docs/rules/newline-after-import.md      |  29 ++++-
 src/rules/newline-after-import.js       |  42 +++++++-
 tests/src/rules/newline-after-import.js | 136 ++++++++++++++++++++++++
 4 files changed, 207 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index db482f619f..89e7f66e80 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Added
+- [`newline-after-import`]: add `considerComments` option ([#2399], thanks [@pri1311])
+
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
 
@@ -983,6 +986,7 @@ for info on changes for earlier releases.
 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
 [#2417]: https://github.com/import-js/eslint-plugin-import/pull/2417
 [#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
+[#2399]: https://github.com/import-js/eslint-plugin-import/pull/2399
 [#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
 [#2388]: https://github.com/import-js/eslint-plugin-import/pull/2388
 [#2381]: https://github.com/import-js/eslint-plugin-import/pull/2381
@@ -1628,6 +1632,7 @@ for info on changes for earlier releases.
 [@Pessimistress]: https://github.com/Pessimistress
 [@pmcelhaney]: https://github.com/pmcelhaney
 [@preco21]: https://github.com/preco21
+[@pri1311]: https://github.com/pri1311
 [@ProdigySim]: https://github.com/ProdigySim
 [@pzhine]: https://github.com/pzhine
 [@ramasilveyra]: https://github.com/ramasilveyra
diff --git a/docs/rules/newline-after-import.md b/docs/rules/newline-after-import.md
index 4883776c92..ab454e4bdc 100644
--- a/docs/rules/newline-after-import.md
+++ b/docs/rules/newline-after-import.md
@@ -5,7 +5,10 @@ Enforces having one or more empty lines after the last top-level import statemen
 
 ## Rule Details
 
-This rule has one option, `count` which sets the number of newlines that are enforced after the last top-level import statement or require call. This option defaults to `1`.
+This rule supports the following options: 
+- `count` which sets the number of newlines that are enforced after the last top-level import statement or require call. This option defaults to `1`.
+
+- `considerComments` which enforces the rule on comments after the last import-statement as well when set to true. This option defaults to `false`.
 
 Valid:
 
@@ -71,6 +74,30 @@ import defaultExport from './foo'
 const FOO = 'BAR'
 ```
 
+With `considerComments` set to `false` this will be considered valid:
+
+```js
+import defaultExport from './foo'
+// some comment here.
+const FOO = 'BAR'
+```
+
+With `considerComments` set to `true` this will be considered valid:
+
+```js
+import defaultExport from './foo'
+
+// some comment here.
+const FOO = 'BAR'
+```
+
+With `considerComments` set to `true` this will be considered invalid:
+
+```js
+import defaultExport from './foo'
+// some comment here.
+const FOO = 'BAR'
+```
 
 ## Example options usage
 ```json
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index a3e0a11e19..3f285345f9 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -67,6 +67,7 @@ module.exports = {
             'type': 'integer',
             'minimum': 1,
           },
+          'considerComments': { 'type': 'boolean' },
         },
         'additionalProperties': false,
       },
@@ -75,6 +76,7 @@ module.exports = {
   create(context) {
     let level = 0;
     const requireCalls = [];
+    const options = Object.assign({ count: 1, considerComments: false }, context.options[0]);
 
     function checkForNewLine(node, nextNode, type) {
       if (isExportDefaultClass(nextNode) || isExportNameClass(nextNode)) {
@@ -87,7 +89,6 @@ module.exports = {
         nextNode = nextNode.decorators[0];
       }
 
-      const options = context.options[0] || { count: 1 };
       const lineDifference = getLineDifference(node, nextNode);
       const EXPECTED_LINE_DIFFERENCE = options.count + 1;
 
@@ -103,8 +104,32 @@ module.exports = {
             line: node.loc.end.line,
             column,
           },
-          message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} \
-after ${type} statement not followed by another ${type}.`,
+          message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} after ${type} statement not followed by another ${type}.`,
+          fix: fixer => fixer.insertTextAfter(
+            node,
+            '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference),
+          ),
+        });
+      }
+    }
+
+    function commentAfterImport(node, nextComment) {
+      const lineDifference = getLineDifference(node, nextComment);
+      const EXPECTED_LINE_DIFFERENCE = options.count + 1;
+
+      if (lineDifference < EXPECTED_LINE_DIFFERENCE) {
+        let column = node.loc.start.column;
+
+        if (node.loc.start.line !== node.loc.end.line) {
+          column = 0;
+        }
+
+        context.report({
+          loc: {
+            line: node.loc.end.line,
+            column,
+          },
+          message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} after import statement not followed by another import.`,
           fix: fixer => fixer.insertTextAfter(
             node,
             '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference),
@@ -124,13 +149,22 @@ after ${type} statement not followed by another ${type}.`,
       const { parent } = node;
       const nodePosition = parent.body.indexOf(node);
       const nextNode = parent.body[nodePosition + 1];
+      const endLine = node.loc.end.line;
+      let nextComment;
+
+      if (typeof parent.comments !== 'undefined' && options.considerComments) {
+        nextComment = parent.comments.find(o => o.loc.start.line === endLine + 1);
+      }
+
 
       // skip "export import"s
       if (node.type === 'TSImportEqualsDeclaration' && node.isExport) {
         return;
       }
 
-      if (nextNode && nextNode.type !== 'ImportDeclaration' && (nextNode.type !== 'TSImportEqualsDeclaration' || nextNode.isExport)) {
+      if (nextComment && typeof nextComment !== 'undefined') {
+        commentAfterImport(node, nextComment);
+      } else if (nextNode && nextNode.type !== 'ImportDeclaration' && (nextNode.type !== 'TSImportEqualsDeclaration' || nextNode.isExport)) {
         checkForNewLine(node, nextNode, 'import');
       }
     }
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 80cc076ced..bf91064f85 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -24,10 +24,41 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
             , y = () => require('bar')`,
       parserOptions: { ecmaVersion: 6 } ,
     },
+    {
+      code: `
+        const x = () => require('baz')
+            , y = () => require('bar')
+            
+        // some comment here
+      `,
+      parserOptions: { ecmaVersion: 6 } ,
+      options: [{ considerComments: true }],
+    },
     {
       code: `const x = () => require('baz') && require('bar')`,
       parserOptions: { ecmaVersion: 6 } ,
     },
+    {
+      code: `
+        const x = () => require('baz') && require('bar')
+
+        // Some random single line comment
+        var bar = 42;
+      `,
+      parserOptions: { ecmaVersion: 6 } ,
+      options: [{ 'considerComments': true }],
+    },
+    {
+      code: `
+        const x = () => require('baz') && require('bar')
+        /**
+         * some multiline comment here
+         * another line of comment
+        **/
+        var bar = 42;
+      `,
+      parserOptions: { ecmaVersion: 6 } ,
+    },
     `function x() { require('baz'); }`,
     `a(require('b'), require('c'), require('d'));`,
     `function foo() {
@@ -255,9 +286,114 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       `,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
+    {
+      code: `
+        import path from 'path';
+        import foo from 'foo';
+        /**
+         * some multiline comment here
+         * another line of comment
+        **/
+        var bar = 42;
+      `,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
+    },
+    {
+      code: `
+        import path from 'path';import foo from 'foo';
+        
+        /**
+         * some multiline comment here
+         * another line of comment
+        **/
+        var bar = 42;
+      `,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
+      options: [{ 'considerComments': true }],
+    },
+    {
+      code: `
+        import path from 'path';
+        import foo from 'foo';
+        
+        // Some random single line comment
+        var bar = 42;
+      `,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
+    },
   ),
 
   invalid: [].concat(
+    {
+      code: `
+        import { A, B, C, D } from
+        '../path/to/my/module/in/very/far/directory'
+        // some comment
+        var foo = 'bar';
+      `,
+      output: `
+        import { A, B, C, D } from
+        '../path/to/my/module/in/very/far/directory'
+
+        // some comment
+        var foo = 'bar';
+      `,
+      errors: [ {
+        line: 3,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE,
+      } ],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ 'considerComments': true }],
+    },
+    {
+      code: `
+        import path from 'path';
+        import foo from 'foo';
+        /**
+         * some multiline comment here
+         * another line of comment
+        **/
+        var bar = 42;
+      `,
+      output: `
+        import path from 'path';
+        import foo from 'foo';\n
+        /**
+         * some multiline comment here
+         * another line of comment
+        **/
+        var bar = 42;
+      `,
+      errors: [ {
+        line: 3,
+        column: 9,
+        message: IMPORT_ERROR_MESSAGE,
+      } ],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
+      options: [{ 'considerComments': true }],
+    },
+    {
+      code: `
+        import path from 'path';
+        import foo from 'foo';
+        // Some random single line comment
+        var bar = 42;
+      `,
+      output: `
+        import path from 'path';
+        import foo from 'foo';\n
+        // Some random single line comment
+        var bar = 42;
+      `,
+      errors: [ {
+        line: 3,
+        column: 9,
+        message: IMPORT_ERROR_MESSAGE,
+      } ],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
+      options: [{ 'considerComments': true, 'count': 1 }],
+    },
     {
       code: `import foo from 'foo';\nexport default function() {};`,
       output: `import foo from 'foo';\n\nexport default function() {};`,

From 347d78b678a772d5d04e56ff36c131e46d0423ef Mon Sep 17 00:00:00 2001
From: pri1311 <nagdapriya13@gmail.com>
Date: Thu, 3 Mar 2022 17:30:16 +0530
Subject: [PATCH 475/767] [Fix] `order`: move nested imports closer to main
 import entry

---
 CHANGELOG.md             |  4 +++
 src/rules/order.js       | 39 +++++++++++++++++++------
 tests/src/rules/order.js | 62 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 97 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89e7f66e80..17cbc2e3a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
 - [`newline-after-import`]: add `considerComments` option ([#2399], thanks [@pri1311])
 
+### Fixed
+- [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
+
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
 
@@ -987,6 +990,7 @@ for info on changes for earlier releases.
 [#2417]: https://github.com/import-js/eslint-plugin-import/pull/2417
 [#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
 [#2399]: https://github.com/import-js/eslint-plugin-import/pull/2399
+[#2396]: https://github.com/import-js/eslint-plugin-import/pull/2396
 [#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
 [#2388]: https://github.com/import-js/eslint-plugin-import/pull/2388
 [#2381]: https://github.com/import-js/eslint-plugin-import/pull/2381
diff --git a/src/rules/order.js b/src/rules/order.js
index fce979f090..df35db065c 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -1,6 +1,8 @@
 'use strict';
 
 import minimatch from 'minimatch';
+import includes from 'array-includes';
+
 import importType from '../core/importType';
 import isStaticRequire from '../core/staticRequire';
 import docsUrl from '../docsUrl';
@@ -244,16 +246,37 @@ function getSorter(ascending) {
   const multiplier = ascending ? 1 : -1;
 
   return function importsSorter(importA, importB) {
-    let result;
-
-    if (importA < importB) {
-      result = -1;
-    } else if (importA > importB) {
-      result = 1;
+    let result = 0;
+
+    if (!includes(importA, '/') && !includes(importB, '/')) {
+      if (importA < importB) {
+        result = -1;
+      } else if (importA > importB) {
+        result = 1;
+      } else {
+        result = 0;
+      }
     } else {
-      result = 0;
-    }
+      const A = importA.split('/');
+      const B = importB.split('/');
+      const a = A.length;
+      const b = B.length;
+
+      for (let i = 0; i < Math.min(a, b); i++) {
+        if (A[i] < B[i]) {
+          result = -1;
+          break;
+        } else if (A[i] > B[i]) {
+          result = 1;
+          break;
+        }
+      }
 
+      if (!result && a !== b) {
+        result = a < b ? -1 : 1;
+      }
+    }
+    
     return result * multiplier;
   };
 }
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index e552c9a853..f5c3bb393e 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -675,6 +675,47 @@ ruleTester.run('order', rule, {
         alphabetize: { order: 'desc' },
       }],
     }),
+    // Option alphabetize: {order: 'asc'} and move nested import entries closer to the main import entry
+    test({
+      code: `
+        import a from "foo";
+        import c from "foo/bar";
+        import d from "foo/barfoo";
+        import b from "foo-bar";
+      `,
+      options: [{ alphabetize: { order: 'asc' } }],
+    }),
+    // Option alphabetize: {order: 'asc'} and move nested import entries closer to the main import entry
+    test({
+      code: `
+        import a from "foo";
+        import c from "foo/foobar/bar";
+        import d from "foo/foobar/barfoo";
+        import b from "foo-bar";
+      `,
+      options: [{ alphabetize: { order: 'asc' } }],
+    }),
+    // Option alphabetize: {order: 'desc'} and move nested import entries closer to the main import entry
+    test({
+      code: `
+        import b from "foo-bar";
+        import d from "foo/barfoo";
+        import c from "foo/bar";
+        import a from "foo";
+      `,
+      options: [{ alphabetize: { order: 'desc' } }],
+    }),
+    // Option alphabetize: {order: 'desc'} and move nested import entries closer to the main import entry with file names having non-alphanumeric characters.
+    test({
+      code: `
+        import b from "foo-bar";
+        import c from "foo,bar";
+        import d from "foo/barfoo";
+        import a from "foo";`,
+      options: [{
+        alphabetize: { order: 'desc' },
+      }],
+    }),
     // Option alphabetize with newlines-between: {order: 'asc', newlines-between: 'always'}
     test({
       code: `
@@ -2230,6 +2271,27 @@ ruleTester.run('order', rule, {
         message: '`bar` import should occur before import of `Bar`',
       }],
     }),
+    // Option alphabetize: {order: 'asc'} and move nested import entries closer to the main import entry
+    test({
+      code: `
+        import a from "foo";
+        import b from "foo-bar";
+        import c from "foo/bar";
+        import d from "foo/barfoo";
+      `,
+      options: [{
+        alphabetize: { order: 'asc' },
+      }],
+      output: `
+        import a from "foo";
+        import c from "foo/bar";
+        import d from "foo/barfoo";
+        import b from "foo-bar";
+      `,
+      errors: [{
+        message: '`foo-bar` import should occur after import of `foo/barfoo`', 
+      }],
+    }),
     // Option alphabetize {order: 'asc': caseInsensitive: true}
     test({
       code: `

From db0970a6bbdfaa84f1e19f6cbb7d60647051546f Mon Sep 17 00:00:00 2001
From: Ben Watkins <ben.watkins@nelnet.net>
Date: Fri, 22 Apr 2022 13:50:14 -0700
Subject: [PATCH 476/767] [readme] note use of typescript in readme
 `import/extensions` section

---
 CHANGELOG.md | 3 +++
 README.md    | 5 ++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 17cbc2e3a6..042f7496ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
+- [readme] note use of typescript in readme `import/extensions` section ([#2440], thanks [@OutdatedVersion])
 
 ## [2.26.0] - 2022-04-05
 
@@ -986,6 +987,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
 [#2417]: https://github.com/import-js/eslint-plugin-import/pull/2417
 [#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
@@ -1629,6 +1631,7 @@ for info on changes for earlier releases.
 [@ntdb]: https://github.com/ntdb
 [@nwalters512]: https://github.com/nwalters512
 [@ombene]: https://github.com/ombene
+[@OutdatedVersion]: https://github.com/OutdatedVersion
 [@ota-meshi]: https://github.com/ota-meshi
 [@panrafal]: https://github.com/panrafal
 [@paztis]: https://github.com/paztis
diff --git a/README.md b/README.md
index 1d7b55ff51..8d38874b18 100644
--- a/README.md
+++ b/README.md
@@ -271,7 +271,10 @@ A list of file extensions that will be parsed as modules and inspected for
 `export`s.
 
 This defaults to `['.js']`, unless you are using the `react` shared config,
-in which case it is specified as `['.js', '.jsx']`.
+in which case it is specified as `['.js', '.jsx']`. Despite the default,
+if you are using TypeScript (without the `plugin:import/typescript` config
+described above) you must specify the new extensions (`.ts`, and also `.tsx`
+if using React).
 
 ```js
 "settings": {

From 8399ef4ed97df1f6edab374a15b9673374bc1543 Mon Sep 17 00:00:00 2001
From: Edwin Kofler <edwin@kofler.dev>
Date: Wed, 2 Mar 2022 13:56:28 -0800
Subject: [PATCH 477/767] [Docs] `order`: use correct default value

---
 CHANGELOG.md        | 3 +++
 docs/rules/order.md | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 042f7496ce..f140b1a0fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
 - [readme] note use of typescript in readme `import/extensions` section ([#2440], thanks [@OutdatedVersion])
+- [Docs] `order`: use correct default value ([#2392], thanks [@hyperupcall])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1280,6 +1281,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2392]: https://github.com/import-js/eslint-plugin-import/issues/2392
 [#2340]: https://github.com/import-js/eslint-plugin-import/issues/2340
 [#2255]: https://github.com/import-js/eslint-plugin-import/issues/2255
 [#2210]: https://github.com/import-js/eslint-plugin-import/issues/2210
@@ -1559,6 +1561,7 @@ for info on changes for earlier releases.
 [@hayes]: https://github.com/hayes
 [@himynameisdave]: https://github.com/himynameisdave
 [@hulkish]: https://github.com/hulkish
+[@hyperupcall]: https://github.com/hyperupcall
 [@Hypnosphi]: https://github.com/Hypnosphi
 [@isiahmeadows]: https://github.com/isiahmeadows
 [@IvanGoncharov]: https://github.com/IvanGoncharov
diff --git a/docs/rules/order.md b/docs/rules/order.md
index f6e1ddbeb1..8eead09359 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -169,7 +169,7 @@ Example:
   ]
 }
 ```
-The default value is `["builtin", "external"]`.
+The default value is `["builtin", "external", "object"]`.
 
 ### `newlines-between: [ignore|always|always-and-inside-groups|never]`:
 

From be30a349b9c28c24f712a81a9c5147a377126ba6 Mon Sep 17 00:00:00 2001
From: Bryan Lee <doslby@gmail.com>
Date: Thu, 28 Apr 2022 22:48:47 +0800
Subject: [PATCH 478/767] [meta] replace git.io link in comments with the
 original URL

Fixes #2443
---
 CHANGELOG.md                     | 2 ++
 tests/src/rules/no-unresolved.js | 2 +-
 utils/moduleVisitor.js           | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f140b1a0fa..cb455b4252 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
 - [readme] note use of typescript in readme `import/extensions` section ([#2440], thanks [@OutdatedVersion])
 - [Docs] `order`: use correct default value ([#2392], thanks [@hyperupcall])
+- [meta] replace git.io link in comments with the original URL ([#2444], thanks [@liby])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1281,6 +1282,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2444]: https://github.com/import-js/eslint-plugin-import/issues/2444
 [#2392]: https://github.com/import-js/eslint-plugin-import/issues/2392
 [#2340]: https://github.com/import-js/eslint-plugin-import/issues/2340
 [#2255]: https://github.com/import-js/eslint-plugin-import/issues/2255
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index c0252ad19d..198d46167d 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -67,7 +67,7 @@ function runResolverTests(resolver) {
         options: [{ amd: true }] }),
       rest({ code: 'require(["./does-not-exist"], function (bar) {})',
         options: [{ amd: false }] }),
-      // magic modules: https://git.io/vByan
+      // magic modules: https://github.com/requirejs/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#magic-modules
       rest({ code: 'define(["require", "exports", "module"], function (r, e, m) { })',
         options: [{ amd: true }] }),
 
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index ade475e2a9..4d93a0199b 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -81,7 +81,7 @@ exports.default = function visitModules(visitor, options) {
       if (typeof element.value !== 'string') continue;
 
       if (element.value === 'require' ||
-          element.value === 'exports') continue; // magic modules: https://git.io/vByan
+          element.value === 'exports') continue; // magic modules: https://github.com/requirejs/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#magic-modules
 
       checkSourceValue(element, element);
     }

From b2f6ac8eedac22a241f9d295bcdd4eef4e1c85cf Mon Sep 17 00:00:00 2001
From: GerkinDev <alexandre.j.p.germain@gmail.com>
Date: Mon, 21 Feb 2022 14:00:51 +0100
Subject: [PATCH 479/767] [New] `no-cycle`: add option to allow cycle via
 dynamic import

---
 CHANGELOG.md                                |  1 +
 docs/rules/no-cycle.md                      | 16 ++++
 src/ExportMap.js                            |  1 +
 src/rules/no-cycle.js                       | 18 +++++
 tests/files/cycles/es6/depth-one-dynamic.js |  1 +
 tests/src/rules/no-cycle.js                 | 87 ++++++++++++++++++---
 6 files changed, 114 insertions(+), 10 deletions(-)
 create mode 100644 tests/files/cycles/es6/depth-one-dynamic.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb455b4252..072911de60 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
 - [`no-relative-packages`]: add fixer ([#2381], thanks [@forivall])
+- [`no-cycle`]: add `allowUnsafeDynamicCyclicDependency` option ([#2387], thanks [@GerkinDev])
 
 ### Fixed
 - [`default`]: `typescript-eslint-parser`: avoid a crash on exporting as namespace (thanks [@ljharb])
diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md
index 7f1b4255a9..70b2ceb9b8 100644
--- a/docs/rules/no-cycle.md
+++ b/docs/rules/no-cycle.md
@@ -75,6 +75,22 @@ import { a } from './dep-a.js' // not reported as this module is external
 
 Its value is `false` by default, but can be set to `true` for reducing total project lint time, if needed.
 
+#### `allowUnsafeDynamicCyclicDependency`
+
+This option disable reporting of errors if a cycle is detected with at least one dynamic import.
+
+```js
+// bar.js
+import { foo } from './foo';
+export const bar = foo;
+
+// foo.js
+export const foo = 'Foo';
+export function getBar() { return import('./bar'); }
+```
+
+> Cyclic dependency are **always** a dangerous anti-pattern as discussed extensively in [#2265](https://github.com/import-js/eslint-plugin-import/issues/2265). Please be extra careful about using this option.
+
 ## When Not To Use It
 
 This rule is comparatively computationally expensive. If you are pressed for lint
diff --git a/src/ExportMap.js b/src/ExportMap.js
index d75c7ecd47..e18797a4d7 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -395,6 +395,7 @@ ExportMap.parse = function (path, content, context) {
           loc: source.loc,
         },
         importedSpecifiers,
+        dynamic: true,
       }]),
     });
   }
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index e61c3be26c..0aa3626827 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -33,6 +33,11 @@ module.exports = {
         type: 'boolean',
         default: false,
       },
+      allowUnsafeDynamicCyclicDependency: {
+        description: 'Allow cyclic dependency if there is at least one dynamic import in the chain',
+        type: 'boolean',
+        default: false,
+      },
     })],
   },
 
@@ -52,6 +57,13 @@ module.exports = {
       if (ignoreModule(sourceNode.value)) {
         return; // ignore external modules
       }
+      if (options.allowUnsafeDynamicCyclicDependency && (
+        // Ignore `import()`
+        importer.type === 'ImportExpression' ||
+        // `require()` calls are always checked (if possible)
+        (importer.type === 'CallExpression' && importer.callee.name !== 'require'))) {
+        return; // cycle via dynamic import allowed by config
+      }
 
       if (
         importer.type === 'ImportDeclaration' && (
@@ -89,6 +101,12 @@ module.exports = {
             // Ignore only type imports
             !isOnlyImportingTypes,
           );
+          
+          /*
+          If cyclic dependency is allowed via dynamic import, skip checking if any module is imported dynamically
+          */
+          if (options.allowUnsafeDynamicCyclicDependency && toTraverse.some(d => d.dynamic)) return;
+
           /*
           Only report as a cycle if there are any import declarations that are considered by
           the rule. For example:
diff --git a/tests/files/cycles/es6/depth-one-dynamic.js b/tests/files/cycles/es6/depth-one-dynamic.js
new file mode 100644
index 0000000000..32dd3db4ea
--- /dev/null
+++ b/tests/files/cycles/es6/depth-one-dynamic.js
@@ -0,0 +1 @@
+export const bar = () => import("../depth-zero").then(({foo}) => foo);
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 22e097dd2c..ad29292c23 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -1,4 +1,4 @@
-import { parsers, test as _test, testFilePath } from '../utils';
+import { parsers, test as _test, testFilePath, testVersion as _testVersion } from '../utils';
 
 import { RuleTester } from 'eslint';
 import flatMap from 'array.prototype.flatmap';
@@ -11,6 +11,9 @@ const error = message => ({ message });
 const test = def => _test(Object.assign(def, {
   filename: testFilePath('./cycles/depth-zero.js'),
 }));
+const testVersion = (specifier, t) => _testVersion(specifier, () => Object.assign(t(), {
+  filename: testFilePath('./cycles/depth-zero.js'),
+}));
 
 const testDialects = ['es6'];
 
@@ -73,7 +76,28 @@ ruleTester.run('no-cycle', rule, {
         code: `import type { FooType, BarType } from "./${testDialect}/depth-one"`,
         parser: parsers.BABEL_OLD,
       }),
-    ]),
+      test({
+        code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 1`,
+        options: [{ allowUnsafeDynamicCyclicDependency: true }],
+        parser: parsers.BABEL_OLD,
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 2`,
+        options: [{ allowUnsafeDynamicCyclicDependency: true }],
+        parser: parsers.BABEL_OLD,
+      }),
+    ].concat(parsers.TS_NEW ? [
+      test({
+        code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 3`,
+        options: [{ allowUnsafeDynamicCyclicDependency: true }],
+        parser: parsers.TS_NEW,
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 4`,
+        options: [{ allowUnsafeDynamicCyclicDependency: true }],
+        parser: parsers.TS_NEW,
+      }),
+    ] : [])),
 
     test({
       code: 'import { bar } from "./flow-types"',
@@ -112,62 +136,83 @@ ruleTester.run('no-cycle', rule, {
       },
     }),
 
-    flatMap(testDialects, (testDialect) => [
+    // Ensure behavior does not change for those tests, with or without `
+    flatMap(testDialects, (testDialect) => flatMap([
+      {},
+      { allowUnsafeDynamicCyclicDependency: true },
+    ], (opts) => [
       test({
         code: `import { foo } from "./${testDialect}/depth-one"`,
+        options: [{ ...opts }],
         errors: [error(`Dependency cycle detected.`)],
       }),
       test({
         code: `import { foo } from "./${testDialect}/depth-one"`,
-        options: [{ maxDepth: 1 }],
+        options: [{ ...opts, maxDepth: 1 }],
         errors: [error(`Dependency cycle detected.`)],
       }),
       test({
         code: `const { foo } = require("./${testDialect}/depth-one")`,
         errors: [error(`Dependency cycle detected.`)],
-        options: [{ commonjs: true }],
+        options: [{ ...opts, commonjs: true }],
       }),
       test({
         code: `require(["./${testDialect}/depth-one"], d1 => {})`,
         errors: [error(`Dependency cycle detected.`)],
-        options: [{ amd: true }],
+        options: [{ ...opts, amd: true }],
       }),
       test({
         code: `define(["./${testDialect}/depth-one"], d1 => {})`,
         errors: [error(`Dependency cycle detected.`)],
-        options: [{ amd: true }],
+        options: [{ ...opts, amd: true }],
       }),
       test({
         code: `import { foo } from "./${testDialect}/depth-two"`,
+        options: [{ ...opts }],
         errors: [error(`Dependency cycle via ./depth-one:1`)],
       }),
       test({
         code: `import { foo } from "./${testDialect}/depth-two"`,
-        options: [{ maxDepth: 2 }],
+        options: [{ ...opts, maxDepth: 2 }],
         errors: [error(`Dependency cycle via ./depth-one:1`)],
       }),
       test({
         code: `const { foo } = require("./${testDialect}/depth-two")`,
         errors: [error(`Dependency cycle via ./depth-one:1`)],
-        options: [{ commonjs: true }],
+        options: [{ ...opts, commonjs: true }],
       }),
       test({
         code: `import { two } from "./${testDialect}/depth-three-star"`,
+        options: [{ ...opts }],
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
       }),
       test({
         code: `import one, { two, three } from "./${testDialect}/depth-three-star"`,
+        options: [{ ...opts }],
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
       }),
       test({
         code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
+        options: [{ ...opts }],
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
       }),
       test({
         code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
+        options: [{ ...opts }],
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
         parser: parsers.BABEL_OLD,
       }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-two"`,
+        options: [{ ...opts, maxDepth: Infinity }],
+        errors: [error(`Dependency cycle via ./depth-one:1`)],
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-two"`,
+        options: [{ ...opts, maxDepth: '∞' }],
+        errors: [error(`Dependency cycle via ./depth-one:1`)],
+      }),
+    ]).concat([
       test({
         code: `import("./${testDialect}/depth-three-star")`,
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
@@ -188,7 +233,29 @@ ruleTester.run('no-cycle', rule, {
         options: [{ maxDepth: '∞' }],
         errors: [error(`Dependency cycle via ./depth-one:1`)],
       }),
-    ]),
+      test({
+        code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 5`,
+        errors: [error(`Dependency cycle detected.`)],
+        parser: parsers.BABEL_OLD,
+      }),
+    ]).concat(
+      testVersion('> 3', () => ({ // Dynamic import is not properly caracterized with eslint < 4
+        code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 6`,
+        errors: [error(`Dependency cycle detected.`)],
+        parser: parsers.BABEL_OLD,
+      })),
+    ).concat(parsers.TS_NEW ? [
+      test({
+        code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 7`,
+        errors: [error(`Dependency cycle detected.`)],
+        parser: parsers.TS_NEW,
+      }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 8`,
+        errors: [error(`Dependency cycle detected.`)],
+        parser: parsers.TS_NEW,
+      }),
+    ] : [])),
 
     test({
       code: 'import { bar } from "./flow-types-depth-one"',

From 72e0eb6ccdd08e39de8e2dc3129f841f2c2a286d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 9 May 2022 10:47:51 -0700
Subject: [PATCH 480/767] [meta] fix mistaken changelog entry per
 https://github.com/import-js/eslint-plugin-import/pull/2387#issuecomment-1121334139

---
 CHANGELOG.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 072911de60..63b33fe917 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Added
 - [`newline-after-import`]: add `considerComments` option ([#2399], thanks [@pri1311])
+- [`no-cycle`]: add `allowUnsafeDynamicCyclicDependency` option ([#2387], thanks [@GerkinDev])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -24,7 +25,6 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
 - [`no-relative-packages`]: add fixer ([#2381], thanks [@forivall])
-- [`no-cycle`]: add `allowUnsafeDynamicCyclicDependency` option ([#2387], thanks [@GerkinDev])
 
 ### Fixed
 - [`default`]: `typescript-eslint-parser`: avoid a crash on exporting as namespace (thanks [@ljharb])
@@ -998,6 +998,7 @@ for info on changes for earlier releases.
 [#2396]: https://github.com/import-js/eslint-plugin-import/pull/2396
 [#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
 [#2388]: https://github.com/import-js/eslint-plugin-import/pull/2388
+[#2387]: https://github.com/import-js/eslint-plugin-import/pull/2387
 [#2381]: https://github.com/import-js/eslint-plugin-import/pull/2381
 [#2378]: https://github.com/import-js/eslint-plugin-import/pull/2378
 [#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371

From 1c62e3c4dbe1205c6f745a1c7b7bd93c538cd157 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 9 May 2022 10:49:36 -0700
Subject: [PATCH 481/767] [Dev Deps] update `@angular-eslint/template-parser`,
 `array.prototype.flatmap`

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index fcfa9b1efa..3a4307965c 100644
--- a/package.json
+++ b/package.json
@@ -53,11 +53,11 @@
   },
   "homepage": "https://github.com/import-js/eslint-plugin-import",
   "devDependencies": {
-    "@angular-eslint/template-parser": "^13.1.0",
+    "@angular-eslint/template-parser": "^13.2.1",
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3 || ^5.10.0",
-    "array.prototype.flatmap": "^1.2.5",
+    "array.prototype.flatmap": "^1.3.0",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
     "babel-eslint": "=8.0.3 || ^8.2.6",

From 376747914b47fbdcf99212b9e9bd4d5e09825385 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 9 May 2022 10:50:35 -0700
Subject: [PATCH 482/767] [Deps] update `array-includes`,
 `array.prototype.flat`, `is-core-module`

---
 package.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 3a4307965c..023d481126 100644
--- a/package.json
+++ b/package.json
@@ -99,14 +99,14 @@
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
   },
   "dependencies": {
-    "array-includes": "^3.1.4",
-    "array.prototype.flat": "^1.2.5",
+    "array-includes": "^3.1.5",
+    "array.prototype.flat": "^1.3.0",
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
     "eslint-module-utils": "^2.7.3",
     "has": "^1.0.3",
-    "is-core-module": "^2.8.1",
+    "is-core-module": "^2.9.0",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.values": "^1.1.5",

From a74c17a77c82567998cd05837e83659075e63081 Mon Sep 17 00:00:00 2001
From: AdriAt360 <adrien.marion@360learning.com>
Date: Wed, 1 Jun 2022 17:47:39 +0200
Subject: [PATCH 483/767] [Fix] `no-restricted-paths`: fix an error message

---
 CHANGELOG.md                           | 3 +++
 src/rules/no-restricted-paths.js       | 2 +-
 tests/src/rules/no-restricted-paths.js | 2 +-
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63b33fe917..fcb9f37cce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
+- [`no-restricted-paths`]: fix an error message ([#2466], thanks [@AdriAt360])
 
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -990,6 +991,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
 [#2417]: https://github.com/import-js/eslint-plugin-import/pull/2417
@@ -1493,6 +1495,7 @@ for info on changes for earlier releases.
 [@aberezkin]: https://github.com/aberezkin
 [@adamborowski]: https://github.com/adamborowski
 [@adjerbetian]: https://github.com/adjerbetian
+[@AdriAt360]: https://github.com/AdriAt360
 [@ai]: https://github.com/ai
 [@aladdin-add]: https://github.com/aladdin-add
 [@alex-page]: https://github.com/alex-page
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index e5bc6bc850..e869564f1f 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -81,7 +81,7 @@ module.exports = {
     function reportInvalidExceptionGlob(node) {
       context.report({
         node,
-        message: 'Restricted path exceptions must be glob patterns when`from` is a glob pattern',
+        message: 'Restricted path exceptions must be glob patterns when `from` is a glob pattern',
       });
     }
 
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index 11934599ee..e38a79300b 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -255,7 +255,7 @@ ruleTester.run('no-restricted-paths', rule, {
         } ],
       } ],
       errors: [ {
-        message: 'Restricted path exceptions must be glob patterns when`from` is a glob pattern',
+        message: 'Restricted path exceptions must be glob patterns when `from` is a glob pattern',
         line: 1,
         column: 15,
       } ],

From 7378a5e80851dea748c697376d48834f88fcfc5f Mon Sep 17 00:00:00 2001
From: AdriAt360 <adrien.marion@360learning.com>
Date: Wed, 1 Jun 2022 17:18:06 +0200
Subject: [PATCH 484/767] [New] `no-restricted-paths`: support arrays for
 `from` and `target` options

---
 CHANGELOG.md                                  |   1 +
 docs/rules/no-restricted-paths.md             |  80 +-
 src/rules/no-restricted-paths.js              | 181 +++--
 tests/files/restricted-paths/client/one/a.js  |   0
 .../files/restricted-paths/server/three/a.js  |   0
 tests/src/rules/no-restricted-paths.js        | 762 ++++++++++++++----
 6 files changed, 804 insertions(+), 220 deletions(-)
 create mode 100644 tests/files/restricted-paths/client/one/a.js
 create mode 100644 tests/files/restricted-paths/server/three/a.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fcb9f37cce..f2f70fedfd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
 - [`newline-after-import`]: add `considerComments` option ([#2399], thanks [@pri1311])
 - [`no-cycle`]: add `allowUnsafeDynamicCyclicDependency` option ([#2387], thanks [@GerkinDev])
+- [`no-restricted-paths`]: support arrays for `from` and `target` options ([#2466], thanks [@AdriAt360])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
diff --git a/docs/rules/no-restricted-paths.md b/docs/rules/no-restricted-paths.md
index c9390754e3..d22a8b3ea3 100644
--- a/docs/rules/no-restricted-paths.md
+++ b/docs/rules/no-restricted-paths.md
@@ -10,16 +10,19 @@ In order to prevent such scenarios this rule allows you to define restricted zon
 This rule has one option. The option is an object containing the definition of all restricted `zones` and the optional `basePath` which is used to resolve relative paths within.
 The default value for `basePath` is the current working directory.
 
-Each zone consists of the `target` path, a `from` path, and an optional `except` and `message` attribute.
-- `target` is the path where the restricted imports should be applied. It can be expressed by
+Each zone consists of the `target` paths, a `from` paths, and an optional `except` and `message` attribute.
+- `target` contains the paths where the restricted imports should be applied. It can be expressed by
     - directory string path that matches all its containing files
     - glob pattern matching all the targeted files
-- `from` path defines the folder that is not allowed to be used in an import.  It can be expressed by
+    - an array of multiple of the two types above
+- `from` paths define the folders that are not allowed to be used in an import. It can be expressed by
     - directory string path that matches all its containing files
     - glob pattern matching all the files restricted to be imported
+    - an array of multiple directory string path
+    - an array of multiple glob patterns
 - `except` may be defined for a zone, allowing exception paths that would otherwise violate the related `from`. Note that it does not alter the behaviour of `target` in any way.
-    - in case `from` is a glob pattern, `except` must be an array of glob patterns as well
-    - in case `from` is a directory path, `except` is relative to `from` and cannot backtrack to a parent directory.
+    - in case `from` contains only glob patterns, `except` must be an array of glob patterns as well
+    - in case `from` contains only directory path, `except` is relative to `from` and cannot backtrack to a parent directory
 - `message` - will be displayed in case of the rule violation.
 
 ### Examples
@@ -124,3 +127,70 @@ The following import is not considered a problem in `my-project/client/sub-modul
 ```js
 import b from './baz'
 ```
+
+---------------
+
+Given the following folder structure:
+
+```
+my-project
+└── one
+   └── a.js
+   └── b.js
+└── two
+   └── a.js
+   └── b.js
+└── three
+   └── a.js
+   └── b.js
+```
+
+and the current configuration is set to:
+
+```
+{
+  "zones": [
+    {
+      "target": ["./tests/files/restricted-paths/two/*", "./tests/files/restricted-paths/three/*"],
+      "from": ["./tests/files/restricted-paths/one", "./tests/files/restricted-paths/three"],
+    }
+  ]
+}
+```
+
+The following patterns are not considered a problem in `my-project/one/b.js`:
+
+```js
+import a from '../three/a'
+```
+
+```js
+import a from './a'
+```
+
+The following pattern is not considered a problem in `my-project/two/b.js`:
+
+```js
+import a from './a'
+```
+
+The following patterns are considered a problem in `my-project/two/a.js`:
+
+```js
+import a from '../one/a'
+```
+
+```js
+import a from '../three/a'
+```
+
+The following patterns are considered a problem in `my-project/three/b.js`:
+
+```js
+import a from '../one/a'
+```
+
+```js
+import a from './a'
+```
+
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index e869564f1f..9d56949726 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -29,8 +29,28 @@ module.exports = {
             items: {
               type: 'object',
               properties: {
-                target: { type: 'string' },
-                from: { type: 'string' },
+                target: {
+                  oneOf: [
+                    { type: 'string' },
+                    {
+                      type: 'array',
+                      items: { type: 'string' },
+                      uniqueItems: true,
+                      minLength: 1,
+                    },
+                  ],
+                },
+                from: {
+                  oneOf: [
+                    { type: 'string' },
+                    {
+                      type: 'array',
+                      items: { type: 'string' },
+                      uniqueItems: true,
+                      minLength: 1,
+                    },
+                  ],
+                },
                 except: {
                   type: 'array',
                   items: {
@@ -56,14 +76,18 @@ module.exports = {
     const basePath = options.basePath || process.cwd();
     const currentFilename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
     const matchingZones = restrictedPaths.filter((zone) => {
-      const targetPath = path.resolve(basePath, zone.target);
+      return [].concat(zone.target)
+        .map(target => path.resolve(basePath, target))
+        .some(targetPath => isMatchingTargetPath(currentFilename, targetPath));
+    });
 
+    function isMatchingTargetPath(filename, targetPath) {
       if (isGlob(targetPath)) {
-        return minimatch(currentFilename, targetPath);
+        return minimatch(filename, targetPath);
       }
 
-      return containsPath(currentFilename, targetPath);
-    });
+      return containsPath(filename, targetPath);
+    }
 
     function isValidExceptionPath(absoluteFromPath, absoluteExceptionPath) {
       const relativeExceptionPath = path.relative(absoluteFromPath, absoluteExceptionPath);
@@ -71,6 +95,10 @@ module.exports = {
       return importType(relativeExceptionPath, context) !== 'parent';
     }
 
+    function areBothGlobPatternAndAbsolutePath(areGlobPatterns) {
+      return areGlobPatterns.some((isGlob) => isGlob) && areGlobPatterns.some((isGlob) => !isGlob);
+    }
+
     function reportInvalidExceptionPath(node) {
       context.report({
         node,
@@ -78,56 +106,108 @@ module.exports = {
       });
     }
 
+    function reportInvalidExceptionMixedGlobAndNonGlob(node) {
+      context.report({
+        node,
+        message: 'Restricted path `from` must contain either only glob patterns or none',
+      });
+    }
+
     function reportInvalidExceptionGlob(node) {
       context.report({
         node,
-        message: 'Restricted path exceptions must be glob patterns when `from` is a glob pattern',
+        message: 'Restricted path exceptions must be glob patterns when `from` contains glob patterns',
       });
     }
 
-    const makePathValidator = (zoneFrom, zoneExcept = []) => {
-      const absoluteFrom = path.resolve(basePath, zoneFrom);
-      const isGlobPattern = isGlob(zoneFrom);
-      let isPathRestricted;
-      let hasValidExceptions;
+    function computeMixedGlobAndAbsolutePathValidator() {
+      return {
+        isPathRestricted: () => true,
+        hasValidExceptions: false,
+        reportInvalidException: reportInvalidExceptionMixedGlobAndNonGlob,
+      };
+    }
+
+    function computeGlobPatternPathValidator(absoluteFrom, zoneExcept) {
       let isPathException;
-      let reportInvalidException;
 
-      if (isGlobPattern) {
-        const mm = new Minimatch(absoluteFrom);
-        isPathRestricted = (absoluteImportPath) => mm.match(absoluteImportPath);
+      const mm = new Minimatch(absoluteFrom);
+      const isPathRestricted = (absoluteImportPath) => mm.match(absoluteImportPath);
+      const hasValidExceptions = zoneExcept.every(isGlob);
 
-        hasValidExceptions = zoneExcept.every(isGlob);
+      if (hasValidExceptions) {
+        const exceptionsMm = zoneExcept.map((except) => new Minimatch(except));
+        isPathException = (absoluteImportPath) => exceptionsMm.some((mm) => mm.match(absoluteImportPath));
+      }
 
-        if (hasValidExceptions) {
-          const exceptionsMm = zoneExcept.map((except) => new Minimatch(except));
-          isPathException = (absoluteImportPath) => exceptionsMm.some((mm) => mm.match(absoluteImportPath));
-        }
+      const reportInvalidException = reportInvalidExceptionGlob;
+
+      return {
+        isPathRestricted,
+        hasValidExceptions,
+        isPathException,
+        reportInvalidException,
+      };
+    }
 
-        reportInvalidException = reportInvalidExceptionGlob;
-      } else {
-        isPathRestricted = (absoluteImportPath) => containsPath(absoluteImportPath, absoluteFrom);
+    function computeAbsolutePathValidator(absoluteFrom, zoneExcept) {
+      let isPathException;
 
-        const absoluteExceptionPaths = zoneExcept
-          .map((exceptionPath) => path.resolve(absoluteFrom, exceptionPath));
-        hasValidExceptions = absoluteExceptionPaths
-          .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
+      const isPathRestricted = (absoluteImportPath) => containsPath(absoluteImportPath, absoluteFrom);
 
-        if (hasValidExceptions) {
-          isPathException = (absoluteImportPath) => absoluteExceptionPaths.some(
-            (absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath),
-          );
-        }
+      const absoluteExceptionPaths = zoneExcept
+        .map((exceptionPath) => path.resolve(absoluteFrom, exceptionPath));
+      const hasValidExceptions = absoluteExceptionPaths
+        .every((absoluteExceptionPath) => isValidExceptionPath(absoluteFrom, absoluteExceptionPath));
 
-        reportInvalidException = reportInvalidExceptionPath;
+      if (hasValidExceptions) {
+        isPathException = (absoluteImportPath) => absoluteExceptionPaths.some(
+          (absoluteExceptionPath) => containsPath(absoluteImportPath, absoluteExceptionPath),
+        );
       }
 
+      const reportInvalidException = reportInvalidExceptionPath;
+
       return {
         isPathRestricted,
         hasValidExceptions,
         isPathException,
         reportInvalidException,
       };
+    }
+
+    function reportInvalidExceptions(validators, node) {
+      validators.forEach(validator => validator.reportInvalidException(node));
+    }
+
+    function reportImportsInRestrictedZone(validators, node, importPath, customMessage) {
+      validators.forEach(() => {
+        context.report({
+          node,
+          message: `Unexpected path "{{importPath}}" imported in restricted zone.${customMessage ? ` ${customMessage}` : ''}`,
+          data: { importPath },
+        });
+      });
+    }
+
+    const makePathValidators = (zoneFrom, zoneExcept = []) => {
+      const allZoneFrom = [].concat(zoneFrom);
+      const areGlobPatterns = allZoneFrom.map(isGlob);
+
+      if (areBothGlobPatternAndAbsolutePath(areGlobPatterns)) {
+        return [computeMixedGlobAndAbsolutePathValidator()];
+      }
+
+      const isGlobPattern = areGlobPatterns.every((isGlob) => isGlob);
+
+      return allZoneFrom.map(singleZoneFrom => {
+        const absoluteFrom = path.resolve(basePath, singleZoneFrom);
+
+        if (isGlobPattern) {
+          return computeGlobPatternPathValidator(absoluteFrom, zoneExcept);
+        }
+        return computeAbsolutePathValidator(absoluteFrom, zoneExcept);
+      });
     };
 
     const validators = [];
@@ -141,35 +221,18 @@ module.exports = {
 
       matchingZones.forEach((zone, index) => {
         if (!validators[index]) {
-          validators[index] = makePathValidator(zone.from, zone.except);
-        }
-
-        const {
-          isPathRestricted,
-          hasValidExceptions,
-          isPathException,
-          reportInvalidException,
-        } = validators[index];
-
-        if (!isPathRestricted(absoluteImportPath)) {
-          return;
+          validators[index] = makePathValidators(zone.from, zone.except);
         }
 
-        if (!hasValidExceptions) {
-          reportInvalidException(node);
-          return;
-        }
+        const applicableValidatorsForImportPath = validators[index].filter(validator => validator.isPathRestricted(absoluteImportPath));
 
-        const pathIsExcepted = isPathException(absoluteImportPath);
-        if (pathIsExcepted) {
-          return;
-        }
+        const validatorsWithInvalidExceptions = applicableValidatorsForImportPath.filter(validator => !validator.hasValidExceptions);
+        reportInvalidExceptions(validatorsWithInvalidExceptions, node);
 
-        context.report({
-          node,
-          message: `Unexpected path "{{importPath}}" imported in restricted zone.${zone.message ? ` ${zone.message}` : ''}`,
-          data: { importPath },
-        });
+        const applicableValidatorsForImportPathExcludingExceptions = applicableValidatorsForImportPath
+          .filter(validator => validator.hasValidExceptions)
+          .filter(validator => !validator.isPathException(absoluteImportPath));
+        reportImportsInRestrictedZone(applicableValidatorsForImportPathExcludingExceptions, node, importPath, zone.message);
       });
     }
 
diff --git a/tests/files/restricted-paths/client/one/a.js b/tests/files/restricted-paths/client/one/a.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/files/restricted-paths/server/three/a.js b/tests/files/restricted-paths/server/three/a.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index e38a79300b..d782a14472 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -6,88 +6,227 @@ import { test, testFilePath } from '../utils';
 const ruleTester = new RuleTester();
 
 ruleTester.run('no-restricted-paths', rule, {
-  valid: [
+  valid: [].concat(
     test({
       code: 'import a from "../client/a.js"',
       filename: testFilePath('./restricted-paths/server/b.js'),
-      options: [ {
-        zones: [ { target: './tests/files/restricted-paths/server', from: './tests/files/restricted-paths/other' } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server',
+              from: './tests/files/restricted-paths/other',
+            },
+          ],
+        },
+      ],
     }),
     test({
       code: 'import a from "../client/a.js"',
       filename: testFilePath('./restricted-paths/server/b.js'),
-      options: [ {
-        zones: [ { target: '**/*', from: './tests/files/restricted-paths/other' } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: '**/*',
+              from: './tests/files/restricted-paths/other',
+            },
+          ],
+        },
+      ],
     }),
     test({
       code: 'import a from "../client/a.js"',
       filename: testFilePath('./restricted-paths/client/b.js'),
-      options: [ {
-        zones: [ {
-          target: './tests/files/restricted-paths/!(client)/**/*',
-          from: './tests/files/restricted-paths/client/**/*',
-        } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/!(client)/**/*',
+              from: './tests/files/restricted-paths/client/**/*',
+            },
+          ],
+        },
+      ],
     }),
     test({
       code: 'const a = require("../client/a.js")',
       filename: testFilePath('./restricted-paths/server/b.js'),
-      options: [ {
-        zones: [ { target: './tests/files/restricted-paths/server', from: './tests/files/restricted-paths/other' } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server',
+              from: './tests/files/restricted-paths/other',
+            },
+          ],
+        },
+      ],
     }),
     test({
       code: 'import b from "../server/b.js"',
       filename: testFilePath('./restricted-paths/client/a.js'),
-      options: [ {
-        zones: [ { target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/other' } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client',
+              from: './tests/files/restricted-paths/other',
+            },
+          ],
+        },
+      ],
     }),
     test({
       code: 'import a from "./a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),
-      options: [ {
-        zones: [ {
-          target: './tests/files/restricted-paths/server/one',
-          from: './tests/files/restricted-paths/server',
-          except: ['./one'],
-        } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['./one'],
+            },
+          ],
+        },
+      ],
     }),
     test({
       code: 'import a from "../two/a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),
-      options: [ {
-        zones: [ {
-          target: './tests/files/restricted-paths/server/one',
-          from: './tests/files/restricted-paths/server',
-          except: ['./two'],
-        } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['./two'],
+            },
+          ],
+        },
+      ],
     }),
     test({
       code: 'import a from "../one/a.js"',
       filename: testFilePath('./restricted-paths/server/two-new/a.js'),
-      options: [ {
-        zones: [ {
-          target: './tests/files/restricted-paths/server/two',
-          from: './tests/files/restricted-paths/server',
-          except: [],
-        } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server/two',
+              from: './tests/files/restricted-paths/server',
+              except: [],
+            },
+          ],
+        },
+      ],
     }),
     test({
       code: 'import A from "../two/a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),
-      options: [ {
-        zones: [ {
-          target: '**/*',
-          from: './tests/files/restricted-paths/server/**/*',
-          except: ['**/a.js'],
-        } ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: '**/*',
+              from: './tests/files/restricted-paths/server/**/*',
+              except: ['**/a.js'],
+            },
+          ],
+        },
+      ],
+    }),
+
+    // support of arrays for from and target
+    // array with single element
+    test({
+      code: 'import a from "../client/a.js"',
+      filename: testFilePath('./restricted-paths/server/b.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: ['./tests/files/restricted-paths/server'],
+              from: './tests/files/restricted-paths/other',
+            },
+          ],
+        },
+      ],
+    }),
+    test({
+      code: 'import a from "../client/a.js"',
+      filename: testFilePath('./restricted-paths/server/b.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server',
+              from: ['./tests/files/restricted-paths/other'],
+            },
+          ],
+        },
+      ],
+    }),
+    // array with multiple elements
+    test({
+      code: 'import a from "../one/a.js"',
+      filename: testFilePath('./restricted-paths/server/two-new/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: ['./tests/files/restricted-paths/server/two', './tests/files/restricted-paths/server/three'],
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+    }),
+    test({
+      code: 'import a from "../one/a.js"',
+      filename: testFilePath('./restricted-paths/server/two-new/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server',
+              from: ['./tests/files/restricted-paths/server/two', './tests/files/restricted-paths/server/three'],
+              except: [],
+            },
+          ],
+        },
+      ],
+    }),
+    // array with multiple glob patterns in from
+    test({
+      code: 'import a from "../client/a.js"',
+      filename: testFilePath('./restricted-paths/client/b.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/!(client)/**/*',
+              from: ['./tests/files/restricted-paths/client/*', './tests/files/restricted-paths/client/one/*'],
+            },
+          ],
+        },
+      ],
+    }),
+    // array with mix of glob and non glob patterns in target
+    test({
+      code: 'import a from "../client/a.js"',
+      filename: testFilePath('./restricted-paths/client/b.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: ['./tests/files/restricted-paths/!(client)/**/*', './tests/files/restricted-paths/client/a/'],
+              from: './tests/files/restricted-paths/client/**/*',
+            },
+          ],
+        },
+      ],
     }),
 
     // irrelevant function calls
@@ -95,9 +234,17 @@ ruleTester.run('no-restricted-paths', rule, {
     test({
       code: 'notrequire("../server/b.js")',
       filename: testFilePath('./restricted-paths/client/a.js'),
-      options: [ {
-        zones: [ { target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/server' } ],
-      } ] }),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client',
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+    }),
 
     // no config
     test({ code: 'require("../server/b.js")' }),
@@ -105,42 +252,111 @@ ruleTester.run('no-restricted-paths', rule, {
 
     // builtin (ignore)
     test({ code: 'require("os")' }),
-  ],
+  ),
 
-  invalid: [
+  invalid: [].concat(
     test({
-      code: 'import b from "../server/b.js"',
+      code: 'import b from "../server/b.js"; // 1',
       filename: testFilePath('./restricted-paths/client/a.js'),
-      options: [ {
-        zones: [ { target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/server' } ],
-      } ],
-      errors: [ {
-        message: 'Unexpected path "../server/b.js" imported in restricted zone.',
-        line: 1,
-        column: 15,
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client',
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
     }),
     test({
-      code: 'import b from "../server/b.js"',
+      code: 'import b from "../server/b.js"; // 2',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client/**/*',
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    // TODO: fix test on windows
+    process.platform === 'win32' ? [] : test({
+      code: 'import b from "../server/b.js";',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client/*.js',
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    test({
+      code: 'import b from "../server/b.js"; // 2 ter',
       filename: testFilePath('./restricted-paths/client/a.js'),
-      options: [ {
-        zones: [ { target: './tests/files/restricted-paths/client/**/*', from: './tests/files/restricted-paths/server' } ],
-      } ],
-      errors: [ {
-        message: 'Unexpected path "../server/b.js" imported in restricted zone.',
-        line: 1,
-        column: 15,
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client/**',
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
     }),
     test({
       code: 'import a from "../client/a"\nimport c from "./c"',
       filename: testFilePath('./restricted-paths/server/b.js'),
-      options: [ {
-        zones: [
-          { target: './tests/files/restricted-paths/server', from: './tests/files/restricted-paths/client' },
-          { target: './tests/files/restricted-paths/server', from: './tests/files/restricted-paths/server/c.js' },
-        ],
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server',
+              from: './tests/files/restricted-paths/client',
+            },
+            {
+              target: './tests/files/restricted-paths/server',
+              from: './tests/files/restricted-paths/server/c.js',
+            },
+          ],
+        },
+      ],
       errors: [
         {
           message: 'Unexpected path "../client/a" imported in restricted zone.',
@@ -155,110 +371,344 @@ ruleTester.run('no-restricted-paths', rule, {
       ],
     }),
     test({
-      code: 'import b from "../server/b.js"',
+      code: 'import b from "../server/b.js"; // 3',
       filename: testFilePath('./restricted-paths/client/a.js'),
-      options: [ {
-        zones: [ { target: './client', from: './server' } ],
-        basePath: testFilePath('./restricted-paths'),
-      } ],
-      errors: [ {
-        message: 'Unexpected path "../server/b.js" imported in restricted zone.',
-        line: 1,
-        column: 15,
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './client',
+              from: './server',
+            },
+          ],
+          basePath: testFilePath('./restricted-paths'),
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
     }),
     test({
       code: 'const b = require("../server/b.js")',
       filename: testFilePath('./restricted-paths/client/a.js'),
-      options: [ {
-        zones: [ { target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/server' } ],
-      } ],
-      errors: [ {
-        message: 'Unexpected path "../server/b.js" imported in restricted zone.',
-        line: 1,
-        column: 19,
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client',
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 19,
+        },
+      ],
     }),
     test({
       code: 'import b from "../two/a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),
-      options: [ {
-        zones: [ {
-          target: './tests/files/restricted-paths/server/one',
-          from: './tests/files/restricted-paths/server',
-          except: ['./one'],
-        } ],
-      } ],
-      errors: [ {
-        message: 'Unexpected path "../two/a.js" imported in restricted zone.',
-        line: 1,
-        column: 15,
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['./one'],
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../two/a.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
     }),
     test({
       code: 'import b from "../two/a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),
-      options: [ {
-        zones: [ {
-          target: './tests/files/restricted-paths/server/one',
-          from: './tests/files/restricted-paths/server',
-          except: ['./one'],
-          message: 'Custom message',
-        } ],
-      } ],
-      errors: [ {
-        message: 'Unexpected path "../two/a.js" imported in restricted zone. Custom message',
-        line: 1,
-        column: 15,
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['./one'],
+              message: 'Custom message',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../two/a.js" imported in restricted zone. Custom message',
+          line: 1,
+          column: 15,
+        },
+      ],
     }),
     test({
       code: 'import b from "../two/a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),
-      options: [ {
-        zones: [ {
-          target: './tests/files/restricted-paths/server/one',
-          from: './tests/files/restricted-paths/server',
-          except: ['../client/a'],
-        } ],
-      } ],
-      errors: [ {
-        message: 'Restricted path exceptions must be descendants of the configured ' +
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['../client/a'],
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Restricted path exceptions must be descendants of the configured ' +
           '`from` path for that zone.',
-        line: 1,
-        column: 15,
-      } ],
+          line: 1,
+          column: 15,
+        },
+      ],
     }),
     test({
       code: 'import A from "../two/a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),
-      options: [ {
-        zones: [ {
-          target: '**/*',
-          from: './tests/files/restricted-paths/server/**/*',
-        } ],
-      } ],
-      errors: [ {
-        message: 'Unexpected path "../two/a.js" imported in restricted zone.',
-        line: 1,
-        column: 15,
-      } ],
+      options: [
+        {
+          zones: [
+            {
+              target: '**/*',
+              from: './tests/files/restricted-paths/server/**/*',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../two/a.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
     }),
     test({
       code: 'import A from "../two/a.js"',
       filename: testFilePath('./restricted-paths/server/one/a.js'),
-      options: [ {
-        zones: [ {
-          target: '**/*',
-          from: './tests/files/restricted-paths/server/**/*',
-          except: ['a.js'],
-        } ],
-      } ],
-      errors: [ {
-        message: 'Restricted path exceptions must be glob patterns when `from` is a glob pattern',
-        line: 1,
-        column: 15,
-      } ],
-    }),
-  ],
+      options: [
+        {
+          zones: [
+            {
+              target: '**/*',
+              from: './tests/files/restricted-paths/server/**/*',
+              except: ['a.js'],
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Restricted path exceptions must be glob patterns when `from` contains glob patterns',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+
+    // support of arrays for from and target
+    // array with single element
+    test({
+      code: 'import b from "../server/b.js"; // 4',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: ['./tests/files/restricted-paths/client'],
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    test({
+      code: 'import b from "../server/b.js"; // 5',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client',
+              from: ['./tests/files/restricted-paths/server'],
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    // array with multiple elements
+    test({
+      code: 'import b from "../server/b.js"; // 6',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: ['./tests/files/restricted-paths/client/one', './tests/files/restricted-paths/client'],
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    test({
+      code: 'import b from "../server/one/b.js"\nimport a from "../server/two/a.js"',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client',
+              from: ['./tests/files/restricted-paths/server/one', './tests/files/restricted-paths/server/two'],
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/one/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+        {
+          message: 'Unexpected path "../server/two/a.js" imported in restricted zone.',
+          line: 2,
+          column: 15,
+        },
+      ],
+    }),
+    // array with multiple glob patterns in from
+    test({
+      code: 'import b from "../server/one/b.js"\nimport a from "../server/two/a.js"',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client',
+              from: ['./tests/files/restricted-paths/server/one/*', './tests/files/restricted-paths/server/two/*'],
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/one/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+        {
+          message: 'Unexpected path "../server/two/a.js" imported in restricted zone.',
+          line: 2,
+          column: 15,
+        },
+      ],
+    }),
+    // array with mix of glob and non glob patterns in target
+    test({
+      code: 'import b from "../server/b.js"; // 7',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: ['./tests/files/restricted-paths/client/one', './tests/files/restricted-paths/client/**/*'],
+              from: './tests/files/restricted-paths/server',
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Unexpected path "../server/b.js" imported in restricted zone.',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    // configuration format
+    test({
+      code: 'import A from "../two/a.js"',
+      filename: testFilePath('./restricted-paths/server/one/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: '**/*',
+              from: ['./tests/files/restricted-paths/server/**/*'],
+              except: ['a.js'],
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Restricted path exceptions must be glob patterns when `from` contains glob patterns',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+    test({
+      code: 'import b from "../server/one/b.js"',
+      filename: testFilePath('./restricted-paths/client/a.js'),
+      options: [
+        {
+          zones: [
+            {
+              target: './tests/files/restricted-paths/client',
+              from: ['./tests/files/restricted-paths/server/one', './tests/files/restricted-paths/server/two/*'],
+            },
+          ],
+        },
+      ],
+      errors: [
+        {
+          message: 'Restricted path `from` must contain either only glob patterns or none',
+          line: 1,
+          column: 15,
+        },
+      ],
+    }),
+  ),
 });

From d1fe8eb35d6a6f3f40c841ed28f71fa80873e9e2 Mon Sep 17 00:00:00 2001
From: AdriAt360 <adrien.marion@360learning.com>
Date: Wed, 8 Jun 2022 11:52:16 +0200
Subject: [PATCH 485/767] [Fix] `no-restricted-paths`: use `Minimatch.match`
 instead of `minimatch` to comply with Windows Native paths

---
 src/rules/no-restricted-paths.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 9d56949726..9b17975b5c 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -3,7 +3,7 @@ import path from 'path';
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import isGlob from 'is-glob';
-import { Minimatch, default as minimatch } from 'minimatch';
+import { Minimatch } from 'minimatch';
 import docsUrl from '../docsUrl';
 import importType from '../core/importType';
 
@@ -83,7 +83,8 @@ module.exports = {
 
     function isMatchingTargetPath(filename, targetPath) {
       if (isGlob(targetPath)) {
-        return minimatch(filename, targetPath);
+        const mm = new Minimatch(targetPath);
+        return mm.match(filename);
       }
 
       return containsPath(filename, targetPath);

From 7f9104a8e5139b71b53f7277717cbf399317406a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 29 Jun 2022 10:34:20 -0700
Subject: [PATCH 486/767] [meta] add a missing changelog entry

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2f70fedfd..5119b02ce7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
 - [`no-restricted-paths`]: fix an error message ([#2466], thanks [@AdriAt360])
+- [`no-restricted-paths`]: use `Minimatch.match` instead of `minimatch` to comply with Windows Native paths ([#2466], thanks [@AdriAt360])
 
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])

From 754e131b051e5b1150153614b0b5e2ccb1df9c88 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 29 Jun 2022 12:27:21 -0700
Subject: [PATCH 487/767] [Deps] update `resolve`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 023d481126..689c3bfa27 100644
--- a/package.json
+++ b/package.json
@@ -110,7 +110,7 @@
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.values": "^1.1.5",
-    "resolve": "^1.22.0",
+    "resolve": "^1.22.1",
     "tsconfig-paths": "^3.14.1"
   }
 }

From 98c0f0556fdf68f669d95b748f572cfd743348c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=94=AF=E7=84=B6?= <weiran.zsd@outlook.com>
Date: Wed, 23 Mar 2022 17:25:45 +0800
Subject: [PATCH 488/767] [Docs] remove global install in readme

as said in the docs, In eslint v6+, users have to install the plugins locally.
refs: https://eslint.org/docs/user-guide/migrating-to-6.0.0#-plugins-and-shareable-configs-are-no-longer-affected-by-eslints-location
---
 CHANGELOG.md | 2 ++
 README.md    | 6 ------
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5119b02ce7..f8cf89d9ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [readme] note use of typescript in readme `import/extensions` section ([#2440], thanks [@OutdatedVersion])
 - [Docs] `order`: use correct default value ([#2392], thanks [@hyperupcall])
 - [meta] replace git.io link in comments with the original URL ([#2444], thanks [@liby])
+- [Docs] remove global install in readme ([#2412], thanks [@aladdin-add])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1289,6 +1290,7 @@ for info on changes for earlier releases.
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
 [#2444]: https://github.com/import-js/eslint-plugin-import/issues/2444
+[#2412]: https://github.com/import-js/eslint-plugin-import/issues/2412
 [#2392]: https://github.com/import-js/eslint-plugin-import/issues/2392
 [#2340]: https://github.com/import-js/eslint-plugin-import/issues/2340
 [#2255]: https://github.com/import-js/eslint-plugin-import/issues/2255
diff --git a/README.md b/README.md
index 8d38874b18..6682d5c918 100644
--- a/README.md
+++ b/README.md
@@ -123,12 +123,6 @@ The maintainers of `eslint-plugin-import` and thousands of other packages are wo
 
 ## Installation
 
-```sh
-npm install eslint-plugin-import -g
-```
-
-or if you manage ESLint as a dev dependency:
-
 ```sh
 # inside your project's working tree
 npm install eslint-plugin-import --save-dev

From ce037f4b52e52a85ead0871d74ade4c849d5b559 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=A0v=C3=A1b?= <michal@svab.net>
Date: Thu, 7 Jul 2022 13:44:44 +0200
Subject: [PATCH 489/767] [Fix] `order`: require with member expression could
 not be fixed if alphabetize.order was used

---
 CHANGELOG.md             |  5 ++++-
 src/rules/order.js       | 29 ++++++++++++++++++++---------
 tests/src/rules/order.js | 27 ++++++++++++++++++++++-----
 3 files changed, 46 insertions(+), 15 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8cf89d9ae..821d943ed7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
 - [`no-restricted-paths`]: fix an error message ([#2466], thanks [@AdriAt360])
 - [`no-restricted-paths`]: use `Minimatch.match` instead of `minimatch` to comply with Windows Native paths ([#2466], thanks [@AdriAt360])
+- [`order`]: require with member expression could not be fixed if alphabetize.order was used ([#2490], thanks [@msvab])
 
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -994,6 +995,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
@@ -1638,6 +1640,7 @@ for info on changes for earlier releases.
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@mplewis]: https://github.com/mplewis
 [@mrmckeb]: https://github.com/mrmckeb
+[@msvab]: https://github.com/msvab
 [@mx-bernhard]: https://github.com/mx-bernhard
 [@nickofthyme]: https://github.com/nickofthyme
 [@nicolashenry]: https://github.com/nicolashenry
@@ -1645,8 +1648,8 @@ for info on changes for earlier releases.
 [@ntdb]: https://github.com/ntdb
 [@nwalters512]: https://github.com/nwalters512
 [@ombene]: https://github.com/ombene
-[@OutdatedVersion]: https://github.com/OutdatedVersion
 [@ota-meshi]: https://github.com/ota-meshi
+[@OutdatedVersion]: https://github.com/OutdatedVersion
 [@panrafal]: https://github.com/panrafal
 [@paztis]: https://github.com/paztis
 [@pcorpet]: https://github.com/pcorpet
diff --git a/src/rules/order.js b/src/rules/order.js
index df35db065c..3f033eb82b 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -129,7 +129,17 @@ function findStartOfLineWithComments(sourceCode, node) {
   return result;
 }
 
-function isPlainRequireModule(node) {
+function isRequireExpression(expr) {
+  return expr != null &&
+    expr.type === 'CallExpression' &&
+    expr.callee != null &&
+    expr.callee.name === 'require' &&
+    expr.arguments != null &&
+    expr.arguments.length === 1 &&
+    expr.arguments[0].type === 'Literal';
+}
+
+function isSupportedRequireModule(node) {
   if (node.type !== 'VariableDeclaration') {
     return false;
   }
@@ -137,16 +147,17 @@ function isPlainRequireModule(node) {
     return false;
   }
   const decl = node.declarations[0];
-  const result = decl.id &&
+  const isPlainRequire = decl.id &&
+    (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') &&
+    isRequireExpression(decl.init);
+  const isRequireWithMemberExpression = decl.id &&
     (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') &&
     decl.init != null &&
     decl.init.type === 'CallExpression' &&
     decl.init.callee != null &&
-    decl.init.callee.name === 'require' &&
-    decl.init.arguments != null &&
-    decl.init.arguments.length === 1 &&
-    decl.init.arguments[0].type === 'Literal';
-  return result;
+    decl.init.callee.type === 'MemberExpression' &&
+    isRequireExpression(decl.init.callee.object);
+  return isPlainRequire || isRequireWithMemberExpression;
 }
 
 function isPlainImportModule(node) {
@@ -158,7 +169,7 @@ function isPlainImportEquals(node) {
 }
 
 function canCrossNodeWhileReorder(node) {
-  return isPlainRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node);
+  return isSupportedRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node);
 }
 
 function canReorderItems(firstNode, secondNode) {
@@ -276,7 +287,7 @@ function getSorter(ascending) {
         result = a < b ? -1 : 1;
       }
     }
-    
+
     return result * multiplier;
   };
 }
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index f5c3bb393e..e8a5143c52 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -896,13 +896,13 @@ ruleTester.run('order', rule, {
         import express from 'express';
 
         import service from '@/api/service';
-        
+
         import fooParent from '../foo';
-        
+
         import fooSibling from './foo';
-        
+
         import index from './';
-        
+
         import internalDoesNotExistSoIsUnknown from '@/does-not-exist';
       `,
       options: [
@@ -2289,7 +2289,7 @@ ruleTester.run('order', rule, {
         import b from "foo-bar";
       `,
       errors: [{
-        message: '`foo-bar` import should occur after import of `foo/barfoo`', 
+        message: '`foo-bar` import should occur after import of `foo/barfoo`',
       }],
     }),
     // Option alphabetize {order: 'asc': caseInsensitive: true}
@@ -2336,6 +2336,23 @@ ruleTester.run('order', rule, {
         message: '`foo` import should occur before import of `Bar`',
       }],
     }),
+    // Option alphabetize {order: 'asc'} and require with member expression
+    test({
+      code: `
+        const b = require('./b').get();
+        const a = require('./a');
+      `,
+      output: `
+        const a = require('./a');
+        const b = require('./b').get();
+      `,
+      options: [{
+        alphabetize: { order: 'asc' },
+      }],
+      errors: [{
+        message: '`./a` import should occur before import of `./b`',
+      }],
+    }),
     // Alphabetize with parent paths
     test({
       code: `

From f18b67687fad7770e638de6f70d1a530addd5e8d Mon Sep 17 00:00:00 2001
From: silverwind <me@silverwind.io>
Date: Mon, 11 Apr 2022 20:01:42 +0200
Subject: [PATCH 490/767] [utils] [fix] ignore hashbang and BOM while parsing
 (#2431)

---
 utils/CHANGELOG.md |  4 ++++
 utils/parse.js     | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 193fc141e0..021b0c0690 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Fixed
+- [Fix] Ignore hashbang and BOM while parsing ([#2431], thanks [@silverwind])
+
 ## v2.7.3 - 2022-01-26
 
 ### Fixed
@@ -115,6 +118,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2431]: https://github.com/import-js/eslint-plugin-import/pull/2431
 [#2350]: https://github.com/import-js/eslint-plugin-import/issues/2350
 [#2343]: https://github.com/import-js/eslint-plugin-import/pull/2343
 [#2261]: https://github.com/import-js/eslint-plugin-import/pull/2261
diff --git a/utils/parse.js b/utils/parse.js
index 98e8215992..ac728ec5b2 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -42,6 +42,14 @@ function makeParseReturn(ast, visitorKeys) {
   return ast;
 }
 
+function stripUnicodeBOM(text) {
+  return text.charCodeAt(0) === 0xFEFF ? text.slice(1) : text;
+}
+
+function transformHashbang(text) {
+  return text.replace(/^#!([^\r\n]+)/u, (_, captured) => `//${captured}`);
+}
+
 exports.default = function parse(path, content, context) {
 
   if (context == null) throw new Error('need context to parse properly');
@@ -78,6 +86,10 @@ exports.default = function parse(path, content, context) {
   // require the parser relative to the main module (i.e., ESLint)
   const parser = moduleRequire(parserPath);
 
+  // replicate bom strip and hashbang transform of ESLint
+  // https://github.com/eslint/eslint/blob/b93af98b3c417225a027cabc964c38e779adb945/lib/linter/linter.js#L779
+  content = transformHashbang(stripUnicodeBOM(String(content)));
+
   if (typeof parser.parseForESLint === 'function') {
     let ast;
     try {

From 53a9d5d725b017442ddf3fc65478fbfd6fe553d4 Mon Sep 17 00:00:00 2001
From: silverwind <me@silverwind.io>
Date: Mon, 11 Apr 2022 20:01:42 +0200
Subject: [PATCH 491/767] [Fix] `no-unused-modules`: ignore hashbang and BOM
 while parsing

ESLint does this outside their espree parser, so we need to do it as
well. Just like ESLint, the code will convert hashbang to comments and
strip off the BOM completely before handing the content to the parser.
---
 tests/files/no-unused-modules/prefix-child.js |  1 +
 .../no-unused-modules/prefix-parent-bom.js    |  1 +
 .../prefix-parent-bomhashbang.js              |  2 +
 .../prefix-parent-hashbang.js                 |  2 +
 .../files/no-unused-modules/prefix-parent.js  |  2 +
 tests/src/rules/no-unused-modules.js          | 69 ++++++++++++++++++-
 6 files changed, 76 insertions(+), 1 deletion(-)
 create mode 100644 tests/files/no-unused-modules/prefix-child.js
 create mode 100644 tests/files/no-unused-modules/prefix-parent-bom.js
 create mode 100644 tests/files/no-unused-modules/prefix-parent-bomhashbang.js
 create mode 100644 tests/files/no-unused-modules/prefix-parent-hashbang.js
 create mode 100644 tests/files/no-unused-modules/prefix-parent.js

diff --git a/tests/files/no-unused-modules/prefix-child.js b/tests/files/no-unused-modules/prefix-child.js
new file mode 100644
index 0000000000..bb1843d113
--- /dev/null
+++ b/tests/files/no-unused-modules/prefix-child.js
@@ -0,0 +1 @@
+export const foo = 1;
diff --git a/tests/files/no-unused-modules/prefix-parent-bom.js b/tests/files/no-unused-modules/prefix-parent-bom.js
new file mode 100644
index 0000000000..46b6da280a
--- /dev/null
+++ b/tests/files/no-unused-modules/prefix-parent-bom.js
@@ -0,0 +1 @@
+import {foo} from './prefix-child.js';
diff --git a/tests/files/no-unused-modules/prefix-parent-bomhashbang.js b/tests/files/no-unused-modules/prefix-parent-bomhashbang.js
new file mode 100644
index 0000000000..4f5d829690
--- /dev/null
+++ b/tests/files/no-unused-modules/prefix-parent-bomhashbang.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+import {foo} from './prefix-child.js';
diff --git a/tests/files/no-unused-modules/prefix-parent-hashbang.js b/tests/files/no-unused-modules/prefix-parent-hashbang.js
new file mode 100644
index 0000000000..db2bf53329
--- /dev/null
+++ b/tests/files/no-unused-modules/prefix-parent-hashbang.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+import {foo} from './prefix-child.js';
diff --git a/tests/files/no-unused-modules/prefix-parent.js b/tests/files/no-unused-modules/prefix-parent.js
new file mode 100644
index 0000000000..4f5d829690
--- /dev/null
+++ b/tests/files/no-unused-modules/prefix-parent.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+import {foo} from './prefix-child.js';
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 485400ece2..8c8fc7c4ed 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -307,7 +307,7 @@ describe('dynamic imports', () => {
       `,
         filename: testFilePath('./unused-modules-reexport-crash/src/index.tsx'),
         parser: parsers.TS_NEW,
-        options: [{        
+        options: [{
           unusedExports: true,
           ignoreExports: ['**/magic/**'],
         }],
@@ -1302,3 +1302,70 @@ describe('support ES2022 Arbitrary module namespace identifier names', () => {
     ),
   });
 });
+
+describe('parser ignores prefixes like BOM and hashbang', () => {
+  // bom, hashbang
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsOptions,
+        code: 'export const foo = 1;\n',
+        filename: testFilePath('./no-unused-modules/prefix-child.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: `\uFEFF#!/usr/bin/env node\nimport {foo} from './prefix-child.js';\n`,
+        filename: testFilePath('./no-unused-modules/prefix-parent-bom.js'),
+      }),
+    ],
+    invalid: [],
+  });
+  // no bom, hashbang
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsOptions,
+        code: 'export const foo = 1;\n',
+        filename: testFilePath('./no-unused-modules/prefix-child.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: `#!/usr/bin/env node\nimport {foo} from './prefix-child.js';\n`,
+        filename: testFilePath('./no-unused-modules/prefix-parent-hashbang.js'),
+      }),
+    ],
+    invalid: [],
+  });
+  // bom, no hashbang
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsOptions,
+        code: 'export const foo = 1;\n',
+        filename: testFilePath('./no-unused-modules/prefix-child.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: `\uFEFF#!/usr/bin/env node\nimport {foo} from './prefix-child.js';\n`,
+        filename: testFilePath('./no-unused-modules/prefix-parent-bomhashbang.js'),
+      }),
+    ],
+    invalid: [],
+  });
+  // no bom, no hashbang
+  ruleTester.run('no-unused-modules', rule, {
+    valid: [
+      test({
+        options: unusedExportsOptions,
+        code: 'export const foo = 1;\n',
+        filename: testFilePath('./no-unused-modules/prefix-child.js'),
+      }),
+      test({
+        options: unusedExportsOptions,
+        code: `import {foo} from './prefix-child.js';\n`,
+        filename: testFilePath('./no-unused-modules/prefix-parent.js'),
+      }),
+    ],
+    invalid: [],
+  });
+});

From d82670c4ee2dafa0badfcf49173950d5289083b5 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 12 Jul 2022 15:10:43 -0700
Subject: [PATCH 492/767] [utils] [refactor] switch to an internal replacement
 for `find-up`

---
 utils/package.json |  3 +--
 utils/pkgUp.js     | 52 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/utils/package.json b/utils/package.json
index 2e348d07f2..9041a8d387 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -26,7 +26,6 @@
   },
   "homepage": "https://github.com/import-js/eslint-plugin-import#readme",
   "dependencies": {
-    "debug": "^3.2.7",
-    "find-up": "^2.1.0"
+    "debug": "^3.2.7"
   }
 }
diff --git a/utils/pkgUp.js b/utils/pkgUp.js
index f73e3f7b25..049869719b 100644
--- a/utils/pkgUp.js
+++ b/utils/pkgUp.js
@@ -1,8 +1,56 @@
 'use strict';
 exports.__esModule = true;
 
-const findUp = require('find-up');
+const fs = require('fs');
+const path = require('path');
+
+/**
+ * Derived significantly from package find-up@2.0.0. See license below.
+ * 
+ * @copyright Sindre Sorhus
+ * MIT License
+ *
+ * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+function findUp(filename, cwd) {
+  let dir = path.resolve(cwd || '');
+  const root = path.parse(dir).root;
+
+  const filenames = [].concat(filename);
+
+  // eslint-disable-next-line no-constant-condition
+  while (true) {
+    const file = filenames.find((el) => fs.existsSync(path.resolve(dir, el)));
+
+    if (file) {
+      return path.join(dir, file);
+    }
+    if (dir === root) {
+      return null;
+    }
+
+    dir = path.dirname(dir);
+  }
+}
 
 exports.default = function pkgUp(opts) {
-  return findUp.sync('package.json', opts);
+  return findUp('package.json', opts && opts.cwd);
 };

From 0ef8cbaab5ba0789a6e1b716317b000b55ee4555 Mon Sep 17 00:00:00 2001
From: Damien Cassou <damien@cassou.me>
Date: Wed, 20 Jul 2022 15:03:34 +0200
Subject: [PATCH 493/767] [New] `no-anonymous-default-export`: add `allowNew`
 option

---
 CHANGELOG.md                                   | 2 ++
 docs/rules/no-anonymous-default-export.md      | 6 ++++++
 src/rules/no-anonymous-default-export.js       | 5 +++++
 tests/src/rules/no-anonymous-default-export.js | 2 ++
 4 files changed, 15 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 821d943ed7..9809e886f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`newline-after-import`]: add `considerComments` option ([#2399], thanks [@pri1311])
 - [`no-cycle`]: add `allowUnsafeDynamicCyclicDependency` option ([#2387], thanks [@GerkinDev])
 - [`no-restricted-paths`]: support arrays for `from` and `target` options ([#2466], thanks [@AdriAt360])
+- [`no-anonymous-default-export`]: add `allowNew` option ([#2505], thanks [@DamienCassou])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -1534,6 +1535,7 @@ for info on changes for earlier releases.
 [@chrislloyd]: https://github.com/chrislloyd
 [@christianvuerings]: https://github.com/christianvuerings
 [@christophercurrie]: https://github.com/christophercurrie
+[@DamienCassou]: https://github.com/DamienCassou
 [@danny-andrews]: https://github.com/dany-andrews
 [@darkartur]: https://github.com/darkartur
 [@davidbonnet]: https://github.com/davidbonnet
diff --git a/docs/rules/no-anonymous-default-export.md b/docs/rules/no-anonymous-default-export.md
index c8db897906..3edac63135 100644
--- a/docs/rules/no-anonymous-default-export.md
+++ b/docs/rules/no-anonymous-default-export.md
@@ -17,6 +17,7 @@ The complete default configuration looks like this.
   "allowAnonymousClass": false,
   "allowAnonymousFunction": false,
   "allowCallExpression": true, // The true value here is for backward compatibility
+  "allowNew": false,
   "allowLiteral": false,
   "allowObject": false
 }]
@@ -40,6 +41,8 @@ export default foo(bar)
 export default 123
 
 export default {}
+
+export default new Foo()
 ```
 
 ### Pass
@@ -70,4 +73,7 @@ export default 123
 
 /* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
 export default {}
+
+/* eslint import/no-anonymous-default-export: [2, {"allowNew": true}] */
+export default new Foo()
 ```
diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js
index f1f495ca38..106f43b091 100644
--- a/src/rules/no-anonymous-default-export.js
+++ b/src/rules/no-anonymous-default-export.js
@@ -50,6 +50,11 @@ const defs = {
     description: 'If `false`, will report default export of a literal',
     message: 'Assign literal to a variable before exporting as module default',
   },
+  NewExpression: {
+    option: 'allowNew',
+    description: 'If `false`, will report default export of a class instantiation',
+    message: 'Assign instance to a variable before exporting as module default',
+  },
 };
 
 const schemaProperties = Object.keys(defs)
diff --git a/tests/src/rules/no-anonymous-default-export.js b/tests/src/rules/no-anonymous-default-export.js
index 0428ee1b99..53b2fc6fbb 100644
--- a/tests/src/rules/no-anonymous-default-export.js
+++ b/tests/src/rules/no-anonymous-default-export.js
@@ -22,6 +22,7 @@ ruleTester.run('no-anonymous-default-export', rule, {
     test({ code: 'export default `foo`', options: [{ allowLiteral: true }] }),
     test({ code: 'export default {}', options: [{ allowObject: true }] }),
     test({ code: 'export default foo(bar)', options: [{ allowCallExpression: true }] }),
+    test({ code: 'export default new Foo()', options: [{ allowNew: true }] }),
 
     // Allow forbidden types with multiple options
     test({ code: 'export default 123', options: [{ allowLiteral: true, allowObject: true }] }),
@@ -53,6 +54,7 @@ ruleTester.run('no-anonymous-default-export', rule, {
     test({ code: 'export default `foo`', errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),
     test({ code: 'export default {}', errors: [{ message: 'Assign object to a variable before exporting as module default' }] }),
     test({ code: 'export default foo(bar)', options: [{ allowCallExpression: false }], errors: [{ message: 'Assign call result to a variable before exporting as module default' }] }),
+    test({ code: 'export default new Foo()', errors: [{ message: 'Assign instance to a variable before exporting as module default' }] }),
 
     // Test failure with non-covering exception
     test({ code: 'export default 123', options: [{ allowObject: true }], errors: [{ message: 'Assign literal to a variable before exporting as module default' }] }),

From 5fe9aa44eb9d20b376d1b32a5d3384c46a01309e Mon Sep 17 00:00:00 2001
From: JounQin <admin@1stg.me>
Date: Wed, 20 Jul 2022 15:41:16 +0800
Subject: [PATCH 494/767] [readme] clarify `eslint-import-resolver-typescript`
 usage

---
 CHANGELOG.md |  2 ++
 README.md    | 15 ++++++++++-----
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9809e886f6..01cf2e69b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] `order`: use correct default value ([#2392], thanks [@hyperupcall])
 - [meta] replace git.io link in comments with the original URL ([#2444], thanks [@liby])
 - [Docs] remove global install in readme ([#2412], thanks [@aladdin-add])
+- [readme] clarify `eslint-import-resolver-typescript` usage ([#2503], thanks [@JounQin])
 
 ## [2.26.0] - 2022-04-05
 
@@ -996,6 +997,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2503]: https://github.com/import-js/eslint-plugin-import/pull/2503
 [#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
diff --git a/README.md b/README.md
index 6682d5c918..329400d594 100644
--- a/README.md
+++ b/README.md
@@ -157,19 +157,24 @@ rules:
 
 You may use the following shortcut or assemble your own config using the granular settings described below.
 
-Make sure you have installed [`@typescript-eslint/parser`] which is used in the following configuration. Unfortunately NPM does not allow to list optional peer dependencies.
+Make sure you have installed [`@typescript-eslint/parser`] and [`eslint-import-resolver-typescript`] which are used in the following configuration.
 
 ```yaml
 extends:
   - eslint:recommended
   - plugin:import/recommended
-  - plugin:import/typescript # this line does the trick
+# the following lines do the trick
+  - plugin:import/typescript
+settings:
+  import/resolver:
+    # You will also need to install and configure the TypeScript resolver
+    # See also https://github.com/import-js/eslint-import-resolver-typescript#configuration
+    typescript: true
+    node: true
 ```
 
 [`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser
-
-You will also need to install and configure the TypeScript resolver:
-[`eslint-import-resolver-typescript`](https://github.com/alexgorbatchev/eslint-import-resolver-typescript).
+[`eslint-import-resolver-typescript`]: https://github.com/import-js/eslint-import-resolver-typescript
 
 # Resolvers
 

From 7a37f9096a35694aeb45458f1baa7d2abccb0b2a Mon Sep 17 00:00:00 2001
From: Pearce <pearce@sigmacomputing.com>
Date: Sat, 23 Jul 2022 14:15:37 -0700
Subject: [PATCH 495/767] [Fix] `order`: leave more space in rankings for
 consecutive path groups

Fixes #2494.
---
 CHANGELOG.md             |  3 ++
 src/rules/order.js       |  4 +--
 tests/src/rules/order.js | 68 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 01cf2e69b8..3102fc8691 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-restricted-paths`]: fix an error message ([#2466], thanks [@AdriAt360])
 - [`no-restricted-paths`]: use `Minimatch.match` instead of `minimatch` to comply with Windows Native paths ([#2466], thanks [@AdriAt360])
 - [`order`]: require with member expression could not be fixed if alphabetize.order was used ([#2490], thanks [@msvab])
+- [`order`]: leave more space in rankings for consecutive path groups ([#2506], thanks [@Pearce-Ropion])
 
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -997,6 +998,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2506]: https://github.com/import-js/eslint-plugin-import/pull/2506
 [#2503]: https://github.com/import-js/eslint-plugin-import/pull/2503
 [#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
@@ -1657,6 +1659,7 @@ for info on changes for earlier releases.
 [@panrafal]: https://github.com/panrafal
 [@paztis]: https://github.com/paztis
 [@pcorpet]: https://github.com/pcorpet
+[@Pearce-Ropion]: https://github.com/Pearce-Ropion
 [@Pessimistress]: https://github.com/Pessimistress
 [@pmcelhaney]: https://github.com/pmcelhaney
 [@preco21]: https://github.com/preco21
diff --git a/src/rules/order.js b/src/rules/order.js
index 3f033eb82b..4fb1787685 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -407,7 +407,7 @@ function convertGroupsToRanks(groups) {
       if (res[groupItem] !== undefined) {
         throw new Error('Incorrect configuration of the rule: `' + groupItem + '` is duplicated');
       }
-      res[groupItem] = index;
+      res[groupItem] = index * 2;
     });
     return res;
   }, {});
@@ -417,7 +417,7 @@ function convertGroupsToRanks(groups) {
   });
 
   const ranks = omittedTypes.reduce(function (res, type) {
-    res[type] = groups.length;
+    res[type] = groups.length * 2;
     return res;
   }, rankObject);
 
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index e8a5143c52..ed4879ac44 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2099,6 +2099,74 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    test({
+      code: `
+        import path from 'path';
+        import { namespace } from '@namespace';
+        import { a } from 'a';
+        import { b } from 'b';
+        import { c } from 'c';
+        import { d } from 'd';
+        import { e } from 'e';
+        import { f } from 'f';
+        import { g } from 'g';
+        import { h } from 'h';
+        import { i } from 'i';
+        import { j } from 'j';
+        import { k } from 'k';`,
+      output: `
+        import path from 'path';
+
+        import { namespace } from '@namespace';
+
+        import { a } from 'a';
+
+        import { b } from 'b';
+
+        import { c } from 'c';
+
+        import { d } from 'd';
+
+        import { e } from 'e';
+
+        import { f } from 'f';
+
+        import { g } from 'g';
+
+        import { h } from 'h';
+
+        import { i } from 'i';
+
+        import { j } from 'j';
+        import { k } from 'k';`,
+      options: [
+        {
+          groups: [
+            'builtin',
+            'external',
+            'internal',
+          ],
+          pathGroups: [
+            { pattern: '@namespace', group: 'external', position: 'after' },
+            { pattern: 'a', group: 'internal', position: 'before' },
+            { pattern: 'b', group: 'internal', position: 'before' },
+            { pattern: 'c', group: 'internal', position: 'before' },
+            { pattern: 'd', group: 'internal', position: 'before' },
+            { pattern: 'e', group: 'internal', position: 'before' },
+            { pattern: 'f', group: 'internal', position: 'before' },
+            { pattern: 'g', group: 'internal', position: 'before' },
+            { pattern: 'h', group: 'internal', position: 'before' },
+            { pattern: 'i', group: 'internal', position: 'before' },
+          ],
+          'newlines-between': 'always',
+          pathGroupsExcludedImportTypes: ['builtin'],
+        },
+      ],
+      settings: {
+        'import/internal-regex': '^(a|b|c|d|e|f|g|h|i|j|k)(\\/|$)',
+      },
+      errors: Array.from({ length: 11 }, () => 'There should be at least one empty line between import groups'),
+    }),
 
     // reorder fix cannot cross non import or require
     test(withoutAutofixOutput({

From ab8b6d84e0523976a94a91c99749144633f5efd0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 6 Aug 2022 13:44:05 -0700
Subject: [PATCH 496/767] [Deps] update `is-core-module`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 689c3bfa27..d3c23b95c2 100644
--- a/package.json
+++ b/package.json
@@ -106,7 +106,7 @@
     "eslint-import-resolver-node": "^0.3.6",
     "eslint-module-utils": "^2.7.3",
     "has": "^1.0.3",
-    "is-core-module": "^2.9.0",
+    "is-core-module": "^2.10.0",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.values": "^1.1.5",

From e4c90e56d5af6852dbde91dc035372a013b55ae2 Mon Sep 17 00:00:00 2001
From: Wout Mertens <Wout.Mertens@gmail.com>
Date: Thu, 11 Aug 2022 11:04:13 +0200
Subject: [PATCH 497/767] [utils] [patch] mark eslint as an optional peer dep

This allows it to find eslint from module-require.js when the package manager is strict.

Maintainer note: this should not be necessary, but using `peerDependenciesMeta` here seems to have no downsides for real npm users, and allows tools like pnpm or yarn PnP to statically "know" that this package wants to access `eslint` if it is present.
---
 utils/CHANGELOG.md | 5 +++++
 utils/package.json | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 021b0c0690..1a8fd96767 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -8,6 +8,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [Fix] Ignore hashbang and BOM while parsing ([#2431], thanks [@silverwind])
 
+### Changed
+- [patch] mark eslint as an optional peer dep ([#2523], thanks [@wmertens])
+
 ## v2.7.3 - 2022-01-26
 
 ### Fixed
@@ -118,6 +121,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2523]: https://github.com/import-js/eslint-plugin-import/pull/2523
 [#2431]: https://github.com/import-js/eslint-plugin-import/pull/2431
 [#2350]: https://github.com/import-js/eslint-plugin-import/issues/2350
 [#2343]: https://github.com/import-js/eslint-plugin-import/pull/2343
@@ -164,3 +168,4 @@ Yanked due to critical issue with cache key resulting from #839.
 [@timkraut]: https://github.com/timkraut
 [@vikr01]: https://github.com/vikr01
 [@VitusFW]: https://github.com/VitusFW
+[@wmertens]: https://github.com/wmertens
diff --git a/utils/package.json b/utils/package.json
index 9041a8d387..55db5234c3 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -27,5 +27,10 @@
   "homepage": "https://github.com/import-js/eslint-plugin-import#readme",
   "dependencies": {
     "debug": "^3.2.7"
+  },
+  "peerDependenciesMeta": {
+    "eslint": {
+      "optional": true
+    }
   }
 }

From d85bc4414cf3516e9ba96aa83eab919e8bd01979 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 11 Aug 2022 15:45:14 -0700
Subject: [PATCH 498/767] utils: v2.7.4

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 1a8fd96767..72fa611a14 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.7.4 - 2022-08-11
+
 ### Fixed
 - [Fix] Ignore hashbang and BOM while parsing ([#2431], thanks [@silverwind])
 
diff --git a/utils/package.json b/utils/package.json
index 55db5234c3..0c0678a5ec 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.7.3",
+  "version": "2.7.4",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From d45fe21bfa09f61402c68c3d271250d95f9c9ed3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 11 Aug 2022 16:05:45 -0700
Subject: [PATCH 499/767] [Deps] update `eslint-module.utils`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index d3c23b95c2..ed87332304 100644
--- a/package.json
+++ b/package.json
@@ -104,7 +104,7 @@
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
-    "eslint-module-utils": "^2.7.3",
+    "eslint-module-utils": "^2.7.4",
     "has": "^1.0.3",
     "is-core-module": "^2.10.0",
     "is-glob": "^4.0.3",

From 7cb6fcddc654490eb9b10a62537420199ab2e1ea Mon Sep 17 00:00:00 2001
From: Sebastian Malton <sebastian@malton.name>
Date: Wed, 30 Mar 2022 15:52:39 -0400
Subject: [PATCH 500/767] [Refactor] `no-cycle`: Add per-run caching of
 traversed paths

 - This leads to about a 5x speed up

Signed-off-by: Sebastian Malton <sebastian@malton.name>
---
 CHANGELOG.md          |  2 ++
 src/rules/no-cycle.js | 12 ++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3102fc8691..d7b7917e6b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [meta] replace git.io link in comments with the original URL ([#2444], thanks [@liby])
 - [Docs] remove global install in readme ([#2412], thanks [@aladdin-add])
 - [readme] clarify `eslint-import-resolver-typescript` usage ([#2503], thanks [@JounQin])
+- [Refactor] `no-cycle`: Add per-run caching of traversed paths ([#2419], thanks [@nokel81])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1004,6 +1005,7 @@ for info on changes for earlier releases.
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
+[#2419]: https://github.com/import-js/eslint-plugin-import/pull/2419
 [#2417]: https://github.com/import-js/eslint-plugin-import/pull/2417
 [#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
 [#2399]: https://github.com/import-js/eslint-plugin-import/pull/2399
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 0aa3626827..e261ac40b7 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -9,7 +9,8 @@ import { isExternalModule } from '../core/importType';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
-// todo: cache cycles / deep relationships for faster repeat evaluation
+const traversed = new Set();
+
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -87,7 +88,6 @@ module.exports = {
       }
 
       const untraversed = [{ mget: () => imported, route:[] }];
-      const traversed = new Set();
       function detectCycle({ mget, route }) {
         const m = mget();
         if (m == null) return;
@@ -101,7 +101,7 @@ module.exports = {
             // Ignore only type imports
             !isOnlyImportingTypes,
           );
-          
+
           /*
           If cyclic dependency is allowed via dynamic import, skip checking if any module is imported dynamically
           */
@@ -138,7 +138,11 @@ module.exports = {
       }
     }
 
-    return moduleVisitor(checkSourceValue, context.options[0]);
+    return Object.assign(moduleVisitor(checkSourceValue, context.options[0]), {
+      'Program:exit': () => {
+        traversed.clear();
+      },
+    });
   },
 };
 

From 72824c7f20b4b52f9ff00dd34067bada28ec2bbb Mon Sep 17 00:00:00 2001
From: Nikita Stenin <stenin.nikita@gmail.com>
Date: Wed, 24 Aug 2022 14:14:41 +0300
Subject: [PATCH 501/767] [Performance] `ExportMap`: add caching after parsing
 for an ambiguous module

---
 CHANGELOG.md                             |  3 +++
 src/ExportMap.js                         |  6 +++++-
 tests/files/typescript-declare-module.ts |  3 +++
 tests/src/core/getExports.js             | 13 +++++++++++++
 4 files changed, 24 insertions(+), 1 deletion(-)
 create mode 100644 tests/files/typescript-declare-module.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d7b7917e6b..66389999d1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] remove global install in readme ([#2412], thanks [@aladdin-add])
 - [readme] clarify `eslint-import-resolver-typescript` usage ([#2503], thanks [@JounQin])
 - [Refactor] `no-cycle`: Add per-run caching of traversed paths ([#2419], thanks [@nokel81])
+- [Performance] `ExportMap`: add caching after parsing for an ambiguous module ([#2531], thanks [@stenin-nikita])
 
 ## [2.26.0] - 2022-04-05
 
@@ -999,6 +1000,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2531]: https://github.com/import-js/eslint-plugin-import/pull/2531
 [#2506]: https://github.com/import-js/eslint-plugin-import/pull/2506
 [#2503]: https://github.com/import-js/eslint-plugin-import/pull/2503
 [#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
@@ -1701,6 +1703,7 @@ for info on changes for earlier releases.
 [@spalger]: https://github.com/spalger
 [@st-sloth]: https://github.com/st-sloth
 [@stekycz]: https://github.com/stekycz
+[@stenin-nikita]: https://github.com/stenin-nikita
 [@stephtr]: https://github.com/stephtr
 [@straub]: https://github.com/straub
 [@strawbrary]: https://github.com/strawbrary
diff --git a/src/ExportMap.js b/src/ExportMap.js
index e18797a4d7..885801fbbb 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -346,7 +346,11 @@ ExportMap.for = function (context) {
   exportMap = ExportMap.parse(path, content, context);
 
   // ambiguous modules return null
-  if (exportMap == null) return null;
+  if (exportMap == null) {
+    log('ignored path due to ambiguous parse:', path);
+    exportCache.set(cacheKey, null);
+    return null;
+  }
 
   exportMap.mtime = stats.mtime;
 
diff --git a/tests/files/typescript-declare-module.ts b/tests/files/typescript-declare-module.ts
new file mode 100644
index 0000000000..8a9e304e91
--- /dev/null
+++ b/tests/files/typescript-declare-module.ts
@@ -0,0 +1,3 @@
+declare module "typescript-declare-module-foo" {
+  export const foo: string;
+}
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 867644bc19..dcfa74d835 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -431,6 +431,19 @@ describe('ExportMap', function () {
           ExportMap.parse('./baz.ts', 'export const baz = 5', differentContext);
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(2);
         });
+
+        it('should cache after parsing for an ambiguous module', function () {
+          const source = './typescript-declare-module.ts';
+          const parseSpy = sinon.spy(ExportMap, 'parse');
+      
+          expect(ExportMap.get(source, context)).to.be.null;
+      
+          ExportMap.get(source, context);
+      
+          expect(parseSpy.callCount).to.equal(1);
+      
+          parseSpy.restore();
+        });
       });
     });
   });

From 116af3192ae9ab428dc332bec4a0107aa7290553 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= <benoit.zugmeyer@datadoghq.com>
Date: Wed, 27 Jul 2022 08:35:52 +0200
Subject: [PATCH 502/767] [Fix] `no-cycle`: add ExportNamedDeclaration
 statements to dependencies

Fixes #2461
---
 CHANGELOG.md                                 |  3 ++
 src/ExportMap.js                             | 42 +++++++++++---------
 tests/files/cycles/es6/depth-one-reexport.js |  1 +
 tests/src/rules/no-cycle.js                  |  5 +++
 4 files changed, 32 insertions(+), 19 deletions(-)
 create mode 100644 tests/files/cycles/es6/depth-one-reexport.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 66389999d1..d54c4266b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-restricted-paths`]: use `Minimatch.match` instead of `minimatch` to comply with Windows Native paths ([#2466], thanks [@AdriAt360])
 - [`order`]: require with member expression could not be fixed if alphabetize.order was used ([#2490], thanks [@msvab])
 - [`order`]: leave more space in rankings for consecutive path groups ([#2506], thanks [@Pearce-Ropion])
+- [`no-cycle`]: add ExportNamedDeclaration statements to dependencies ([#2511], thanks [@BenoitZugmeyer])
 
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -1001,6 +1002,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2531]: https://github.com/import-js/eslint-plugin-import/pull/2531
+[#2511]: https://github.com/import-js/eslint-plugin-import/pull/2511
 [#2506]: https://github.com/import-js/eslint-plugin-import/pull/2506
 [#2503]: https://github.com/import-js/eslint-plugin-import/pull/2503
 [#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
@@ -1529,6 +1531,7 @@ for info on changes for earlier releases.
 [@beatrizrezener]: https://github.com/beatrizrezener
 [@benmosher]: https://github.com/benmosher
 [@benmunro]: https://github.com/benmunro
+[@BenoitZugmeyer]: https://github.com/BenoitZugmeyer
 [@bicstone]: https://github.com/bicstone
 [@Blasz]: https://github.com/Blasz
 [@bmish]: https://github.com/bmish
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 885801fbbb..bbf43cf038 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -501,6 +501,26 @@ ExportMap.parse = function (path, content, context) {
     m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) });
   }
 
+  function captureDependencyWithSpecifiers(n) {
+    // import type { Foo } (TS and Flow)
+    const declarationIsType = n.importKind === 'type';
+    // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
+    // shouldn't be considered to be just importing types
+    let specifiersOnlyImportingTypes = n.specifiers.length > 0;
+    const importedSpecifiers = new Set();
+    n.specifiers.forEach(specifier => {
+      if (specifier.type === 'ImportSpecifier') {
+        importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
+      } else if (supportedImportTypes.has(specifier.type)) {
+        importedSpecifiers.add(specifier.type);
+      }
+
+      // import { type Foo } (Flow)
+      specifiersOnlyImportingTypes = specifiersOnlyImportingTypes && specifier.importKind === 'type';
+    });
+    captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
+  }
+
   function captureDependency({ source }, isOnlyImportingTypes, importedSpecifiers = new Set()) {
     if (source == null) return null;
 
@@ -587,25 +607,7 @@ ExportMap.parse = function (path, content, context) {
 
     // capture namespaces in case of later export
     if (n.type === 'ImportDeclaration') {
-      // import type { Foo } (TS and Flow)
-      const declarationIsType = n.importKind === 'type';
-      // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
-      // shouldn't be considered to be just importing types
-      let specifiersOnlyImportingTypes = n.specifiers.length;
-      const importedSpecifiers = new Set();
-      n.specifiers.forEach(specifier => {
-        if (supportedImportTypes.has(specifier.type)) {
-          importedSpecifiers.add(specifier.type);
-        }
-        if (specifier.type === 'ImportSpecifier') {
-          importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
-        }
-
-        // import { type Foo } (Flow)
-        specifiersOnlyImportingTypes =
-          specifiersOnlyImportingTypes && specifier.importKind === 'type';
-      });
-      captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
+      captureDependencyWithSpecifiers(n);
 
       const ns = n.specifiers.find(s => s.type === 'ImportNamespaceSpecifier');
       if (ns) {
@@ -615,6 +617,8 @@ ExportMap.parse = function (path, content, context) {
     }
 
     if (n.type === 'ExportNamedDeclaration') {
+      captureDependencyWithSpecifiers(n);
+
       // capture declaration
       if (n.declaration != null) {
         switch (n.declaration.type) {
diff --git a/tests/files/cycles/es6/depth-one-reexport.js b/tests/files/cycles/es6/depth-one-reexport.js
new file mode 100644
index 0000000000..df509fa51c
--- /dev/null
+++ b/tests/files/cycles/es6/depth-one-reexport.js
@@ -0,0 +1 @@
+export { foo } from "../depth-zero";
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index ad29292c23..233cae613b 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -166,6 +166,11 @@ ruleTester.run('no-cycle', rule, {
         errors: [error(`Dependency cycle detected.`)],
         options: [{ ...opts, amd: true }],
       }),
+      test({
+        code: `import { foo } from "./${testDialect}/depth-one-reexport"`,
+        options: [{ ...opts }],
+        errors: [error(`Dependency cycle detected.`)],
+      }),
       test({
         code: `import { foo } from "./${testDialect}/depth-two"`,
         options: [{ ...opts }],

From a8781f793210c2aae751ab98918ffd2b1306b03e Mon Sep 17 00:00:00 2001
From: Michael Busby <michael.busby@helloagora.com>
Date: Thu, 7 Apr 2022 08:32:52 -0500
Subject: [PATCH 503/767] [Tests] `named`: Add direct test for `export =`
 assignment in TS

Closes #1984.
---
 .../typescript-export-assign-object/index.ts  |  5 +++
 .../tsconfig.json                             |  5 +++
 tests/src/rules/named.js                      | 37 ++++++++++++++++++-
 3 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 tests/files/typescript-export-assign-object/index.ts
 create mode 100644 tests/files/typescript-export-assign-object/tsconfig.json

diff --git a/tests/files/typescript-export-assign-object/index.ts b/tests/files/typescript-export-assign-object/index.ts
new file mode 100644
index 0000000000..8899e3fbad
--- /dev/null
+++ b/tests/files/typescript-export-assign-object/index.ts
@@ -0,0 +1,5 @@
+const someObj = {
+  FooBar: 12,
+};
+
+export = someObj;
diff --git a/tests/files/typescript-export-assign-object/tsconfig.json b/tests/files/typescript-export-assign-object/tsconfig.json
new file mode 100644
index 0000000000..a72ee3e88b
--- /dev/null
+++ b/tests/files/typescript-export-assign-object/tsconfig.json
@@ -0,0 +1,5 @@
+{
+    "compilerOptions": {
+        "esModuleInterop": true
+    }
+}
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 0361983979..227e242ef8 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -1,5 +1,6 @@
 import { test, SYNTAX_CASES, getTSParsers, testFilePath, testVersion, parsers } from '../utils';
 import { RuleTester } from 'eslint';
+import path from 'path';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
@@ -388,7 +389,16 @@ context('TypeScript', function () {
       'import/resolver': { 'eslint-import-resolver-typescript': true },
     };
 
-    let valid = [];
+    let valid = [
+      test({
+        code: `import x from './typescript-export-assign-object'`,
+        parser,
+        parserOptions: {
+          tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-assign-object/'),
+        },
+        settings,
+      }),
+    ];
     const invalid = [
       // TODO: uncomment this test
       // test({
@@ -400,6 +410,31 @@ context('TypeScript', function () {
       //     { message: 'a not found in ./export-star-3/b' },
       //   ],
       // }),
+      test({
+        code: `import { NotExported } from './typescript-export-assign-object'`,
+        parser,
+        parserOptions: {
+          tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-assign-object/'),
+        },
+        settings,
+        errors: [{
+          message: `NotExported not found in './typescript-export-assign-object'`,
+          type: 'Identifier',
+        }],
+      }),
+      test({
+        // `export =` syntax creates a default export only
+        code: `import { FooBar } from './typescript-export-assign-object'`,
+        parser,
+        parserOptions: {
+          tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-assign-object/'),
+        },
+        settings,
+        errors: [{
+          message: `FooBar not found in './typescript-export-assign-object'`,
+          type: 'Identifier',
+        }],
+      }),
     ];
 
     [

From 998655b1438c9718403ae876163b739c57f658ca Mon Sep 17 00:00:00 2001
From: Edwin Kofler <edwin@kofler.dev>
Date: Sat, 13 Aug 2022 17:34:22 -0700
Subject: [PATCH 504/767] [New] `order`: Add `distinctGroup` option

Fixes #2292.
---
 CHANGELOG.md             |   2 +
 docs/rules/order.md      |  25 +++++
 src/rules/order.js       |  44 +++++---
 tests/src/rules/order.js | 211 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 268 insertions(+), 14 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d54c4266b4..27c59ac032 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-cycle`]: add `allowUnsafeDynamicCyclicDependency` option ([#2387], thanks [@GerkinDev])
 - [`no-restricted-paths`]: support arrays for `from` and `target` options ([#2466], thanks [@AdriAt360])
 - [`no-anonymous-default-export`]: add `allowNew` option ([#2505], thanks [@DamienCassou])
+- [`order`]: Add `distinctGroup` option ([#2395], thanks [@hyperupcall])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -1014,6 +1015,7 @@ for info on changes for earlier releases.
 [#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
 [#2399]: https://github.com/import-js/eslint-plugin-import/pull/2399
 [#2396]: https://github.com/import-js/eslint-plugin-import/pull/2396
+[#2395]: https://github.com/import-js/eslint-plugin-import/pull/2395
 [#2393]: https://github.com/import-js/eslint-plugin-import/pull/2393
 [#2388]: https://github.com/import-js/eslint-plugin-import/pull/2388
 [#2387]: https://github.com/import-js/eslint-plugin-import/pull/2387
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 8eead09359..53faff1530 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -128,6 +128,31 @@ Properties of the objects
 }
 ```
 
+### `distinctGroup: [boolean]`:
+
+This changes how `pathGroups[].position` affects grouping. The property is most useful when `newlines-between` is set to `always` and at least 1 `pathGroups` entry has a `position` property set.
+
+By default, in the context of a particular `pathGroup` entry, when setting `position`, a new "group" will silently be created. That is, even if the `group` is specified, a newline will still separate imports that match that `pattern` with the rest of the group (assuming `newlines-between` is `always`). This is undesirable if your intentions are to use `position` to position _within_ the group (and not create a new one). Override this behavior by setting `distinctGroup` to `false`; this will keep imports within the same group as intended.
+
+Note that currently, `distinctGroup` defaults to `true`. However, in a later update, the default will change to `false`
+
+Example:
+```json
+{
+  "import/order": ["error", {
+    "newlines-between": "always",
+    "pathGroups": [
+      {
+        "pattern": "@app/**",
+        "group": "external",
+        "position": "after"
+      }
+    ],
+    "distinctGroup": false
+  }]
+}
+```
+
 ### `pathGroupsExcludedImportTypes: [array]`:
 
 This defines import types that are not handled by configured pathGroups.
diff --git a/src/rules/order.js b/src/rules/order.js
index 4fb1787685..95311c0bcf 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -493,7 +493,7 @@ function removeNewLineAfterImport(context, currentImport, previousImport) {
   return undefined;
 }
 
-function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports) {
+function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, distinctGroup) {
   const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
     const linesBetweenImports = context.getSourceCode().lines.slice(
       previousImport.node.loc.end.line,
@@ -502,27 +502,34 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports) {
 
     return linesBetweenImports.filter((line) => !line.trim().length).length;
   };
+  const getIsStartOfDistinctGroup = (currentImport, previousImport) => {
+    return currentImport.rank - 1 >= previousImport.rank;
+  };
   let previousImport = imported[0];
 
   imported.slice(1).forEach(function (currentImport) {
     const emptyLinesBetween = getNumberOfEmptyLinesBetween(currentImport, previousImport);
+    const isStartOfDistinctGroup = getIsStartOfDistinctGroup(currentImport, previousImport);
 
     if (newlinesBetweenImports === 'always'
         || newlinesBetweenImports === 'always-and-inside-groups') {
       if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
-        context.report({
-          node: previousImport.node,
-          message: 'There should be at least one empty line between import groups',
-          fix: fixNewLineAfterImport(context, previousImport),
-        });
-      } else if (currentImport.rank === previousImport.rank
-        && emptyLinesBetween > 0
+        if (distinctGroup || (!distinctGroup && isStartOfDistinctGroup)) {
+          context.report({
+            node: previousImport.node,
+            message: 'There should be at least one empty line between import groups',
+            fix: fixNewLineAfterImport(context, previousImport),
+          });
+        }
+      } else if (emptyLinesBetween > 0
         && newlinesBetweenImports !== 'always-and-inside-groups') {
-        context.report({
-          node: previousImport.node,
-          message: 'There should be no empty line within import group',
-          fix: removeNewLineAfterImport(context, currentImport, previousImport),
-        });
+        if ((distinctGroup && currentImport.rank === previousImport.rank) || (!distinctGroup && !isStartOfDistinctGroup)) {
+          context.report({
+            node: previousImport.node,
+            message: 'There should be no empty line within import group',
+            fix: removeNewLineAfterImport(context, currentImport, previousImport),
+          });
+        }
       }
     } else if (emptyLinesBetween > 0) {
       context.report({
@@ -544,6 +551,9 @@ function getAlphabetizeConfig(options) {
   return { order, caseInsensitive };
 }
 
+// TODO, semver-major: Change the default of "distinctGroup" from true to false
+const defaultDistinctGroup = true;
+
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -562,6 +572,10 @@ module.exports = {
           pathGroupsExcludedImportTypes: {
             type: 'array',
           },
+          distinctGroup: {
+            type: 'boolean',
+            default: defaultDistinctGroup,
+          },
           pathGroups: {
             type: 'array',
             items: {
@@ -582,6 +596,7 @@ module.exports = {
                   enum: ['after', 'before'],
                 },
               },
+              additionalProperties: false,
               required: ['pattern', 'group'],
             },
           },
@@ -622,6 +637,7 @@ module.exports = {
     const newlinesBetweenImports = options['newlines-between'] || 'ignore';
     const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external', 'object']);
     const alphabetize = getAlphabetizeConfig(options);
+    const distinctGroup = options.distinctGroup == null ? defaultDistinctGroup : !!options.distinctGroup;
     let ranks;
 
     try {
@@ -724,7 +740,7 @@ module.exports = {
       'Program:exit': function reportAndReset() {
         importMap.forEach((imported) => {
           if (newlinesBetweenImports !== 'ignore') {
-            makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
+            makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, distinctGroup);
           }
 
           if (alphabetize.order !== 'ignore') {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index ed4879ac44..75c19d4152 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -925,6 +925,161 @@ ruleTester.run('order', rule, {
         },
       },
     }),
+    // Option pathGroup[].distinctGroup: 'true' does not prevent 'position' properties from affecting the visible grouping
+    test({
+      code: `
+        import A from 'a';
+
+        import C from 'c';
+
+        import B from 'b';
+      `,
+      options: [
+        {
+          'newlines-between': 'always',
+          'distinctGroup': true,
+          'pathGroupsExcludedImportTypes': [],
+          'pathGroups': [
+            {
+              'pattern': 'a',
+              'group': 'external',
+              'position': 'before',
+            },
+            {
+              'pattern': 'b',
+              'group': 'external',
+              'position': 'after',
+            },
+          ],
+        },
+      ],
+    }),
+    // Option pathGroup[].distinctGroup: 'false' should prevent 'position' properties from affecting the visible grouping
+    test({
+      code: `
+        import A from 'a';
+        import C from 'c';
+        import B from 'b';
+      `,
+      options: [
+        {
+          'newlines-between': 'always',
+          'distinctGroup': false,
+          'pathGroupsExcludedImportTypes': [],
+          'pathGroups': [
+            {
+              'pattern': 'a',
+              'group': 'external',
+              'position': 'before',
+            },
+            {
+              'pattern': 'b',
+              'group': 'external',
+              'position': 'after',
+            },
+          ],
+        },
+      ],
+    }),
+    // Option pathGroup[].distinctGroup: 'false' should prevent 'position' properties from affecting the visible grouping 2
+    test({
+      code: `
+        import A from 'a';
+
+        import b from './b';
+        import B from './B';
+      `,
+      options: [
+        {
+          'newlines-between': 'always',
+          'distinctGroup': false,
+          'pathGroupsExcludedImportTypes': [],
+          'pathGroups': [
+            {
+              'pattern': 'a',
+              'group': 'external',
+            },
+            {
+              'pattern': 'b',
+              'group': 'internal',
+              'position': 'before',
+            },
+          ],
+        },
+      ],
+    }),
+    // Option pathGroup[].distinctGroup: 'false' should prevent 'position' properties from affecting the visible grouping 3
+    test({
+      code: `
+        import A from "baz";
+        import B from "Bar";
+        import C from "Foo";
+
+        import D from "..";
+        import E from "../";
+        import F from "../baz";
+        import G from "../Bar";
+        import H from "../Foo";
+
+        import I from ".";
+        import J from "./baz";
+        import K from "./Bar";
+        import L from "./Foo";
+      `,
+      options: [
+        {
+          'alphabetize': {
+            'caseInsensitive': false,
+            'order': 'asc',
+          },
+          'newlines-between': 'always',
+          'groups': [
+            ['builtin', 'external', 'internal', 'unknown', 'object', 'type'],
+            'parent',
+            ['sibling', 'index'],
+          ],
+          'distinctGroup': false,
+          'pathGroupsExcludedImportTypes': [],
+          'pathGroups': [
+            {
+              'pattern': './',
+              'group': 'sibling',
+              'position': 'before',
+            },
+            {
+              'pattern': '.',
+              'group': 'sibling',
+              'position': 'before',
+            },
+            {
+              'pattern': '..',
+              'group': 'parent',
+              'position': 'before',
+            },
+            {
+              'pattern': '../',
+              'group': 'parent',
+              'position': 'before',
+            },
+            {
+              'pattern': '[a-z]*',
+              'group': 'external',
+              'position': 'before',
+            },
+            {
+              'pattern': '../[a-z]*',
+              'group': 'parent',
+              'position': 'before',
+            },
+            {
+              'pattern': './[a-z]*',
+              'group': 'sibling',
+              'position': 'before',
+            },
+          ],
+        },
+      ],
+    }),
   ],
   invalid: [
     // builtin before external module (require)
@@ -2439,6 +2594,62 @@ ruleTester.run('order', rule, {
         message: '`..` import should occur before import of `../a`',
       }],
     }),
+    // Option pathGroup[].distinctGroup: 'false' should error when newlines are incorrect 2
+    test({
+      code: `
+        import A from 'a';
+        import C from './c';
+      `,
+      output: `
+        import A from 'a';
+
+        import C from './c';
+      `,
+      options: [
+        {
+          'newlines-between': 'always',
+          'distinctGroup': false,
+          'pathGroupsExcludedImportTypes': [],
+        },
+      ],
+      errors: [{
+        message: 'There should be at least one empty line between import groups',
+      }],
+    }),
+    // Option pathGroup[].distinctGroup: 'false' should error when newlines are incorrect 2
+    test({
+      code: `
+        import A from 'a';
+
+        import C from 'c';
+      `,
+      output: `
+        import A from 'a';
+        import C from 'c';
+      `,
+      options: [
+        {
+          'newlines-between': 'always',
+          'distinctGroup': false,
+          'pathGroupsExcludedImportTypes': [],
+          'pathGroups': [
+            {
+              'pattern': 'a',
+              'group': 'external',
+              'position': 'before',
+            },
+            {
+              'pattern': 'c',
+              'group': 'external',
+              'position': 'after',
+            },
+          ],
+        },
+      ],
+      errors: [{
+        message: 'There should be no empty line within import group',
+      }],
+    }),
     // Alphabetize with require
     ...semver.satisfies(eslintPkg.version, '< 3.0.0') ? [] : [
       test({

From 404f48253272fdfe552e0e60e59f5c24c474137a Mon Sep 17 00:00:00 2001
From: Max Burmagin <mhmad.hamster@gmail.com>
Date: Sat, 18 Dec 2021 17:59:22 +0300
Subject: [PATCH 505/767] [Tests] `dynamic-import-chunkname`: remove unused
 "errors" from valid tests

---
 tests/src/rules/dynamic-import-chunkname.js | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index 7e482cf03c..2731084f04 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -53,10 +53,6 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       options: pickyCommentOptions,
-      errors: [{
-        message: pickyCommentFormatError,
-        type: 'CallExpression',
-      }],
     },
     {
       code: `import(
@@ -147,10 +143,6 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options: pickyCommentOptions,
       parser,
-      errors: [{
-        message: pickyCommentFormatError,
-        type: 'CallExpression',
-      }],
     },
     ...SYNTAX_CASES,
   ],

From 47b529e0ac127f8e203bbb2d3f46d821cf43341e Mon Sep 17 00:00:00 2001
From: Max Burmagin <mhmad.hamster@gmail.com>
Date: Sat, 18 Dec 2021 17:59:22 +0300
Subject: [PATCH 506/767] [Fix] `dynamic-import-chunkname`: add handling
 webpack magic comments

---
 CHANGELOG.md                                |    3 +
 src/rules/dynamic-import-chunkname.js       |    6 +-
 tests/src/rules/dynamic-import-chunkname.js | 1017 ++++++++++++++++++-
 3 files changed, 971 insertions(+), 55 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27c59ac032..5f9cfc0a1a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: require with member expression could not be fixed if alphabetize.order was used ([#2490], thanks [@msvab])
 - [`order`]: leave more space in rankings for consecutive path groups ([#2506], thanks [@Pearce-Ropion])
 - [`no-cycle`]: add ExportNamedDeclaration statements to dependencies ([#2511], thanks [@BenoitZugmeyer])
+- [`dynamic-import-chunkname`]: prevent false report on a valid webpack magic comment ([#2330], thanks [@mhmadhamster])
 
 ### Changed
 - [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -1027,6 +1028,7 @@ for info on changes for earlier releases.
 [#2358]: https://github.com/import-js/eslint-plugin-import/pull/2358
 [#2341]: https://github.com/import-js/eslint-plugin-import/pull/2341
 [#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
+[#2330]: https://github.com/import-js/eslint-plugin-import/pull/2330
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
 [#2299]: https://github.com/import-js/eslint-plugin-import/pull/2299
 [#2297]: https://github.com/import-js/eslint-plugin-import/pull/2297
@@ -1652,6 +1654,7 @@ for info on changes for earlier releases.
 [@maxkomarychev]: https://github.com/maxkomarychev
 [@maxmalov]: https://github.com/maxmalov
 [@mgwalker]: https://github.com/mgwalker
+[@mhmadhamster]: https://github.com/MhMadHamster
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@mplewis]: https://github.com/mplewis
 [@mrmckeb]: https://github.com/mrmckeb
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 859e9fea46..2c59d35e59 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -27,10 +27,10 @@ module.exports = {
   create(context) {
     const config = context.options[0];
     const { importFunctions = [] } = config || {};
-    const { webpackChunknameFormat = '[0-9a-zA-Z-_/.]+' } = config || {};
+    const { webpackChunknameFormat = '([0-9a-zA-Z-_/.]|\\[(request|index)\\])+' } = config || {};
 
     const paddedCommentRegex = /^ (\S[\s\S]+\S) $/;
-    const commentStyleRegex = /^( \w+: (["'][^"']*["']|\d+|false|true),?)+ $/;
+    const commentStyleRegex = /^( ((webpackChunkName: .+)|((webpackPrefetch|webpackPreload): (true|false|-?[0-9]+))|(webpackIgnore: (true|false))|((webpackInclude|webpackExclude): \/.*\/)|(webpackMode: ["'](lazy|lazy-once|eager|weak)["'])|(webpackExports: (['"]\w+['"]|\[(['"]\w+['"], *)+(['"]\w+['"]*)\]))),?)+ $/;
     const chunkSubstrFormat = ` webpackChunkName: ["']${webpackChunknameFormat}["'],? `;
     const chunkSubstrRegex = new RegExp(chunkSubstrFormat);
 
@@ -83,7 +83,7 @@ module.exports = {
           context.report({
             node,
             message:
-              `dynamic imports require a leading comment in the form /*${chunkSubstrFormat}*/`,
+              `dynamic imports require a "webpack" comment with valid syntax`,
           });
           return;
         }
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index 2731084f04..46a1b97afe 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -5,7 +5,7 @@ import semver from 'semver';
 const rule = require('rules/dynamic-import-chunkname');
 const ruleTester = new RuleTester();
 
-const commentFormat = '[0-9a-zA-Z-_/.]+';
+const commentFormat = '([0-9a-zA-Z-_/.]|\\[(request|index)\\])+';
 const pickyCommentFormat = '[a-zA-Z-_/.]+';
 const options = [{ importFunctions: ['dynamicImport'] }];
 const pickyCommentOptions = [{
@@ -21,8 +21,9 @@ const noLeadingCommentError = 'dynamic imports require a leading comment with th
 const nonBlockCommentError = 'dynamic imports require a /* foo */ style comment, not a // foo comment';
 const noPaddingCommentError = 'dynamic imports require a block comment padded with spaces - /* foo */';
 const invalidSyntaxCommentError = 'dynamic imports require a "webpack" comment with valid syntax';
-const commentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${commentFormat}["'],? */`;
-const pickyCommentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${pickyCommentFormat}["'],? */`;
+const commentFormatError = `dynamic imports require a "webpack" comment with valid syntax`;
+const chunkNameFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${commentFormat}["'],? */`;
+const pickyChunkNameFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${pickyCommentFormat}["'],? */`;
 
 ruleTester.run('dynamic-import-chunkname', rule, {
   valid: [
@@ -54,6 +55,34 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options: pickyCommentOptions,
     },
+    {
+      code: `dynamicImport(
+        /* webpackChunkName: "[request]" */
+        'someModule'
+      )`,
+      options,
+    },
+    {
+      code: `dynamicImport(
+        /* webpackChunkName: "my-chunk-[request]-custom" */
+        'someModule'
+      )`,
+      options,
+    },
+    {
+      code: `dynamicImport(
+        /* webpackChunkName: '[index]' */
+        'someModule'
+      )`,
+      options,
+    },
+    {
+      code: `dynamicImport(
+        /* webpackChunkName: 'my-chunk.[index].with-index' */
+        'someModule'
+      )`,
+      options,
+    },
     {
       code: `import(
         /* webpackChunkName: "someModule" */
@@ -128,6 +157,24 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       options,
       parser,
     },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackPrefetch: 12 */
+        'test'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackPrefetch: -30 */
+        'test'
+      )`,
+      options,
+      parser,
+    },
     {
       code: `import(
         /* webpackChunkName: 'someModule' */
@@ -144,6 +191,217 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       options: pickyCommentOptions,
       parser,
     },
+    {
+      code: `import(
+        /* webpackChunkName: "[request]" */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "my-chunk-[request]-custom" */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: '[index]' */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: 'my-chunk.[index].with-index' */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackInclude: /\\.json$/ */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule", webpackInclude: /\\.json$/ */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackExclude: /\\.json$/ */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule", webpackExclude: /\\.json$/ */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackPreload: true */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackPreload: 0 */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackPreload: -2 */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule", webpackPreload: false */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackIgnore: false */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule", webpackIgnore: true */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackMode: "lazy" */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: 'someModule', webpackMode: 'lazy' */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackMode: "lazy-once" */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackMode: "eager" */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackMode: "weak" */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackExports: "default" */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule", webpackExports: "named" */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackExports: ["default", "named"] */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: 'someModule', webpackExports: ['default', 'named'] */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackInclude: /\\.json$/ */
+        /* webpackExclude: /\\.json$/ */
+        /* webpackPrefetch: true */
+        /* webpackPreload: true */
+        /* webpackIgnore: false */
+        /* webpackMode: "eager" */
+        /* webpackExports: ["default", "named"] */
+        'someModule'
+      )`,
+      options,
+      parser,
+    },
     ...SYNTAX_CASES,
   ],
 
@@ -256,79 +514,77 @@ ruleTester.run('dynamic-import-chunkname', rule, {
     },
     {
       code: `import(
-        /*webpackChunkName: "someModule"*/
+        /* webpackChunkName: true */
         'someModule'
       )`,
       options,
       parser,
       output: `import(
-        /*webpackChunkName: "someModule"*/
+        /* webpackChunkName: true */
         'someModule'
       )`,
       errors: [{
-        message: noPaddingCommentError,
+        message: chunkNameFormatError,
         type: 'CallExpression',
       }],
     },
     {
       code: `import(
-        /* webpackChunkName  :  "someModule" */
+        /* webpackChunkName: "my-module-[id]" */
         'someModule'
       )`,
       options,
       parser,
       output: `import(
-        /* webpackChunkName  :  "someModule" */
+        /* webpackChunkName: "my-module-[id]" */
         'someModule'
       )`,
       errors: [{
-        message: commentFormatError,
+        message: chunkNameFormatError,
         type: 'CallExpression',
       }],
     },
     {
       code: `import(
-        /* webpackChunkName: "someModule" ; */
+        /* webpackChunkName: ["request"] */
         'someModule'
       )`,
       options,
       parser,
       output: `import(
-        /* webpackChunkName: "someModule" ; */
+        /* webpackChunkName: ["request"] */
         'someModule'
       )`,
       errors: [{
-        message: invalidSyntaxCommentError,
+        message: chunkNameFormatError,
         type: 'CallExpression',
       }],
     },
     {
       code: `import(
-        /* totally not webpackChunkName: "someModule" */
+        /*webpackChunkName: "someModule"*/
         'someModule'
       )`,
       options,
       parser,
       output: `import(
-        /* totally not webpackChunkName: "someModule" */
+        /*webpackChunkName: "someModule"*/
         'someModule'
       )`,
       errors: [{
-        message: invalidSyntaxCommentError,
+        message: noPaddingCommentError,
         type: 'CallExpression',
       }],
     },
     {
       code: `import(
-        /* webpackPrefetch: true */
-        /* webpackChunk: "someModule" */
+        /* webpackChunkName  :  "someModule" */
         'someModule'
       )`,
       options,
       parser,
       output: `import(
-        /* webpackPrefetch: true */
-        /* webpackChunk: "someModule" */
+        /* webpackChunkName  :  "someModule" */
         'someModule'
       )`,
       errors: [{
@@ -338,33 +594,259 @@ ruleTester.run('dynamic-import-chunkname', rule, {
     },
     {
       code: `import(
-        /* webpackPrefetch: true, webpackChunk: "someModule" */
+        /* webpackChunkName: "someModule" ; */
         'someModule'
       )`,
       options,
       parser,
       output: `import(
-        /* webpackPrefetch: true, webpackChunk: "someModule" */
+        /* webpackChunkName: "someModule" ; */
         'someModule'
       )`,
       errors: [{
-        message: commentFormatError,
+        message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
     },
     {
       code: `import(
-        /* webpackChunkName: "someModule123" */
+        /* totally not webpackChunkName: "someModule" */
         'someModule'
       )`,
-      options: pickyCommentOptions,
+      options,
       parser,
       output: `import(
-        /* webpackChunkName: "someModule123" */
+        /* totally not webpackChunkName: "someModule" */
         'someModule'
       )`,
       errors: [{
-        message: pickyCommentFormatError,
+        message: invalidSyntaxCommentError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackPrefetch: true */
+        /* webpackChunk: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackPrefetch: true */
+        /* webpackChunk: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackPrefetch: true, webpackChunk: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackPrefetch: true, webpackChunk: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule123" */
+        'someModule'
+      )`,
+      options: pickyCommentOptions,
+      parser,
+      output: `import(
+        /* webpackChunkName: "someModule123" */
+        'someModule'
+      )`,
+      errors: [{
+        message: pickyChunkNameFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackPrefetch: "module", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackPrefetch: "module", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackPreload: "module", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackPreload: "module", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackIgnore: "no", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackIgnore: "no", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackInclude: "someModule", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackInclude: "someModule", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackInclude: true, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackInclude: true, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackExclude: "someModule", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackExclude: "someModule", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackExclude: true, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackExclude: true, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackMode: "fast", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackMode: "fast", webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackMode: true, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackMode: true, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackExports: true, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackExports: true, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
+        type: 'CallExpression',
+      }],
+    },
+    {
+      code: `import(
+        /* webpackExports: /default/, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackExports: /default/, webpackChunkName: "someModule" */
+        'someModule'
+      )`,
+      errors: [{
+        message: commentFormatError,
         type: 'CallExpression',
       }],
     },
@@ -478,7 +960,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         'someModule'
       )`,
       errors: [{
-        message: pickyCommentFormatError,
+        message: pickyChunkNameFormatError,
         type: 'CallExpression',
       }],
     },
@@ -496,64 +978,242 @@ context('TypeScript', () => {
         {
           code: `import(
             /* webpackChunkName: "someModule" */
-            'test'
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "Some_Other_Module" */
+            "test"
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "SomeModule123" */
+            "test"
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule", webpackPrefetch: true */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule", webpackPrefetch: true, */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: true, webpackChunkName: "someModule" */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: true, webpackChunkName: "someModule", */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: true */
+            /* webpackChunkName: "someModule" */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackPrefetch: true */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackPrefetch: 11 */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackPrefetch: -11 */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options: pickyCommentOptions,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: 'someModule' */
+            'test'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "[request]" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "my-chunk-[request]-custom" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: '[index]' */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: 'my-chunk.[index].with-index' */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackInclude: /\\.json$/ */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule", webpackInclude: /\\.json$/ */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackExclude: /\\.json$/ */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule", webpackExclude: /\\.json$/ */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackPreload: true */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
         },
         {
           code: `import(
-            /* webpackChunkName: "Some_Other_Module" */
-            "test"
+            /* webpackChunkName: "someModule", webpackPreload: false */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
         },
         {
           code: `import(
-            /* webpackChunkName: "SomeModule123" */
-            "test"
+            /* webpackChunkName: "someModule" */
+            /* webpackIgnore: false */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
         },
         {
           code: `import(
-            /* webpackChunkName: "someModule", webpackPrefetch: true */
-            'test'
+            /* webpackChunkName: "someModule", webpackIgnore: true */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
         },
         {
           code: `import(
-            /* webpackChunkName: "someModule", webpackPrefetch: true, */
-            'test'
+            /* webpackChunkName: "someModule" */
+            /* webpackMode: "lazy" */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
         },
         {
           code: `import(
-            /* webpackPrefetch: true, webpackChunkName: "someModule" */
-            'test'
+            /* webpackChunkName: 'someModule', webpackMode: 'lazy' */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
         },
         {
           code: `import(
-            /* webpackPrefetch: true, webpackChunkName: "someModule", */
-            'test'
+            /* webpackChunkName: "someModule" */
+            /* webpackMode: "lazy-once" */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
         },
         {
           code: `import(
-            /* webpackPrefetch: true */
             /* webpackChunkName: "someModule" */
-            'test'
+            /* webpackMode: "eager" */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
@@ -561,8 +1221,8 @@ context('TypeScript', () => {
         {
           code: `import(
             /* webpackChunkName: "someModule" */
-            /* webpackPrefetch: true */
-            'test'
+            /* webpackMode: "weak" */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
@@ -570,19 +1230,48 @@ context('TypeScript', () => {
         {
           code: `import(
             /* webpackChunkName: "someModule" */
+            /* webpackExports: "default" */
             'someModule'
           )`,
-          options: pickyCommentOptions,
+          options,
           parser: typescriptParser,
-          errors: [{
-            message: pickyCommentFormatError,
-            type: nodeType,
-          }],
         },
         {
           code: `import(
-            /* webpackChunkName: 'someModule' */
-            'test'
+            /* webpackChunkName: "someModule", webpackExports: "named" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackExports: ["default", "named"] */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: 'someModule', webpackExports: ['default', 'named'] */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule" */
+            /* webpackInclude: /\\.json$/ */
+            /* webpackExclude: /\\.json$/ */
+            /* webpackPrefetch: true */
+            /* webpackPreload: true */
+            /* webpackIgnore: false */
+            /* webpackMode: "eager" */
+            /* webpackExports: ["default", "named"] */
+            'someModule'
           )`,
           options,
           parser: typescriptParser,
@@ -793,6 +1482,54 @@ context('TypeScript', () => {
             type: nodeType,
           }],
         },
+        {
+          code: `import(
+            /* webpackChunkName: true */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName: true */
+            'someModule'
+          )`,
+          errors: [{
+            message: chunkNameFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName: "my-module-[id]" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName: "my-module-[id]" */
+            'someModule'
+          )`,
+          errors: [{
+            message: chunkNameFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackChunkName: ["request"] */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName: ["request"] */
+            'someModule'
+          )`,
+          errors: [{
+            message: chunkNameFormatError,
+            type: nodeType,
+          }],
+        },
         {
           code: `import(
             /* webpackChunkName: "someModule123" */
@@ -805,7 +1542,183 @@ context('TypeScript', () => {
             'someModule'
           )`,
           errors: [{
-            message: pickyCommentFormatError,
+            message: pickyChunkNameFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackPrefetch: "module", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackPrefetch: "module", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackPreload: "module", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackPreload: "module", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackIgnore: "no", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackIgnore: "no", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackInclude: "someModule", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackInclude: "someModule", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackInclude: true, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackInclude: true, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackExclude: "someModule", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackExclude: "someModule", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackExclude: true, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackExclude: true, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackMode: "fast", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackMode: "fast", webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackMode: true, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackMode: true, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackExports: true, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackExports: true, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
+            type: nodeType,
+          }],
+        },
+        {
+          code: `import(
+            /* webpackExports: /default/, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackExports: /default/, webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+          errors: [{
+            message: commentFormatError,
             type: nodeType,
           }],
         },

From 7be127d7fdd911ad451211965687ba5378a162cb Mon Sep 17 00:00:00 2001
From: Andreas Opferkuch <andreas.opferkuch@gmail.com>
Date: Tue, 5 Apr 2022 11:41:53 +0200
Subject: [PATCH 507/767] [Docs] `no-useless-path-segments`: fix paths

---
 CHANGELOG.md                           | 2 ++
 docs/rules/no-useless-path-segments.md | 9 +++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f9cfc0a1a..d710b71bc3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [readme] clarify `eslint-import-resolver-typescript` usage ([#2503], thanks [@JounQin])
 - [Refactor] `no-cycle`: Add per-run caching of traversed paths ([#2419], thanks [@nokel81])
 - [Performance] `ExportMap`: add caching after parsing for an ambiguous module ([#2531], thanks [@stenin-nikita])
+- [Docs] `no-useless-path-segments`: fix paths ([#2424] thanks [@s-h-a-d-o-w])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1011,6 +1012,7 @@ for info on changes for earlier releases.
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
+[#2424]: https://github.com/import-js/eslint-plugin-import/pull/2424
 [#2419]: https://github.com/import-js/eslint-plugin-import/pull/2419
 [#2417]: https://github.com/import-js/eslint-plugin-import/pull/2417
 [#2411]: https://github.com/import-js/eslint-plugin-import/pull/2411
diff --git a/docs/rules/no-useless-path-segments.md b/docs/rules/no-useless-path-segments.md
index 81b56579c1..5f01dcb4a2 100644
--- a/docs/rules/no-useless-path-segments.md
+++ b/docs/rules/no-useless-path-segments.md
@@ -14,6 +14,7 @@ my-project
 └── helpers.js
 └── helpers
     └── index.js
+├── index.js
 └── pages
     ├── about.js
     ├── contact.js
@@ -27,10 +28,10 @@ The following patterns are considered problems:
  *  in my-project/app.js
  */
 
-import "./../pages/about.js"; // should be "./pages/about.js"
-import "./../pages/about"; // should be "./pages/about"
-import "../pages/about.js"; // should be "./pages/about.js"
-import "../pages/about"; // should be "./pages/about"
+import "./../my-project/pages/about.js"; // should be "./pages/about.js"
+import "./../my-project/pages/about"; // should be "./pages/about"
+import "../my-project/pages/about.js"; // should be "./pages/about.js"
+import "../my-project/pages/about"; // should be "./pages/about"
 import "./pages//about"; // should be "./pages/about"
 import "./pages/"; // should be "./pages"
 import "./pages/index"; // should be "./pages" (except if there is a ./pages.js file)

From 9f401a8f7e049a3f16fa2e453eca62126ffd3af6 Mon Sep 17 00:00:00 2001
From: George Reith <georeith@gmail.com>
Date: Thu, 21 Apr 2022 12:09:02 +0100
Subject: [PATCH 508/767] [Tests] `no-cycle`: add passing test cases

---
 CHANGELOG.md                              | 11 +++++++----
 tests/files/cycles/ignore/.eslintrc       |  5 +++++
 tests/files/cycles/ignore/index.js        |  2 ++
 tests/files/cycles/intermediate-ignore.js |  2 ++
 tests/src/rules/no-cycle.js               | 18 ++++++++++++++++++
 5 files changed, 34 insertions(+), 4 deletions(-)
 create mode 100644 tests/files/cycles/ignore/.eslintrc
 create mode 100644 tests/files/cycles/ignore/index.js
 create mode 100644 tests/files/cycles/intermediate-ignore.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d710b71bc3..f1bbceb50f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,15 +23,16 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`dynamic-import-chunkname`]: prevent false report on a valid webpack magic comment ([#2330], thanks [@mhmadhamster])
 
 ### Changed
-- [Tests] `named`: Run all TypeScript test ([#2427], thanks [@ProdigySim])
+- [Tests] [`named`]: Run all TypeScript test ([#2427], thanks [@ProdigySim])
 - [readme] note use of typescript in readme `import/extensions` section ([#2440], thanks [@OutdatedVersion])
-- [Docs] `order`: use correct default value ([#2392], thanks [@hyperupcall])
+- [Docs] [`order`]: use correct default value ([#2392], thanks [@hyperupcall])
 - [meta] replace git.io link in comments with the original URL ([#2444], thanks [@liby])
 - [Docs] remove global install in readme ([#2412], thanks [@aladdin-add])
 - [readme] clarify `eslint-import-resolver-typescript` usage ([#2503], thanks [@JounQin])
-- [Refactor] `no-cycle`: Add per-run caching of traversed paths ([#2419], thanks [@nokel81])
+- [Refactor] [`no-cycle`]: Add per-run caching of traversed paths ([#2419], thanks [@nokel81])
 - [Performance] `ExportMap`: add caching after parsing for an ambiguous module ([#2531], thanks [@stenin-nikita])
-- [Docs] `no-useless-path-segments`: fix paths ([#2424] thanks [@s-h-a-d-o-w])
+- [Docs] [`no-useless-path-segments`]: fix paths ([#2424], thanks [@s-h-a-d-o-w])
+- [Tests] [`no-cycle`]: add passing test cases ([#2438], thanks [@georeith])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1011,6 +1012,7 @@ for info on changes for earlier releases.
 [#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
+[#2438]: https://github.com/import-js/eslint-plugin-import/pull/2438
 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
 [#2424]: https://github.com/import-js/eslint-plugin-import/pull/2424
 [#2419]: https://github.com/import-js/eslint-plugin-import/pull/2419
@@ -1583,6 +1585,7 @@ for info on changes for earlier releases.
 [@futpib]: https://github.com/futpib
 [@gajus]: https://github.com/gajus
 [@gausie]: https://github.com/gausie
+[@georeith]: https://github.com/georeith
 [@gavriguy]: https://github.com/gavriguy
 [@giodamelio]: https://github.com/giodamelio
 [@golopot]: https://github.com/golopot
diff --git a/tests/files/cycles/ignore/.eslintrc b/tests/files/cycles/ignore/.eslintrc
new file mode 100644
index 0000000000..896eda6a31
--- /dev/null
+++ b/tests/files/cycles/ignore/.eslintrc
@@ -0,0 +1,5 @@
+{
+  "rules": {
+    "import/no-cycle": 0
+  }
+}
diff --git a/tests/files/cycles/ignore/index.js b/tests/files/cycles/ignore/index.js
new file mode 100644
index 0000000000..211fd972f6
--- /dev/null
+++ b/tests/files/cycles/ignore/index.js
@@ -0,0 +1,2 @@
+import { foo } from "../depth-zero";
+export { foo };
diff --git a/tests/files/cycles/intermediate-ignore.js b/tests/files/cycles/intermediate-ignore.js
new file mode 100644
index 0000000000..1ba6fba79b
--- /dev/null
+++ b/tests/files/cycles/intermediate-ignore.js
@@ -0,0 +1,2 @@
+import foo from "./ignore";
+export { foo };
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 233cae613b..de0083f563 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -267,5 +267,23 @@ ruleTester.run('no-cycle', rule, {
       parser: parsers.BABEL_OLD,
       errors: [error(`Dependency cycle via ./flow-types-depth-two:4=>./es6/depth-one:1`)],
     }),
+    test({
+      code: 'import { foo } from "./intermediate-ignore"',
+      errors: [
+        {
+          message: 'Dependency cycle via ./ignore:1',
+          line: 1,
+        },
+      ],
+    }),
+    test({
+      code: 'import { foo } from "./ignore"',
+      errors: [
+        {
+          message: 'Dependency cycle detected.',
+          line: 1,
+        },
+      ],
+    }),
   ),
 });

From 04e114b686bd5acab887ebacaa3b178ea264c96a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 27 Aug 2022 22:23:53 -0700
Subject: [PATCH 509/767] [Fix] `export`: do not error on TS export overloads

Fixes #1590
---
 CHANGELOG.md              |  2 ++
 src/rules/export.js       | 32 ++++++++++++++++++++++++++------
 tests/src/rules/export.js | 11 +++++++++++
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f1bbceb50f..dfa64512cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: leave more space in rankings for consecutive path groups ([#2506], thanks [@Pearce-Ropion])
 - [`no-cycle`]: add ExportNamedDeclaration statements to dependencies ([#2511], thanks [@BenoitZugmeyer])
 - [`dynamic-import-chunkname`]: prevent false report on a valid webpack magic comment ([#2330], thanks [@mhmadhamster])
+- [`export`]: do not error on TS export overloads ([#1590], thanks [@ljharb])
 
 ### Changed
 - [Tests] [`named`]: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -1341,6 +1342,7 @@ for info on changes for earlier releases.
 [#1631]: https://github.com/import-js/eslint-plugin-import/issues/1631
 [#1616]: https://github.com/import-js/eslint-plugin-import/issues/1616
 [#1613]: https://github.com/import-js/eslint-plugin-import/issues/1613
+[#1590]: https://github.com/import-js/eslint-plugin-import/issues/1590
 [#1589]: https://github.com/import-js/eslint-plugin-import/issues/1589
 [#1565]: https://github.com/import-js/eslint-plugin-import/issues/1565
 [#1366]: https://github.com/import-js/eslint-plugin-import/issues/1366
diff --git a/src/rules/export.js b/src/rules/export.js
index 4cae107402..5d430360a2 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -1,6 +1,7 @@
 import ExportMap, { recursivePatternCapture } from '../ExportMap';
 import docsUrl from '../docsUrl';
 import includes from 'array-includes';
+import flatMap from 'array.prototype.flatmap';
 
 /*
 Notes on TypeScript namespaces aka TSModuleDeclaration:
@@ -35,12 +36,31 @@ const tsTypePrefix = 'type:';
  * @returns {boolean}
  */
 function isTypescriptFunctionOverloads(nodes) {
-  const types = new Set(Array.from(nodes, node => node.parent.type));
-  return types.has('TSDeclareFunction')
-    && (
-      types.size === 1
-      || (types.size === 2 && types.has('FunctionDeclaration'))
-    );
+  const nodesArr = Array.from(nodes);
+  const types = new Set(nodesArr.map(node => node.parent.type));
+
+  const idents = flatMap(nodesArr, (node) => (
+    node.declaration && (
+      node.declaration.type === 'TSDeclareFunction' // eslint 6+
+      || node.declaration.type === 'TSEmptyBodyFunctionDeclaration' // eslint 4-5
+    )
+      ? node.declaration.id.name
+      : []
+  ));
+  if (new Set(idents).size !== idents.length) {
+    return true;
+  }
+
+  if (!types.has('TSDeclareFunction')) {
+    return false;
+  }
+  if (types.size === 1) {
+    return true;
+  }
+  if (types.size === 2 && types.has('FunctionDeclaration')) {
+    return true;
+  }
+  return false;
 }
 
 /**
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 5996e9fa3f..95093bf4a8 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -45,6 +45,17 @@ ruleTester.run('export', rule, {
         ecmaVersion: 2020,
       },
     })) || [],
+
+    getTSParsers().map((parser) => ({
+      code: `
+        export default function foo(param: string): boolean;
+        export default function foo(param: string, param1: number): boolean;
+        export default function foo(param: string, param1?: number): boolean {
+          return param && param1;
+        }
+      `,
+      parser,
+    })),
   ),
 
   invalid: [].concat(

From 0dada1ca39d0cd9b755c3a4d96f243a20961ea76 Mon Sep 17 00:00:00 2001
From: Lukas Kullmann <lukas.kullmann@maibornwolff.de>
Date: Tue, 19 Apr 2022 10:38:52 +0200
Subject: [PATCH 510/767]  [Fix] `no-unresolved`, `extensions`: ignore
 type-only exports

---
 CHANGELOG.md                     |  3 +++
 src/rules/extensions.js          |  6 +++---
 src/rules/no-unresolved.js       |  4 ++--
 tests/src/rules/extensions.js    | 17 +++++++++++++++++
 tests/src/rules/no-unresolved.js |  9 +++++++++
 5 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dfa64512cb..e349c4a0bf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-cycle`]: add ExportNamedDeclaration statements to dependencies ([#2511], thanks [@BenoitZugmeyer])
 - [`dynamic-import-chunkname`]: prevent false report on a valid webpack magic comment ([#2330], thanks [@mhmadhamster])
 - [`export`]: do not error on TS export overloads ([#1590], thanks [@ljharb])
+- [`no-unresolved`], [`extensions`]: ignore type only exports ([#2436], thanks [@Lukas-Kullmann])
 
 ### Changed
 - [Tests] [`named`]: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -1014,6 +1015,7 @@ for info on changes for earlier releases.
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
 [#2438]: https://github.com/import-js/eslint-plugin-import/pull/2438
+[#2436]: https://github.com/import-js/eslint-plugin-import/pull/2436
 [#2427]: https://github.com/import-js/eslint-plugin-import/pull/2427
 [#2424]: https://github.com/import-js/eslint-plugin-import/pull/2424
 [#2419]: https://github.com/import-js/eslint-plugin-import/pull/2419
@@ -1645,6 +1647,7 @@ for info on changes for earlier releases.
 [@loganfsmyth]: https://github.com/loganfsmyth
 [@luczsoma]: https://github.com/luczsoma
 [@ludofischer]: https://github.com/ludofischer
+[@Lukas-Kullmann]: https://github.com/Lukas-Kullmann
 [@lukeapage]: https://github.com/lukeapage
 [@lydell]: https://github.com/lydell
 [@magarcia]: https://github.com/magarcia
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 8596cbfd0f..9dad56f863 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -138,7 +138,7 @@ module.exports = {
     function checkFileExtension(source, node) {
       // bail if the declaration doesn't have a source, e.g. "export { foo };", or if it's only partially typed like in an editor
       if (!source || !source.value) return;
-      
+
       const importPathWithQueryString = source.value;
 
       // don't enforce anything on builtins
@@ -164,8 +164,8 @@ module.exports = {
       ) || isScoped(importPath);
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
-        // ignore type-only imports
-        if (node.importKind === 'type') return;
+        // ignore type-only imports and exports
+        if (node.importKind === 'type' || node.exportKind === 'type') return;
         const extensionRequired = isUseOfExtensionRequired(extension, isPackage);
         const extensionForbidden = isUseOfExtensionForbidden(extension);
         if (extensionRequired && !extensionForbidden) {
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index b9dae97c8e..dafc7cb13f 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -27,8 +27,8 @@ module.exports = {
     const options = context.options[0] || {};
 
     function checkSourceValue(source, node) {
-      // ignore type-only imports
-      if (node.importKind === 'type') {
+      // ignore type-only imports and exports
+      if (node.importKind === 'type' || node.exportKind === 'type') {
         return;
       }
 
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index cf93fac9f4..45b4498fe9 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -613,6 +613,14 @@ describe('TypeScript', () => {
             ],
             parser,
           }),
+          test({
+            code: 'export type { MyType } from "./typescript-declare";',
+            options: [
+              'always',
+              { ts: 'never', tsx: 'never', js: 'never', jsx: 'never' },
+            ],
+            parser,
+          }),
         ],
         invalid: [
           test({
@@ -624,6 +632,15 @@ describe('TypeScript', () => {
             ],
             parser,
           }),
+          test({
+            code: 'export { MyType } from "./typescript-declare";',
+            errors: ['Missing file extension for "./typescript-declare"'],
+            options: [
+              'always',
+              { ts: 'never', tsx: 'never', js: 'never', jsx: 'never' },
+            ],
+            parser,
+          }),
         ],
       });
     });
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 198d46167d..f5245a6bef 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -451,6 +451,10 @@ context('TypeScript', () => {
           code: 'import type { JSONSchema7Type } from "@types/json-schema";',
           parser,
         }),
+        test({
+          code: 'export type { JSONSchema7Type } from "@types/json-schema";',
+          parser,
+        }),
       ],
       invalid: [
         test({
@@ -458,6 +462,11 @@ context('TypeScript', () => {
           errors: [ "Unable to resolve path to module '@types/json-schema'." ],
           parser,
         }),
+        test({
+          code: 'export { JSONSchema7Type } from "@types/json-schema";',
+          errors: [ "Unable to resolve path to module '@types/json-schema'." ],
+          parser,
+        }),
       ],
     });
   });

From 5116699fa0183e35f70a07fc25d1c72be2c33c8e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 29 Aug 2022 16:00:53 -0700
Subject: [PATCH 511/767] [Tests] `order`: add passing test

Closes #2313
---
 tests/src/rules/order.js | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 75c19d4152..d143e54f9e 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2876,6 +2876,29 @@ context('TypeScript', function () {
               },
             ],
           }),
+          test({
+            code: `
+              import { useLazyQuery, useQuery } from "@apollo/client";
+              import { useEffect } from "react";
+            `,
+            options: [
+              {
+                groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'react',
+                    group: 'external',
+                    position: 'before',
+                  },
+                ],
+                'newlines-between': 'always',
+                alphabetize: {
+                  order: 'asc',
+                  caseInsensitive: true,
+                },
+              },
+            ],
+          }),
         ],
         invalid: [
           // Option alphabetize: {order: 'asc'}

From d7c4f94fbb9823d077ac923d8e5561cdbbf0f383 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 29 Aug 2022 22:14:35 -0700
Subject: [PATCH 512/767] [Tests] `no-unresolved`: fix formatting

---
 tests/src/rules/no-unresolved.js | 284 ++++++++++++++++++++-----------
 1 file changed, 181 insertions(+), 103 deletions(-)

diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index f5245a6bef..024e8965ae 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -13,12 +13,14 @@ function runResolverTests(resolver) {
   // redefine 'test' to set a resolver
   // thus 'rest'. needed something 4-chars-long for formatting simplicity
   function rest(specs) {
-    specs.settings = Object.assign({},
-      specs.settings,
-      { 'import/resolver': resolver, 'import/cache': { lifetime: 0 } },
-    );
-
-    return test(specs);
+    return test({
+      ...specs,
+      settings: {
+        ...specs.settings,
+        'import/resolver': resolver, 
+        'import/cache': { lifetime: 0 },
+      },
+    });
   }
 
   ruleTester.run(`no-unresolved (${resolver})`, rule, {
@@ -29,8 +31,10 @@ function runResolverTests(resolver) {
       rest({ code: "import bar from './bar.js';" }),
       rest({ code: "import {someThing} from './test-module';" }),
       rest({ code: "import fs from 'fs';" }),
-      rest({ code: "import('fs');",
-        parser: parsers.BABEL_OLD }),
+      rest({
+        code: "import('fs');",
+        parser: parsers.BABEL_OLD,
+      }),
 
       // check with eslint parser
       testVersion('>= 7', () => rest({
@@ -45,92 +49,146 @@ function runResolverTests(resolver) {
       rest({ code: 'let foo; export { foo }' }),
 
       // stage 1 proposal for export symmetry,
-      rest({ code: 'export * as bar from "./bar"',
-        parser: parsers.BABEL_OLD }),
-      rest({ code: 'export bar from "./bar"',
-        parser: parsers.BABEL_OLD }),
+      rest({
+        code: 'export * as bar from "./bar"',
+        parser: parsers.BABEL_OLD,
+      }),
+      rest({
+        code: 'export bar from "./bar"',
+        parser: parsers.BABEL_OLD,
+      }),
       rest({ code: 'import foo from "./jsx/MyUnCoolComponent.jsx"' }),
 
       // commonjs setting
-      rest({ code: 'var foo = require("./bar")',
-        options: [{ commonjs: true }] }),
-      rest({ code: 'require("./bar")',
-        options: [{ commonjs: true }] }),
-      rest({ code: 'require("./does-not-exist")',
-        options: [{ commonjs: false }] }),
+      rest({
+        code: 'var foo = require("./bar")',
+        options: [{ commonjs: true }],
+      }),
+      rest({
+        code: 'require("./bar")',
+        options: [{ commonjs: true }],
+      }),
+      rest({
+        code: 'require("./does-not-exist")',
+        options: [{ commonjs: false }],
+      }),
       rest({ code: 'require("./does-not-exist")' }),
 
       // amd setting
-      rest({ code: 'require(["./bar"], function (bar) {})',
-        options: [{ amd: true }] }),
-      rest({ code: 'define(["./bar"], function (bar) {})',
-        options: [{ amd: true }] }),
-      rest({ code: 'require(["./does-not-exist"], function (bar) {})',
-        options: [{ amd: false }] }),
+      rest({
+        code: 'require(["./bar"], function (bar) {})',
+        options: [{ amd: true }],
+      }),
+      rest({
+        code: 'define(["./bar"], function (bar) {})',
+        options: [{ amd: true }],
+      }),
+      rest({
+        code: 'require(["./does-not-exist"], function (bar) {})',
+        options: [{ amd: false }],
+      }),
       // magic modules: https://github.com/requirejs/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#magic-modules
-      rest({ code: 'define(["require", "exports", "module"], function (r, e, m) { })',
-        options: [{ amd: true }] }),
+      rest({
+        code: 'define(["require", "exports", "module"], function (r, e, m) { })',
+        options: [{ amd: true }],
+      }),
 
       // don't validate without callback param
-      rest({ code: 'require(["./does-not-exist"])',
-        options: [{ amd: true }] }),
+      rest({
+        code: 'require(["./does-not-exist"])',
+        options: [{ amd: true }],
+      }),
       rest({ code: 'define(["./does-not-exist"], function (bar) {})' }),
 
       // stress tests
-      rest({ code: 'require("./does-not-exist", "another arg")',
-        options: [{ commonjs: true, amd: true }] }),
-      rest({ code: 'proxyquire("./does-not-exist")',
-        options: [{ commonjs: true, amd: true }] }),
-      rest({ code: '(function() {})("./does-not-exist")',
-        options: [{ commonjs: true, amd: true }] }),
-      rest({ code: 'define([0, foo], function (bar) {})',
-        options: [{ amd: true }] }),
-      rest({ code: 'require(0)',
-        options: [{ commonjs: true }] }),
-      rest({ code: 'require(foo)',
-        options: [{ commonjs: true }] }),
+      rest({
+        code: 'require("./does-not-exist", "another arg")',
+        options: [{ commonjs: true, amd: true }],
+      }),
+      rest({
+        code: 'proxyquire("./does-not-exist")',
+        options: [{ commonjs: true, amd: true }],
+      }),
+      rest({
+        code: '(function() {})("./does-not-exist")',
+        options: [{ commonjs: true, amd: true }],
+      }),
+      rest({
+        code: 'define([0, foo], function (bar) {})',
+        options: [{ amd: true }],
+      }),
+      rest({
+        code: 'require(0)',
+        options: [{ commonjs: true }],
+      }),
+      rest({
+        code: 'require(foo)',
+        options: [{ commonjs: true }],
+      }),
     ),
 
     invalid: [].concat(
       rest({
         code: 'import reallyfake from "./reallyfake/module"',
         settings: { 'import/ignore': ['^\\./fake/'] },
-        errors: [{ message: 'Unable to resolve path to module ' +
-                            '\'./reallyfake/module\'.' }],
+        errors: [
+          { message: 'Unable to resolve path to module \'./reallyfake/module\'.' },
+        ],
       }),
 
       rest({
         code: "import bar from './baz';",
-        errors: [{ message: "Unable to resolve path to module './baz'.",
-          type: 'Literal' }],
+        errors: [
+          {
+            message: "Unable to resolve path to module './baz'.",
+            type: 'Literal',
+          },
+        ],
+      }),
+      rest({
+        code: "import bar from './baz';",
+        errors: [
+          {
+            message: "Unable to resolve path to module './baz'.",
+            type: 'Literal',
+          },
+        ],
       }),
-      rest({ code: "import bar from './baz';",
-        errors: [{ message: "Unable to resolve path to module './baz'.",
-          type: 'Literal',
-        }] }),
       rest({
         code: "import bar from './empty-folder';",
-        errors: [{ message: "Unable to resolve path to module './empty-folder'.",
-          type: 'Literal',
-        }] }),
+        errors: [
+          {
+            message: "Unable to resolve path to module './empty-folder'.",
+            type: 'Literal',
+          },
+        ], 
+      }),
 
       // sanity check that this module is _not_ found without proper settings
       rest({
         code: "import { DEEP } from 'in-alternate-root';",
-        errors: [{ message: 'Unable to resolve path to ' +
-                            "module 'in-alternate-root'.",
-        type: 'Literal',
-        }] }),
+        errors: [
+          {
+            message: 'Unable to resolve path to module \'in-alternate-root\'.',
+            type: 'Literal',
+          },
+        ],
+      }),
       rest({
         code: "import('in-alternate-root').then(function({DEEP}) {});",
-        errors: [{
-          message: 'Unable to resolve path to module \'in-alternate-root\'.',
-          type: 'Literal',
-        }],
-        parser: parsers.BABEL_OLD }),
+        errors: [
+          {
+            message: 'Unable to resolve path to module \'in-alternate-root\'.',
+            type: 'Literal',
+          },
+        ],
+        parser: parsers.BABEL_OLD,
+      }),
 
-      rest({ code: 'export { foo } from "./does-not-exist"',
-        errors: ["Unable to resolve path to module './does-not-exist'."] }),
+      rest({ 
+        code: 'export { foo } from "./does-not-exist"',
+        errors: ["Unable to resolve path to module './does-not-exist'."],
+      }),
       rest({
         code: 'export * from "./does-not-exist"',
         errors: ["Unable to resolve path to module './does-not-exist'."],
@@ -139,19 +197,23 @@ function runResolverTests(resolver) {
       // check with eslint parser
       testVersion('>= 7', () => rest({
         code: "import('in-alternate-root').then(function({DEEP}) {});",
-        errors: [{
-          message: 'Unable to resolve path to module \'in-alternate-root\'.',
-          type: 'Literal',
-        }],
+        errors: [
+          {
+            message: 'Unable to resolve path to module \'in-alternate-root\'.',
+            type: 'Literal',
+          },
+        ],
         parserOptions: { ecmaVersion: 2021 },
       })) || [],
 
       // export symmetry proposal
-      rest({ code: 'export * as bar from "./does-not-exist"',
+      rest({
+        code: 'export * as bar from "./does-not-exist"',
         parser: parsers.BABEL_OLD,
         errors: ["Unable to resolve path to module './does-not-exist'."],
       }),
-      rest({ code: 'export bar from "./does-not-exist"',
+      rest({
+        code: 'export bar from "./does-not-exist"',
         parser: parsers.BABEL_OLD,
         errors: ["Unable to resolve path to module './does-not-exist'."],
       }),
@@ -160,47 +222,58 @@ function runResolverTests(resolver) {
       rest({
         code: 'var bar = require("./baz")',
         options: [{ commonjs: true }],
-        errors: [{
-          message: "Unable to resolve path to module './baz'.",
-          type: 'Literal',
-        }],
+        errors: [
+          {
+            message: "Unable to resolve path to module './baz'.",
+            type: 'Literal',
+          },
+        ],
       }),
       rest({
         code: 'require("./baz")',
         options: [{ commonjs: true }],
-        errors: [{
-          message: "Unable to resolve path to module './baz'.",
-          type: 'Literal',
-        }],
+        errors: [
+          {
+            message: "Unable to resolve path to module './baz'.",
+            type: 'Literal',
+          },
+        ],
       }),
 
       // amd
       rest({
         code: 'require(["./baz"], function (bar) {})',
         options: [{ amd: true }],
-        errors: [{
-          message: "Unable to resolve path to module './baz'.",
-          type: 'Literal',
-        }],
+        errors: [
+          {
+            message: "Unable to resolve path to module './baz'.",
+            type: 'Literal',
+          },
+        ],
       }),
       rest({
         code: 'define(["./baz"], function (bar) {})',
         options: [{ amd: true }],
-        errors: [{
-          message: "Unable to resolve path to module './baz'.",
-          type: 'Literal',
-        }],
+        errors: [
+          {
+            message: "Unable to resolve path to module './baz'.",
+            type: 'Literal',
+          },
+        ],
       }),
       rest({
         code: 'define(["./baz", "./bar", "./does-not-exist"], function (bar) {})',
         options: [{ amd: true }],
-        errors: [{
-          message: "Unable to resolve path to module './baz'.",
-          type: 'Literal',
-        },{
-          message: "Unable to resolve path to module './does-not-exist'.",
-          type: 'Literal',
-        }],
+        errors: [
+          {
+            message: "Unable to resolve path to module './baz'.",
+            type: 'Literal',
+          },
+          {
+            message: "Unable to resolve path to module './does-not-exist'.",
+            type: 'Literal',
+          },
+        ],
       }),
     ),
   });
@@ -286,19 +359,24 @@ ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
       code: "import { DEEP } from 'in-alternate-root';",
       settings: {
         'import/resolve': {
-          'paths': [path.join( process.cwd()
-            , 'tests', 'files', 'alternate-root')],
+          'paths': [
+            path.join(process.cwd(), 'tests', 'files', 'alternate-root'),
+          ],
         },
       },
     }),
 
     test({
-      code: "import { DEEP } from 'in-alternate-root'; " +
-            "import { bar } from 'src-bar';",
-      settings: { 'import/resolve': { 'paths': [
-        path.join('tests', 'files', 'src-root'),
-        path.join('tests', 'files', 'alternate-root'),
-      ] } } }),
+      code: "import { DEEP } from 'in-alternate-root'; import { bar } from 'src-bar';",
+      settings: {
+        'import/resolve': {
+          paths: [
+            path.join('tests', 'files', 'src-root'),
+            path.join('tests', 'files', 'alternate-root'),
+          ], 
+        },
+      },
+    }),
 
     test({
       code: 'import * as foo from "jsx-module/foo"',
@@ -332,9 +410,9 @@ ruleTester.run('no-unresolved (webpack-specific)', rule, {
       // default webpack config in files/webpack.config.js knows about jsx
       code: 'import * as foo from "jsx-module/foo"',
       settings: {
-        'import/resolver': { 'webpack': { 'config': 'webpack.empty.config.js' } },
+        'import/resolver': { webpack: { config: 'webpack.empty.config.js' } },
       },
-      errors: [ "Unable to resolve path to module 'jsx-module/foo'." ],
+      errors: ["Unable to resolve path to module 'jsx-module/foo'."],
     }),
   ],
 });
@@ -366,13 +444,13 @@ ruleTester.run('no-unresolved ignore list', rule, {
     test({
       code: 'import "./test.gif"',
       options: [{ ignore: ['.png$'] }],
-      errors: [ "Unable to resolve path to module './test.gif'." ],
+      errors: ["Unable to resolve path to module './test.gif'."],
     }),
 
     test({
       code: 'import "./test.png"',
       options: [{ ignore: ['.gif$'] }],
-      errors: [ "Unable to resolve path to module './test.png'." ],
+      errors: ["Unable to resolve path to module './test.png'."],
     }),
   ],
 });

From 7f251b2f0f8c221dba374263d044bcc82748c486 Mon Sep 17 00:00:00 2001
From: meowtec <bertonzh@gmail.com>
Date: Thu, 27 Jan 2022 11:54:15 +0800
Subject: [PATCH 513/767] [Refactor] `no-extraneous-dependencies` improve
 performance using cache

Extracted from #2374.
---
 CHANGELOG.md                            |  3 ++
 src/rules/no-extraneous-dependencies.js | 42 ++++++++++++++++++-------
 2 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e349c4a0bf..8a04c80a0a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,6 +35,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Performance] `ExportMap`: add caching after parsing for an ambiguous module ([#2531], thanks [@stenin-nikita])
 - [Docs] [`no-useless-path-segments`]: fix paths ([#2424], thanks [@s-h-a-d-o-w])
 - [Tests] [`no-cycle`]: add passing test cases ([#2438], thanks [@georeith])
+- [Refactor] [`no-extraneous-dependencies`] improve performance using cache ([#2374], thanks [@meowtec])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1029,6 +1030,7 @@ for info on changes for earlier releases.
 [#2387]: https://github.com/import-js/eslint-plugin-import/pull/2387
 [#2381]: https://github.com/import-js/eslint-plugin-import/pull/2381
 [#2378]: https://github.com/import-js/eslint-plugin-import/pull/2378
+[#2374]: https://github.com/import-js/eslint-plugin-import/pull/2374
 [#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
 [#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
 [#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
@@ -1663,6 +1665,7 @@ for info on changes for earlier releases.
 [@Maxim-Mazurok]: https://github.com/Maxim-Mazurok
 [@maxkomarychev]: https://github.com/maxkomarychev
 [@maxmalov]: https://github.com/maxmalov
+[@meowtec]: https://github.com/meowtec
 [@mgwalker]: https://github.com/mgwalker
 [@mhmadhamster]: https://github.com/MhMadHamster
 [@MikeyBeLike]: https://github.com/MikeyBeLike
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index b54ee28bb7..4fc1a01d4b 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -1,6 +1,6 @@
 import path from 'path';
 import fs from 'fs';
-import readPkgUp from 'eslint-module-utils/readPkgUp';
+import pkgUp from 'eslint-module-utils/pkgUp';
 import minimatch from 'minimatch';
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
@@ -18,6 +18,16 @@ function arrayOrKeys(arrayOrObject) {
   return Array.isArray(arrayOrObject) ? arrayOrObject : Object.keys(arrayOrObject);
 }
 
+function readJSON(jsonPath, throwException) {
+  try {
+    return JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+  } catch (err) {
+    if (throwException) {
+      throw err;
+    }
+  }
+}
+
 function extractDepFields(pkg) {
   return {
     dependencies: pkg.dependencies || {},
@@ -30,6 +40,15 @@ function extractDepFields(pkg) {
   };
 }
 
+function getPackageDepFields(packageJsonPath, throwAtRead) {
+  if (!depFieldCache.has(packageJsonPath)) {
+    const depFields = extractDepFields(readJSON(packageJsonPath, throwAtRead));
+    depFieldCache.set(packageJsonPath, depFields);
+  }
+
+  return depFieldCache.get(packageJsonPath);
+}
+
 function getDependencies(context, packageDir) {
   let paths = [];
   try {
@@ -53,24 +72,21 @@ function getDependencies(context, packageDir) {
       // use rule config to find package.json
       paths.forEach(dir => {
         const packageJsonPath = path.join(dir, 'package.json');
-        if (!depFieldCache.has(packageJsonPath)) {
-          const depFields = extractDepFields(
-            JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')),
-          );
-          depFieldCache.set(packageJsonPath, depFields);
-        }
-        const _packageContent = depFieldCache.get(packageJsonPath);
+        const _packageContent = getPackageDepFields(packageJsonPath, true);
         Object.keys(packageContent).forEach(depsKey =>
           Object.assign(packageContent[depsKey], _packageContent[depsKey]),
         );
       });
     } else {
+      const packageJsonPath = pkgUp({
+        cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(),
+        normalize: false,
+      });
+
       // use closest package.json
       Object.assign(
         packageContent,
-        extractDepFields(
-          readPkgUp({ cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), normalize: false }).pkg,
-        ),
+        getPackageDepFields(packageJsonPath, false),
       );
     }
 
@@ -267,4 +283,8 @@ module.exports = {
       reportIfMissing(context, deps, depsOptions, node, source.value);
     }, { commonjs: true });
   },
+
+  'Program:exit': () => {
+    depFieldCache.clear();
+  },
 };

From 74f39d901a7ce39888f9261d464590f7350bc40a Mon Sep 17 00:00:00 2001
From: bwain <bwain@grubhub.com>
Date: Sat, 3 Sep 2022 01:54:08 -0500
Subject: [PATCH 514/767] [New] `no-extraneous-dependencies`: added
 includeInternal option to validate imports of internal dependencies

Fixes #1678
---
 CHANGELOG.md                                  |  2 ++
 docs/rules/no-extraneous-dependencies.md      | 12 +++++++++++-
 src/rules/no-extraneous-dependencies.js       |  9 ++++++++-
 tests/src/rules/no-extraneous-dependencies.js | 12 ++++++++++++
 4 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a04c80a0a..dd858a3afe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-restricted-paths`]: support arrays for `from` and `target` options ([#2466], thanks [@AdriAt360])
 - [`no-anonymous-default-export`]: add `allowNew` option ([#2505], thanks [@DamienCassou])
 - [`order`]: Add `distinctGroup` option ([#2395], thanks [@hyperupcall])
+- [`no-extraneous-dependencies`]: Add `includeInternal` option ([#2541], thanks [@bdwain])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -1008,6 +1009,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2541]: https://github.com/import-js/eslint-plugin-import/pull/2541
 [#2531]: https://github.com/import-js/eslint-plugin-import/pull/2531
 [#2511]: https://github.com/import-js/eslint-plugin-import/pull/2511
 [#2506]: https://github.com/import-js/eslint-plugin-import/pull/2506
diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index cdc0a913fe..4d9f035d29 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -1,7 +1,7 @@
 # import/no-extraneous-dependencies: Forbid the use of extraneous packages
 
 Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`, or `bundledDependencies`.
-The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behavior can be changed with the rule option `packageDir`.
+The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behavior can be changed with the rule option `packageDir`. Normally ignores imports of modules marked internal, but this can be changed with the rule option `includeInternal`.
 
 Modules have to be installed for this rule to work.
 
@@ -31,6 +31,12 @@ You can also use an array of globs instead of literal booleans:
 
 When using an array of globs, the setting will be set to `true` (no errors reported) if the name of the file being linted matches a single glob in the array, and `false` otherwise.
 
+There is a boolean option called `includeInternal`, which enables the checking of internal modules, which are otherwise ignored by this rule.
+
+```js
+"import/no-extraneous-dependencies": ["error", {"includeInternal": true}]
+```
+
 Also there is one more option called `packageDir`, this option is to specify the path to the folder containing package.json.
 
 If provided as a relative path string, will be computed relative to the current working directory at linter execution time. If this is not ideal (does not work with some editor integrations), consider using `__dirname` to provide a path relative to your configuration.
@@ -99,6 +105,10 @@ var isArray = require('lodash.isarray');
 /* eslint import/no-extraneous-dependencies: ["error", {"bundledDependencies": false}] */
 import foo from '"@generated/foo"';
 var foo = require('"@generated/foo"');
+
+/* eslint import/no-extraneous-dependencies: ["error", {"includeInternal": true}] */
+import foo from './foo';
+var foo = require('./foo');
 ```
 
 
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 4fc1a01d4b..2e8b7fecef 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -183,7 +183,12 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
     return;
   }
 
-  if (importType(name, context) !== 'external') {
+  const typeOfImport = importType(name, context);
+
+  if (
+    typeOfImport !== 'external'
+    && (typeOfImport !== 'internal' || !depsOptions.verifyInternalDeps)
+  ) {
     return;
   }
 
@@ -261,6 +266,7 @@ module.exports = {
           'peerDependencies': { 'type': ['boolean', 'array'] },
           'bundledDependencies': { 'type': ['boolean', 'array'] },
           'packageDir': { 'type': ['string', 'array'] },
+          'includeInternal': { 'type': ['boolean'] },
         },
         'additionalProperties': false,
       },
@@ -277,6 +283,7 @@ module.exports = {
       allowOptDeps: testConfig(options.optionalDependencies, filename) !== false,
       allowPeerDeps: testConfig(options.peerDependencies, filename) !== false,
       allowBundledDeps: testConfig(options.bundledDependencies, filename) !== false,
+      verifyInternalDeps: !!options.includeInternal,
     };
 
     return moduleVisitor((source, node) => {
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index d4e3886bed..364921db35 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -392,6 +392,18 @@ ruleTester.run('no-extraneous-dependencies', rule, {
         message: `'esm-package-not-in-pkg-json' should be listed in the project's dependencies. Run 'npm i -S esm-package-not-in-pkg-json' to add it`,
       }],
     }),
+
+    test({
+      code: 'import "not-a-dependency"',
+      settings: {
+        'import/resolver': { node: { paths: [ path.join(__dirname, '../../files') ] } },
+        'import/internal-regex': '^not-a-dependency.*',
+      },
+      options: [{ includeInternal: true }],
+      errors: [{
+        message: '\'not-a-dependency\' should be listed in the project\'s dependencies. Run \'npm i -S not-a-dependency\' to add it',
+      }],
+    }),
   ],
 });
 

From 395e26b901e321ed79f7c34ced78d293942571f7 Mon Sep 17 00:00:00 2001
From: bwain <bwain@grubhub.com>
Date: Sun, 4 Sep 2022 00:50:09 -0500
Subject: [PATCH 515/767] [New] `no-extraneous-dependencies`: added
 includeTypes option to validate type imports

Fixes #2542
---
 CHANGELOG.md                                  |  1 +
 docs/rules/no-extraneous-dependencies.md      | 10 ++++++---
 src/rules/no-extraneous-dependencies.js       |  8 ++++---
 tests/src/rules/no-extraneous-dependencies.js | 21 +++++++++++++++++++
 4 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dd858a3afe..3351937a98 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-anonymous-default-export`]: add `allowNew` option ([#2505], thanks [@DamienCassou])
 - [`order`]: Add `distinctGroup` option ([#2395], thanks [@hyperupcall])
 - [`no-extraneous-dependencies`]: Add `includeInternal` option ([#2541], thanks [@bdwain])
+- [`no-extraneous-dependencies`]: Add `includeTypes` option ([#2543], thanks [@bdwain])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index 4d9f035d29..70c08809cf 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -1,7 +1,7 @@
 # import/no-extraneous-dependencies: Forbid the use of extraneous packages
 
 Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`, or `bundledDependencies`.
-The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behavior can be changed with the rule option `packageDir`. Normally ignores imports of modules marked internal, but this can be changed with the rule option `includeInternal`.
+The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behavior can be changed with the rule option `packageDir`. Normally ignores imports of modules marked internal, but this can be changed with the rule option `includeInternal`. Type imports can be verified by specifying `includeTypes`.
 
 Modules have to be installed for this rule to work.
 
@@ -31,10 +31,10 @@ You can also use an array of globs instead of literal booleans:
 
 When using an array of globs, the setting will be set to `true` (no errors reported) if the name of the file being linted matches a single glob in the array, and `false` otherwise.
 
-There is a boolean option called `includeInternal`, which enables the checking of internal modules, which are otherwise ignored by this rule.
+There are 2 boolean options to opt into checking extra imports that are normally ignored: `includeInternal`, which enables the checking of internal modules, and `includeTypes`, which enables checking of type imports in TypeScript.
 
 ```js
-"import/no-extraneous-dependencies": ["error", {"includeInternal": true}]
+"import/no-extraneous-dependencies": ["error", {"includeInternal": true, "includeTypes": true}]
 ```
 
 Also there is one more option called `packageDir`, this option is to specify the path to the folder containing package.json.
@@ -109,6 +109,9 @@ var foo = require('"@generated/foo"');
 /* eslint import/no-extraneous-dependencies: ["error", {"includeInternal": true}] */
 import foo from './foo';
 var foo = require('./foo');
+
+/* eslint import/no-extraneous-dependencies: ["error", {"includeTypes": true}] */
+import type { MyType } from 'foo';
 ```
 
 
@@ -123,6 +126,7 @@ import test from 'ava';
 import find from 'lodash.find';
 import isArray from 'lodash.isarray';
 import foo from '"@generated/foo"';
+import type { MyType } from 'foo';
 
 /* eslint import/no-extraneous-dependencies: ["error", {"peerDependencies": true}] */
 import react from 'react';
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 2e8b7fecef..65c396e672 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -175,10 +175,10 @@ function checkDependencyDeclaration(deps, packageName, declarationStatus) {
 }
 
 function reportIfMissing(context, deps, depsOptions, node, name) {
-  // Do not report when importing types
+  // Do not report when importing types unless option is enabled
   if (
-    node.importKind === 'type' ||
-    node.importKind === 'typeof'
+    !depsOptions.verifyTypeImports &&
+    (node.importKind === 'type' || node.importKind === 'typeof')
   ) {
     return;
   }
@@ -267,6 +267,7 @@ module.exports = {
           'bundledDependencies': { 'type': ['boolean', 'array'] },
           'packageDir': { 'type': ['string', 'array'] },
           'includeInternal': { 'type': ['boolean'] },
+          'includeTypes': { 'type': ['boolean'] },
         },
         'additionalProperties': false,
       },
@@ -284,6 +285,7 @@ module.exports = {
       allowPeerDeps: testConfig(options.peerDependencies, filename) !== false,
       allowBundledDeps: testConfig(options.bundledDependencies, filename) !== false,
       verifyInternalDeps: !!options.includeInternal,
+      verifyTypeImports: !!options.includeTypes,
     };
 
     return moduleVisitor((source, node) => {
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 364921db35..c1018a9149 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -435,6 +435,18 @@ describe('TypeScript', () => {
               message: "'a' should be listed in the project's dependencies, not devDependencies.",
             }],
           }, parserConfig)),
+
+          test(Object.assign({
+            code: 'import type T from "a";',
+            options: [{ 
+              packageDir: packageDirWithTypescriptDevDependencies,
+              devDependencies: false,
+              includeTypes: true,
+            }],
+            errors: [{
+              message: "'a' should be listed in the project's dependencies, not devDependencies.",
+            }],
+          }, parserConfig)),
         ],
       });
     });
@@ -454,5 +466,14 @@ typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', r
     }),
   ],
   invalid: [
+    test({
+      code: 'import type { MyType } from "not-a-dependency";',
+      options: [{ includeTypes: true }],
+      filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      parser: parsers.BABEL_OLD,
+      errors: [{
+        message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
+      }],
+    }),
   ],
 });

From c4f3cc4dda3af1583c3e876864fd19bbb36c69ef Mon Sep 17 00:00:00 2001
From: Aaron Adams <aaron@aaronadams.ca>
Date: Fri, 4 Mar 2022 20:59:08 +0000
Subject: [PATCH 516/767] [New] `order`: new `alphabetize.orderImportKind`
 option to sort imports with same path based on their kind (`type`, `typeof`)

Fixes #2339

Co-authored-by: Aaron Adams <aaron@aaronadams.ca>
Co-authored-by: stropho <3704482+stropho@users.noreply.github.com>
---
 CHANGELOG.md             |   1 +
 docs/rules/order.md      |   3 +-
 src/rules/order.js       |  85 +++++++++++++++++++--------
 tests/src/rules/order.js | 122 ++++++++++++++++++++++++++++++++++++---
 4 files changed, 177 insertions(+), 34 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3351937a98..89ed22ac03 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: Add `distinctGroup` option ([#2395], thanks [@hyperupcall])
 - [`no-extraneous-dependencies`]: Add `includeInternal` option ([#2541], thanks [@bdwain])
 - [`no-extraneous-dependencies`]: Add `includeTypes` option ([#2543], thanks [@bdwain])
+- [`order`]: new `alphabetize.orderImportKind` option to sort imports with same path based on their kind (`type`, `typeof`) ([#2544], thanks [@stropho])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 53faff1530..c525dfbbac 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -267,11 +267,12 @@ import index from './';
 import sibling from './foo';
 ```
 
-### `alphabetize: {order: asc|desc|ignore, caseInsensitive: true|false}`:
+### `alphabetize: {order: asc|desc|ignore, orderImportKind: asc|desc|ignore, caseInsensitive: true|false}`:
 
 Sort the order within each group in alphabetical manner based on **import path**:
 
 - `order`: use `asc` to sort in ascending order, and `desc` to sort in descending order (default: `ignore`).
+- `orderImportKind`: use `asc` to sort in ascending order various import kinds, e.g. imports prefixed with `type` or `typeof`, with same import path. Use `desc` to sort in descending order (default: `ignore`).
 - `caseInsensitive`: use `true` to ignore case, and `false` to consider case (default: `false`).
 
 Example setting:
diff --git a/src/rules/order.js b/src/rules/order.js
index 95311c0bcf..e8d023dfe6 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -187,6 +187,16 @@ function canReorderItems(firstNode, secondNode) {
   return true;
 }
 
+function makeImportDescription(node) {
+  if (node.node.importKind === 'type') {
+    return 'type import';
+  }
+  if (node.node.importKind === 'typeof') {
+    return 'typeof import';
+  }
+  return 'import';
+}
+
 function fixOutOfOrder(context, firstNode, secondNode, order) {
   const sourceCode = context.getSourceCode();
 
@@ -204,7 +214,9 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
     newCode = newCode + '\n';
   }
 
-  const message = `\`${secondNode.displayName}\` import should occur ${order} import of \`${firstNode.displayName}\``;
+  const firstImport = `${makeImportDescription(firstNode)} of \`${firstNode.displayName}\``;
+  const secondImport = `\`${secondNode.displayName}\` ${makeImportDescription(secondNode)}`;
+  const message = `${secondImport} should occur ${order} ${firstImport}`;
 
   if (order === 'before') {
     context.report({
@@ -253,20 +265,36 @@ function makeOutOfOrderReport(context, imported) {
   reportOutOfOrder(context, imported, outOfOrder, 'before');
 }
 
-function getSorter(ascending) {
-  const multiplier = ascending ? 1 : -1;
+const compareString = (a, b) => {
+  if (a < b) {
+    return -1;
+  }
+  if (a > b) {
+    return 1;
+  }
+  return 0;
+};
+
+/** Some parsers (languages without types) don't provide ImportKind */
+const DEAFULT_IMPORT_KIND = 'value';
+const getNormalizedValue = (node, toLowerCase) => {
+  const value = node.value;
+  return toLowerCase ? String(value).toLowerCase() : value;
+};
+
+function getSorter(alphabetizeOptions) {
+  const multiplier = alphabetizeOptions.order === 'asc' ? 1 : -1;
+  const orderImportKind = alphabetizeOptions.orderImportKind;
+  const multiplierImportKind = orderImportKind !== 'ignore' &&
+    (alphabetizeOptions.orderImportKind === 'asc' ? 1 : -1);
 
-  return function importsSorter(importA, importB) {
+  return function importsSorter(nodeA, nodeB) {
+    const importA = getNormalizedValue(nodeA, alphabetizeOptions.caseInsensitive);
+    const importB = getNormalizedValue(nodeB, alphabetizeOptions.caseInsensitive);
     let result = 0;
 
     if (!includes(importA, '/') && !includes(importB, '/')) {
-      if (importA < importB) {
-        result = -1;
-      } else if (importA > importB) {
-        result = 1;
-      } else {
-        result = 0;
-      }
+      result = compareString(importA, importB);
     } else {
       const A = importA.split('/');
       const B = importB.split('/');
@@ -274,13 +302,8 @@ function getSorter(ascending) {
       const b = B.length;
 
       for (let i = 0; i < Math.min(a, b); i++) {
-        if (A[i] < B[i]) {
-          result = -1;
-          break;
-        } else if (A[i] > B[i]) {
-          result = 1;
-          break;
-        }
+        result = compareString(A[i], B[i]);
+        if (result) break;
       }
 
       if (!result && a !== b) {
@@ -288,7 +311,17 @@ function getSorter(ascending) {
       }
     }
 
-    return result * multiplier;
+    result = result * multiplier;
+
+    // In case the paths are equal (result === 0), sort them by importKind
+    if (!result && multiplierImportKind) {
+      result = multiplierImportKind * compareString(
+        nodeA.node.importKind || DEAFULT_IMPORT_KIND,
+        nodeB.node.importKind || DEAFULT_IMPORT_KIND,
+      );
+    }
+
+    return result;
   };
 }
 
@@ -303,14 +336,11 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
 
   const groupRanks = Object.keys(groupedByRanks);
 
-  const sorterFn = getSorter(alphabetizeOptions.order === 'asc');
-  const comparator = alphabetizeOptions.caseInsensitive
-    ? (a, b) => sorterFn(String(a.value).toLowerCase(), String(b.value).toLowerCase())
-    : (a, b) => sorterFn(a.value, b.value);
+  const sorterFn = getSorter(alphabetizeOptions);
 
   // sort imports locally within their group
   groupRanks.forEach(function (groupRank) {
-    groupedByRanks[groupRank].sort(comparator);
+    groupedByRanks[groupRank].sort(sorterFn);
   });
 
   // assign globally unique rank to each import
@@ -546,9 +576,10 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, di
 function getAlphabetizeConfig(options) {
   const alphabetize = options.alphabetize || {};
   const order = alphabetize.order || 'ignore';
+  const orderImportKind = alphabetize.orderImportKind || 'ignore';
   const caseInsensitive = alphabetize.caseInsensitive || false;
 
-  return { order, caseInsensitive };
+  return { order, orderImportKind, caseInsensitive };
 }
 
 // TODO, semver-major: Change the default of "distinctGroup" from true to false
@@ -619,6 +650,10 @@ module.exports = {
                 enum: ['ignore', 'asc', 'desc'],
                 default: 'ignore',
               },
+              orderImportKind: {
+                enum: ['ignore', 'asc', 'desc'],
+                default: 'ignore',
+              },
             },
             additionalProperties: false,
           },
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index d143e54f9e..07511ee4de 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -4,8 +4,21 @@ import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import flatMap from 'array.prototype.flatmap';
+import { resolve } from 'path';
+import { default as babelPresetFlow } from 'babel-preset-flow';
+
 
 const ruleTester = new RuleTester();
+const flowRuleTester = new RuleTester({
+  parser: resolve(__dirname, '../../../node_modules/babel-eslint'),
+  parserOptions: {
+    babelOptions: {
+      configFile: false,
+      babelrc: false,
+      presets: [babelPresetFlow],
+    },
+  },
+});
 const rule = require('rules/order');
 
 function withoutAutofixOutput(test) {
@@ -1080,6 +1093,19 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    // orderImportKind option that is not used
+    test({
+      code: `
+            import B from './B';
+            import b from './b';
+          `,
+      options: [
+        {
+          'alphabetize': { order: 'asc', orderImportKind: 'asc', 'caseInsensitive': true },
+        },
+      ],
+    }),
+
   ],
   invalid: [
     // builtin before external module (require)
@@ -2931,8 +2957,8 @@ context('TypeScript', function () {
             errors: [
               {
                 message: semver.satisfies(eslintPkg.version, '< 3')
-                  ? '`bar` import should occur after import of `Bar`'
-                  : /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,
+                  ? '`bar` import should occur after type import of `Bar`'
+                  : /(`bar` import should occur after type import of `Bar`)|(`Bar` type import should occur before import of `bar`)/,
               },
             ],
           }),
@@ -3002,10 +3028,10 @@ context('TypeScript', function () {
             ],
             errors: semver.satisfies(eslintPkg.version, '< 3') ? [
               { message: '`Bar` import should occur before import of `bar`' },
-              { message: '`Bar` import should occur before import of `foo`' },
+              { message: '`Bar` type import should occur before type import of `foo`' },
             ] : [
               { message: /(`Bar` import should occur before import of `bar`)|(`bar` import should occur after import of `Bar`)/ },
-              { message: /(`Bar` import should occur before import of `foo`)|(`foo` import should occur after import of `Bar`)/ },
+              { message: /(`Bar` type import should occur before type import of `foo`)|(`foo` type import should occur after type import of `Bar`)/ },
             ],
           }),
           // Option alphabetize: {order: 'desc'} with type group
@@ -3039,10 +3065,10 @@ context('TypeScript', function () {
             ],
             errors: semver.satisfies(eslintPkg.version, '< 3') ? [
               { message: '`bar` import should occur before import of `Bar`' },
-              { message: '`foo` import should occur before import of `Bar`' },
+              { message: '`foo` type import should occur before type import of `Bar`' },
             ] : [
               { message: /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/ },
-              { message: /(`foo` import should occur before import of `Bar`)|(`Bar` import should occur after import of `foo`)/ },
+              { message: /(`foo` type import should occur before type import of `Bar`)|(`Bar` type import should occur after import of type `foo`)/ },
             ],
           }),
           // warns for out of order unassigned imports (warnOnUnassignedImports enabled)
@@ -3113,9 +3139,9 @@ context('TypeScript', function () {
               }
             `,
             errors: [{
-              message: '`fs` import should occur before import of `path`',
+              message: '`fs` type import should occur before type import of `path`',
             },{
-              message: '`fs` import should occur before import of `path`',
+              message: '`fs` type import should occur before type import of `path`',
             }],
             ...parserConfig,
             options: [
@@ -3128,3 +3154,83 @@ context('TypeScript', function () {
       });
     });
 });
+
+flowRuleTester.run('order', rule, {
+  valid: [
+    test({
+      options: [
+        {
+          alphabetize: { order: 'asc', orderImportKind: 'asc' },
+        },
+      ],
+      code: `
+        import type {Bar} from 'common';
+        import typeof {foo} from 'common';
+        import {bar} from 'common';
+      `,
+    })],
+  invalid: [
+    test({
+      options: [
+        {
+          alphabetize: { order: 'asc', orderImportKind: 'asc' },
+        },
+      ],
+      code: `
+        import type {Bar} from 'common';
+        import {bar} from 'common';
+        import typeof {foo} from 'common';
+      `,
+      output: `
+        import type {Bar} from 'common';
+        import typeof {foo} from 'common';
+        import {bar} from 'common';
+      `,
+      errors: [{
+        message: '`common` typeof import should occur before import of `common`',
+      }],
+    }),
+    test({
+      options: [
+        {
+          alphabetize: { order: 'asc', orderImportKind: 'desc' },
+        },
+      ],
+      code: `
+        import type {Bar} from 'common';
+        import {bar} from 'common';
+        import typeof {foo} from 'common';
+      `,
+      output: `
+        import {bar} from 'common';
+        import typeof {foo} from 'common';
+        import type {Bar} from 'common';
+      `,
+      errors: [{
+        message: '`common` type import should occur after typeof import of `common`',
+      }],
+    }),
+    test({
+      options: [
+        {
+          alphabetize: { order: 'asc', orderImportKind: 'asc' },
+        },
+      ],
+      code: `
+        import type {Bar} from './local/sub';
+        import {bar} from './local/sub';
+        import {baz} from './local-sub';
+        import typeof {foo} from './local/sub';
+      `,
+      output: `
+        import type {Bar} from './local/sub';
+        import typeof {foo} from './local/sub';
+        import {bar} from './local/sub';
+        import {baz} from './local-sub';
+      `,
+      errors: [{
+        message: '`./local/sub` typeof import should occur before import of `./local/sub`',
+      }],
+    }),
+  ],
+});

From 5cf5038cd326286deaf70b5142fc3deb173744bb Mon Sep 17 00:00:00 2001
From: Brad Zacher <brad.zacher@gmail.com>
Date: Thu, 9 Jun 2022 11:04:13 -0700
Subject: [PATCH 517/767] [New] `consistent-type-specifier-style`: add rule

---
 CHANGELOG.md                                  |   3 +
 README.md                                     |   2 +
 docs/rules/consistent-type-specifier-style.md |  87 ++++
 package.json                                  |   2 +-
 src/index.js                                  |   1 +
 src/rules/consistent-type-specifier-style.js  | 216 ++++++++++
 tests/src/core/getExports.js                  |   3 +-
 .../rules/consistent-type-specifier-style.js  | 403 ++++++++++++++++++
 tests/src/utils.js                            |  17 +-
 9 files changed, 730 insertions(+), 4 deletions(-)
 create mode 100644 docs/rules/consistent-type-specifier-style.md
 create mode 100644 src/rules/consistent-type-specifier-style.js
 create mode 100644 tests/src/rules/consistent-type-specifier-style.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89ed22ac03..22a5c386b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-extraneous-dependencies`]: Add `includeInternal` option ([#2541], thanks [@bdwain])
 - [`no-extraneous-dependencies`]: Add `includeTypes` option ([#2543], thanks [@bdwain])
 - [`order`]: new `alphabetize.orderImportKind` option to sort imports with same path based on their kind (`type`, `typeof`) ([#2544], thanks [@stropho])
+- [`consistent-type-specifier-style`]: add rule ([#2473], thanks [@bradzacher])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -965,6 +966,7 @@ for info on changes for earlier releases.
 [`import/external-module-folders` setting]: ./README.md#importexternal-module-folders
 [`internal-regex` setting]: ./README.md#importinternal-regex
 
+[`consistent-type-specifier-style`]: ./docs/rules/consistent-type-specifier-style.md
 [`default`]: ./docs/rules/default.md
 [`dynamic-import-chunkname`]: ./docs/rules/dynamic-import-chunkname.md
 [`export`]: ./docs/rules/export.md
@@ -1017,6 +1019,7 @@ for info on changes for earlier releases.
 [#2506]: https://github.com/import-js/eslint-plugin-import/pull/2506
 [#2503]: https://github.com/import-js/eslint-plugin-import/pull/2503
 [#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
+[#2473]: https://github.com/import-js/eslint-plugin-import/pull/2473
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
 [#2438]: https://github.com/import-js/eslint-plugin-import/pull/2438
diff --git a/README.md b/README.md
index 329400d594..775fc198b5 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 * Forbid anonymous values as default exports ([`no-anonymous-default-export`])
 * Prefer named exports to be grouped together in a single export declaration ([`group-exports`])
 * Enforce a leading comment with the webpackChunkName for dynamic imports ([`dynamic-import-chunkname`])
+* Enforce or ban the use of inline type-only markers for named imports ([`consistent-type-specifier-style`])
 
 [`first`]: ./docs/rules/first.md
 [`exports-last`]: ./docs/rules/exports-last.md
@@ -114,6 +115,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 [`no-default-export`]: ./docs/rules/no-default-export.md
 [`no-named-export`]: ./docs/rules/no-named-export.md
 [`dynamic-import-chunkname`]: ./docs/rules/dynamic-import-chunkname.md
+[`consistent-type-specifier-style`]: ./docs/rules/consistent-type-specifier-style.md
 
 ## `eslint-plugin-import` for enterprise
 
diff --git a/docs/rules/consistent-type-specifier-style.md b/docs/rules/consistent-type-specifier-style.md
new file mode 100644
index 0000000000..4314e33867
--- /dev/null
+++ b/docs/rules/consistent-type-specifier-style.md
@@ -0,0 +1,87 @@
+# import/consistent-type-specifier-style
+
+In both Flow and TypeScript you can mark an import as a type-only import by adding a "kind" marker to the import. Both languages support two positions for marker.
+
+**At the top-level** which marks all names in the import as type-only and applies to named, default, and namespace (for TypeScript) specifiers:
+
+```ts
+import type Foo from 'Foo';
+import type {Bar} from 'Bar';
+// ts only
+import type * as Bam from 'Bam';
+// flow only
+import typeof Baz from 'Baz';
+```
+
+**Inline** with to the named import, which marks just the specific name in the import as type-only. An inline specifier is only valid for named specifiers, and not for default or namespace specifiers:
+
+```ts
+import {type Foo} from 'Foo';
+// flow only
+import {typeof Bar} from 'Bar';
+```
+
+## Rule Details
+
+This rule either enforces or bans the use of inline type-only markers for named imports.
+
+This rule includes a fixer that will automatically convert your specifiers to the correct form - however the fixer will not respect your preferences around de-duplicating imports. If this is important to you, consider using the [`import/no-duplicates`] rule.
+
+[`import/no-duplicates`]: ./no-duplicates.md
+
+## Options
+
+The rule accepts a single string option which may be one of:
+
+- `'prefer-inline'` - enforces that named type-only specifiers are only ever written with an inline marker; and never as part of a top-level, type-only import.
+- `'prefer-top-level'` - enforces that named type-only specifiers only ever written as part of a top-level, type-only import; and never with an inline marker.
+
+By default the rule will use the `prefer-inline` option.
+
+## Examples
+
+### `prefer-top-level`
+
+❌ Invalid with `["error", "prefer-top-level"]`
+
+```ts
+import {type Foo} from 'Foo';
+import Foo, {type Bar} from 'Foo';
+// flow only
+import {typeof Foo} from 'Foo';
+```
+
+✅ Valid with `["error", "prefer-top-level"]`
+
+```ts
+import type {Foo} from 'Foo';
+import type Foo, {Bar} from 'Foo';
+// flow only
+import typeof {Foo} from 'Foo';
+```
+
+### `prefer-inline`
+
+❌ Invalid with `["error", "prefer-inline"]`
+
+```ts
+import type {Foo} from 'Foo';
+import type Foo, {Bar} from 'Foo';
+// flow only
+import typeof {Foo} from 'Foo';
+```
+
+✅ Valid with `["error", "prefer-inline"]`
+
+```ts
+import {type Foo} from 'Foo';
+import Foo, {type Bar} from 'Foo';
+// flow only
+import {typeof Foo} from 'Foo';
+```
+
+## When Not To Use It
+
+If you aren't using Flow or TypeScript 4.5+, then this rule does not apply and need not be used.
+
+If you don't care about, and don't want to standardize how named specifiers are imported then you should not use this rule.
diff --git a/package.json b/package.json
index ed87332304..c3ffef586e 100644
--- a/package.json
+++ b/package.json
@@ -92,7 +92,7 @@
     "safe-publish-latest": "^2.0.0",
     "semver": "^6.3.0",
     "sinon": "^2.4.1",
-    "typescript": "^2.8.1 || ~3.9.5",
+    "typescript": "^2.8.1 || ~3.9.5 || ~4.5.2",
     "typescript-eslint-parser": "^15 || ^20 || ^22"
   },
   "peerDependencies": {
diff --git a/src/index.js b/src/index.js
index 7fa3710d64..fd83a4aaf8 100644
--- a/src/index.js
+++ b/src/index.js
@@ -12,6 +12,7 @@ export const rules = {
   'group-exports': require('./rules/group-exports'),
   'no-relative-packages': require('./rules/no-relative-packages'),
   'no-relative-parent-imports': require('./rules/no-relative-parent-imports'),
+  'consistent-type-specifier-style': require('./rules/consistent-type-specifier-style'),
 
   'no-self-import': require('./rules/no-self-import'),
   'no-cycle': require('./rules/no-cycle'),
diff --git a/src/rules/consistent-type-specifier-style.js b/src/rules/consistent-type-specifier-style.js
new file mode 100644
index 0000000000..73e0ba92f2
--- /dev/null
+++ b/src/rules/consistent-type-specifier-style.js
@@ -0,0 +1,216 @@
+import docsUrl from '../docsUrl';
+
+function isComma(token) {
+  return token.type === 'Punctuator' && token.value === ',';
+}
+
+function removeSpecifiers(fixes, fixer, sourceCode, specifiers) {
+  for (const specifier of specifiers) {
+    // remove the trailing comma
+    const comma = sourceCode.getTokenAfter(specifier, isComma);
+    if (comma) {
+      fixes.push(fixer.remove(comma));
+    }
+    fixes.push(fixer.remove(specifier));
+  }
+}
+
+function getImportText(
+  node,
+  sourceCode,
+  specifiers,
+  kind,
+) {
+  const sourceString = sourceCode.getText(node.source);
+  if (specifiers.length === 0) {
+    return '';
+  }
+
+  const names = specifiers.map(s => {
+    if (s.imported.name === s.local.name) {
+      return s.imported.name;
+    }
+    return `${s.imported.name} as ${s.local.name}`;
+  });
+  // insert a fresh top-level import
+  return `import ${kind} {${names.join(', ')}} from ${sourceString};`;
+}
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description: 'Enforce or ban the use of inline type-only markers for named imports',
+      url: docsUrl('consistent-type-specifier-style'),
+    },
+    fixable: 'code',
+    schema: [
+      {
+        type: 'string',
+        enum: ['prefer-inline', 'prefer-top-level'],
+        default: 'prefer-inline',
+      },
+    ],
+  },
+
+  create(context) {
+    const sourceCode = context.getSourceCode();
+
+    if (context.options[0] === 'prefer-inline') {
+      return {
+        ImportDeclaration(node) {
+          if (node.importKind === 'value' || node.importKind == null) {
+            // top-level value / unknown is valid
+            return;
+          }
+
+          if (
+            // no specifiers (import type {} from '') have no specifiers to mark as inline
+            node.specifiers.length === 0 ||
+            (node.specifiers.length === 1 &&
+              // default imports are both "inline" and "top-level"
+              (node.specifiers[0].type === 'ImportDefaultSpecifier' ||
+                // namespace imports are both "inline" and "top-level"
+                node.specifiers[0].type === 'ImportNamespaceSpecifier'))
+          ) {
+            return;
+          }
+
+          context.report({
+            node,
+            message: 'Prefer using inline {{kind}} specifiers instead of a top-level {{kind}}-only import.',
+            data: {
+              kind: node.importKind,
+            },
+            fix(fixer) {
+              const kindToken = sourceCode.getFirstToken(node, { skip: 1 });
+
+              return [].concat(
+                kindToken ? fixer.remove(kindToken) : [],
+                node.specifiers.map((specifier) => fixer.insertTextBefore(specifier, `${node.importKind} `)),
+              );
+            },
+          });
+        },
+      };
+    }
+
+    // prefer-top-level
+    return {
+      ImportDeclaration(node) {
+        if (
+          // already top-level is valid
+          node.importKind === 'type' ||
+          node.importKind === 'typeof' ||
+          // no specifiers (import {} from '') cannot have inline - so is valid
+          node.specifiers.length === 0 ||
+          (node.specifiers.length === 1 &&
+            // default imports are both "inline" and "top-level"
+            (node.specifiers[0].type === 'ImportDefaultSpecifier' ||
+              // namespace imports are both "inline" and "top-level"
+              node.specifiers[0].type === 'ImportNamespaceSpecifier'))
+        ) {
+          return;
+        }
+
+        const typeSpecifiers = [];
+        const typeofSpecifiers = [];
+        const valueSpecifiers = [];
+        let defaultSpecifier = null;
+        for (const specifier of node.specifiers) {
+          if (specifier.type === 'ImportDefaultSpecifier') {
+            defaultSpecifier = specifier;
+            continue;
+          }
+
+          if (specifier.importKind === 'type') {
+            typeSpecifiers.push(specifier);
+          } else if (specifier.importKind === 'typeof') {
+            typeofSpecifiers.push(specifier);
+          } else if (specifier.importKind === 'value' || specifier.importKind == null) {
+            valueSpecifiers.push(specifier);
+          }
+        }
+
+        const typeImport = getImportText(node, sourceCode, typeSpecifiers, 'type');
+        const typeofImport = getImportText(node, sourceCode, typeofSpecifiers, 'typeof');
+        const newImports = `${typeImport}\n${typeofImport}`.trim();
+
+        if (typeSpecifiers.length + typeofSpecifiers.length === node.specifiers.length) {
+          // all specifiers have inline specifiers - so we replace the entire import
+          const kind = [].concat(
+            typeSpecifiers.length > 0 ? 'type' : [],
+            typeofSpecifiers.length > 0 ? 'typeof' : [],
+          );
+
+          context.report({
+            node,
+            message: 'Prefer using a top-level {{kind}}-only import instead of inline {{kind}} specifiers.',
+            data: {
+              kind: kind.join('/'),
+            },
+            fix(fixer) {
+              return fixer.replaceText(node, newImports);
+            },
+          });
+        } else {
+          // remove specific specifiers and insert new imports for them
+          for (const specifier of typeSpecifiers.concat(typeofSpecifiers)) {
+            context.report({
+              node: specifier,
+              message: 'Prefer using a top-level {{kind}}-only import instead of inline {{kind}} specifiers.',
+              data: {
+                kind: specifier.importKind,
+              },
+              fix(fixer) {
+                const fixes = [];
+
+                // if there are no value specifiers, then the other report fixer will be called, not this one
+
+                if (valueSpecifiers.length > 0) {
+                  // import { Value, type Type } from 'mod';
+
+                  // we can just remove the type specifiers
+                  removeSpecifiers(fixes, fixer, sourceCode, typeSpecifiers);
+                  removeSpecifiers(fixes, fixer, sourceCode, typeofSpecifiers);
+
+                  // make the import nicely formatted by also removing the trailing comma after the last value import
+                  // eg
+                  // import { Value, type Type } from 'mod';
+                  // to
+                  // import { Value  } from 'mod';
+                  // not
+                  // import { Value,  } from 'mod';
+                  const maybeComma = sourceCode.getTokenAfter(valueSpecifiers[valueSpecifiers.length - 1]);
+                  if (isComma(maybeComma)) {
+                    fixes.push(fixer.remove(maybeComma));
+                  }
+                } else if (defaultSpecifier) {
+                  // import Default, { type Type } from 'mod';
+
+                  // remove the entire curly block so we don't leave an empty one behind
+                  // NOTE - the default specifier *must* be the first specifier always!
+                  //        so a comma exists that we also have to clean up or else it's bad syntax
+                  const comma = sourceCode.getTokenAfter(defaultSpecifier, isComma);
+                  const closingBrace = sourceCode.getTokenAfter(
+                    node.specifiers[node.specifiers.length - 1],
+                    token => token.type === 'Punctuator' && token.value === '}',
+                  );
+                  fixes.push(fixer.removeRange([
+                    comma.range[0],
+                    closingBrace.range[1],
+                  ]));
+                }
+
+                return fixes.concat(
+                  // insert the new imports after the old declaration
+                  fixer.insertTextAfter(node, `\n${newImports}`),
+                );
+              },
+            });
+          }
+        }
+      },
+    };
+  },
+};
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index dcfa74d835..6dea6e0210 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -2,6 +2,7 @@ import { expect } from  'chai';
 import semver from 'semver';
 import sinon from 'sinon';
 import eslintPkg from 'eslint/package.json';
+import typescriptPkg from 'typescript/package.json';
 import * as tsConfigLoader from 'tsconfig-paths/lib/tsconfig-loader';
 import ExportMap from '../../../src/ExportMap';
 
@@ -351,7 +352,7 @@ describe('ExportMap', function () {
       configs.push(['array form', { '@typescript-eslint/parser': ['.ts', '.tsx'] }]);
     }
 
-    if (semver.satisfies(eslintPkg.version, '<6')) {
+    if (semver.satisfies(eslintPkg.version, '<6') && semver.satisfies(typescriptPkg.version, '<4')) {
       configs.push(['array form', { 'typescript-eslint-parser': ['.ts', '.tsx'] }]);
     }
 
diff --git a/tests/src/rules/consistent-type-specifier-style.js b/tests/src/rules/consistent-type-specifier-style.js
new file mode 100644
index 0000000000..31a4c09ffe
--- /dev/null
+++ b/tests/src/rules/consistent-type-specifier-style.js
@@ -0,0 +1,403 @@
+import { RuleTester } from 'eslint';
+import { test, parsers, tsVersionSatisfies, eslintVersionSatisfies, typescriptEslintParserSatisfies } from '../utils';
+
+const rule = require('rules/consistent-type-specifier-style');
+
+const COMMON_TESTS = {
+  valid: [
+    //
+    // prefer-top-level
+    //
+    test({
+      code: "import Foo from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import type Foo from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import { Foo } from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import { Foo as Bar } from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import * as Foo from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import {} from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import type {} from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import type { Foo } from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import type { Foo as Bar } from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+    test({
+      code: "import type { Foo, Bar, Baz, Bam } from 'Foo';",
+      options: ['prefer-top-level'],
+    }),
+
+    //
+    // prefer-inline
+    //
+    test({
+      code: "import Foo from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import type Foo from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import { Foo } from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import { Foo as Bar } from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import * as Foo from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import {} from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import type {} from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import { type Foo } from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import { type Foo as Bar } from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+    test({
+      code: "import { type Foo, type Bar, Baz, Bam } from 'Foo';",
+      options: ['prefer-inline'],
+    }),
+  ],
+  invalid: [
+    //
+    // prefer-top-level
+    //
+    {
+      code: "import { type Foo } from 'Foo';",
+      output: "import type {Foo} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import { type Foo as Bar } from 'Foo';",
+      output: "import type {Foo as Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import { type Foo, type Bar } from 'Foo';",
+      output: "import type {Foo, Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import { Foo, type Bar } from 'Foo';",
+      output: "import { Foo  } from 'Foo';\nimport type {Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
+    {
+      code: "import { type Foo, Bar } from 'Foo';",
+      output: "import {  Bar } from 'Foo';\nimport type {Foo} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
+    {
+      code: "import Foo, { type Bar } from 'Foo';",
+      output: "import Foo from 'Foo';\nimport type {Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
+    {
+      code: "import Foo, { type Bar, Baz } from 'Foo';",
+      output: "import Foo, {  Baz } from 'Foo';\nimport type {Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
+
+    //
+    // prefer-inline
+    //
+    {
+      code: "import type { Foo } from 'Foo';",
+      output: "import  { type Foo } from 'Foo';",
+      options: ['prefer-inline'],
+      errors: [{
+        message: 'Prefer using inline type specifiers instead of a top-level type-only import.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import type { Foo, Bar, Baz } from 'Foo';",
+      output: "import  { type Foo, type Bar, type Baz } from 'Foo';",
+      options: ['prefer-inline'],
+      errors: [{
+        message: 'Prefer using inline type specifiers instead of a top-level type-only import.',
+        type: 'ImportDeclaration',
+      }],
+    },
+  ],
+};
+
+const TS_ONLY = {
+  valid: [
+    //
+    // always valid
+    //
+    test({ code: "import type * as Foo from 'Foo';" }),
+  ],
+  invalid: [],
+};
+
+const FLOW_ONLY = {
+  valid: [
+    //
+    // prefer-top-level
+    //
+    {
+      code: "import typeof Foo from 'Foo';",
+      options: ['prefer-top-level'],
+    },
+    {
+      code: "import typeof { Foo, Bar, Baz, Bam } from 'Foo';",
+      options: ['prefer-top-level'],
+    },
+
+    //
+    // prefer-inline
+    //
+    {
+      code: "import typeof Foo from 'Foo';",
+      options: ['prefer-inline'],
+    },
+    {
+      code: "import { typeof Foo } from 'Foo';",
+      options: ['prefer-inline'],
+    },
+    {
+      code: "import { typeof Foo, typeof Bar, typeof Baz, typeof Bam } from 'Foo';",
+      options: ['prefer-inline'],
+    },
+    {
+      code: "import { type Foo, type Bar, typeof Baz, typeof Bam } from 'Foo';",
+      options: ['prefer-inline'],
+    },
+  ],
+  invalid: [
+    //
+    // prefer-top-level
+    //
+    {
+      code: "import { typeof Foo } from 'Foo';",
+      output: "import typeof {Foo} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level typeof-only import instead of inline typeof specifiers.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import { typeof Foo as Bar } from 'Foo';",
+      output: "import typeof {Foo as Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level typeof-only import instead of inline typeof specifiers.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import { type Foo, typeof Bar } from 'Foo';",
+      output: "import type {Foo} from 'Foo';\nimport typeof {Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type/typeof-only import instead of inline type/typeof specifiers.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import { typeof Foo, typeof Bar } from 'Foo';",
+      output: "import typeof {Foo, Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level typeof-only import instead of inline typeof specifiers.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import { Foo, typeof Bar } from 'Foo';",
+      output: "import { Foo  } from 'Foo';\nimport typeof {Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level typeof-only import instead of inline typeof specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
+    {
+      code: "import { typeof Foo, Bar } from 'Foo';",
+      output: "import {  Bar } from 'Foo';\nimport typeof {Foo} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level typeof-only import instead of inline typeof specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
+    {
+      code: "import { Foo, type Bar, typeof Baz } from 'Foo';",
+      output: "import { Foo   } from 'Foo';\nimport type {Bar} from 'Foo';\nimport typeof {Baz} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [
+        {
+          message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+          type: 'ImportSpecifier',
+        },
+        {
+          message: 'Prefer using a top-level typeof-only import instead of inline typeof specifiers.',
+          type: 'ImportSpecifier',
+        },
+      ],
+    },
+    {
+      code: "import Foo, { typeof Bar } from 'Foo';",
+      output: "import Foo from 'Foo';\nimport typeof {Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level typeof-only import instead of inline typeof specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
+    {
+      code: "import Foo, { typeof Bar, Baz } from 'Foo';",
+      output: "import Foo, {  Baz } from 'Foo';\nimport typeof {Bar} from 'Foo';",
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level typeof-only import instead of inline typeof specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
+
+    //
+    // prefer-inline
+    //
+    {
+      code: "import typeof { Foo } from 'Foo';",
+      output: "import  { typeof Foo } from 'Foo';",
+      options: ['prefer-inline'],
+      errors: [{
+        message: 'Prefer using inline typeof specifiers instead of a top-level typeof-only import.',
+        type: 'ImportDeclaration',
+      }],
+    },
+    {
+      code: "import typeof { Foo, Bar, Baz } from 'Foo';",
+      output: "import  { typeof Foo, typeof Bar, typeof Baz } from 'Foo';",
+      options: ['prefer-inline'],
+      errors: [{
+        message: 'Prefer using inline typeof specifiers instead of a top-level typeof-only import.',
+        type: 'ImportDeclaration',
+      }],
+    },
+  ],
+};
+
+context('TypeScript', () => {
+  // inline type specifiers weren't supported prior to TS v4.5
+  if (!parsers.TS_NEW || !tsVersionSatisfies('>= 4.5') || !typescriptEslintParserSatisfies('>= 5.7.0')) {
+    return;
+  }
+
+  const ruleTester = new RuleTester({
+    parser: parsers.TS_NEW,
+    parserOptions: {
+      ecmaVersion: 6,
+      sourceType: 'module',
+    },
+  });
+  ruleTester.run('consistent-type-specifier-style', rule, {
+    valid: [
+      ...COMMON_TESTS.valid,
+      ...TS_ONLY.valid,
+    ],
+    invalid: [
+      ...COMMON_TESTS.invalid,
+      ...TS_ONLY.invalid,
+    ],
+  });
+});
+
+context('Babel/Flow', () => {
+  if (!eslintVersionSatisfies('> 3')) {
+    return;
+  }
+
+  const ruleTester = new RuleTester({
+    parser: parsers.BABEL_OLD,
+    parserOptions: {
+      ecmaVersion: 6,
+      sourceType: 'module',
+    },
+  });
+  ruleTester.run('consistent-type-specifier-style', rule, {
+    valid: [
+      ...COMMON_TESTS.valid,
+      ...FLOW_ONLY.valid,
+    ],
+    invalid: [
+      ...COMMON_TESTS.invalid,
+      ...FLOW_ONLY.invalid,
+    ],
+  });
+});
diff --git a/tests/src/utils.js b/tests/src/utils.js
index ed04aa9678..b82883a6f4 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -1,17 +1,26 @@
 import path from 'path';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
+import typescriptPkg from 'typescript/package.json';
 
 // warms up the module cache. this import takes a while (>500ms)
 import 'babel-eslint';
 
 export const parsers = {
   ESPREE: require.resolve('espree'),
-  TS_OLD: semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0') && require.resolve('typescript-eslint-parser'),
+  TS_OLD: semver.satisfies(eslintPkg.version, '>=4.0.0 <6.0.0') && semver.satisfies(typescriptPkg.version, '<4') && require.resolve('typescript-eslint-parser'),
   TS_NEW: semver.satisfies(eslintPkg.version, '> 5') && require.resolve('@typescript-eslint/parser'),
   BABEL_OLD: require.resolve('babel-eslint'),
 };
 
+export function tsVersionSatisfies(specifier) {
+  return semver.satisfies(typescriptPkg.version, specifier);
+}
+
+export function typescriptEslintParserSatisfies(specifier) {
+  return parsers.TS_NEW && semver.satisfies(require('@typescript-eslint/parser/package.json').version, specifier);
+}
+
 export function testFilePath(relativePath) {
   return path.join(process.cwd(), './tests/files', relativePath);
 }
@@ -29,8 +38,12 @@ export function getNonDefaultParsers() {
 
 export const FILENAME = testFilePath('foo.js');
 
+export function eslintVersionSatisfies(specifier) {
+  return semver.satisfies(eslintPkg.version, specifier);
+}
+
 export function testVersion(specifier, t) {
-  return semver.satisfies(eslintPkg.version, specifier) ? test(t()) : [];
+  return eslintVersionSatisfies(specifier) ? test(t()) : [];
 }
 
 export function test(t) {

From 06cc47c4e60246a4caa120b2d8cc0a98e07e894d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 7 Sep 2022 10:41:37 -0700
Subject: [PATCH 518/767] [meta] `CONTRIBUTING.md`: link to CoC; soft wrap
 instead of hard wrap

---
 CONTRIBUTING.md | 77 ++++++++++---------------------------------------
 1 file changed, 16 insertions(+), 61 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c992d67f0f..04e9265050 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,7 +1,6 @@
 # Contributing
 
-Thanks for your interest in helping out! Here are a **few** _weird_ tricks to
-~~cut your mortgage in half~~ maximize the global net efficiency of your efforts!
+Thanks for your interest in helping out! Here are a **few** _weird_ tricks to ~~cut your mortgage in half~~ maximize the global net efficiency of your efforts!
 
 ## TL;DR: Checklist
 
@@ -21,23 +20,16 @@ Remember, you don't need to do it all yourself; any of these are helpful! 😎
 
 ### Search open + closed issues for similar cases.
 
-  You may find an open issue that closely matches what you are thinking. You
-  may also find a closed issue with discussion that either solves your problem
-  or explains why we are unlikely to solve it in the near future.
+  You may find an open issue that closely matches what you are thinking. You may also find a closed issue with discussion that either solves your problem or explains why we are unlikely to solve it in the near future.
 
-  If you find a matching issue that is open, and marked `accepted` and/or `help
-  wanted`, you might want to [open a PR](#prs).
+  If you find a matching issue that is open, and marked `accepted` and/or `help wanted`, you might want to [open a PR](#prs).
 
 ### Open an issue.
 
-  Let's discuss your issue. Could be as simple as unclear documentation or a
-  wonky config file.
-  If you're suggesting a feature, it might exist and need better
-  documentation, or it might be in process. Even given those, some discussion might
-  be warranted to ensure the enhancement is clear.
+  Let's discuss your issue. Could be as simple as unclear documentation or a wonky config file.
+  If you're suggesting a feature, it might exist and need better documentation, or it might be in process. Even given those, some discussion might be warranted to ensure the enhancement is clear.
 
-  You're welcome to jump right to a PR, but without a discussion, can't make any
-  guarantees about merging.
+  You're welcome to jump right to a PR, but without a discussion, can't make any guarantees about merging.
 
   That said: sometimes seeing the code makes the discussion clearer.😄
 
@@ -45,9 +37,7 @@ This is a helpful contribution all by itself. Thanks!
 
 ## PRs
 
-If you would like to implement something, firstly: thanks! Community contributions
-are a magical thing. Like Redux or [the flux capacitor](https://youtu.be/SR5BfQ4rEqQ?t=2m25s),
-they make open source possible.
+If you would like to implement something, firstly: thanks! Community contributions are a magical thing. Like Redux or [the flux capacitor](https://youtu.be/SR5BfQ4rEqQ?t=2m25s), they make open source possible.
 
 **Working on your first Pull Request?**
 You can learn how from this _free_ series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
@@ -56,61 +46,26 @@ Here are some things to keep in mind when working on a PR:
 
 #### Tests
 
-A PR that is just failing test cases for an existing issue is very helpful, as this
-can take as much time (if not more) as it takes to implement a new feature or fix
-a bug.
+A PR that is just failing test cases for an existing issue is very helpful, as this can take as much time (if not more) as it takes to implement a new feature or fix a bug.
 
-If you only have enough time to write tests, fantastic! Submit away. This is a great
-jumping-off point for a core contributor or even another PR to continue what you've started.
+If you only have enough time to write tests, fantastic! Submit away. This is a great jumping-off point for a core contributor or even another PR to continue what you've started.
 
 #### Docs
 
-For enhancements to rules, please update the docs in `docs/rules` matching the rule
-filename from `src/rules`.
+For enhancements to rules, please update the docs in `docs/rules` matching the rule filename from `src/rules`.
 
-Also, take a quick look at the rule summary in [README.md] in case it could use tweaking,
-or add a line if you've implemented a new rule.
+Also, take a quick look at the rule summary in [README.md] in case it could use tweaking, or add a line if you've implemented a new rule.
 
-Bugfixes may not warrant docs changes, though it's worth skimming the existing
-docs to see if there are any relevant caveats that need to be removed.
+Bugfixes may not warrant docs changes, though it's worth skimming the existing docs to see if there are any relevant caveats that need to be removed.
 
 #### Changelog
 
-Please add a quick blurb to the [**Unreleased**](./CHANGELOG.md#unreleased) section of the change log. Give yourself
-some credit, and please link back to the PR for future reference. This is especially
-helpful for resolver changes, as the resolvers are less frequently modified and published.
+Please add a quick blurb to the [**Unreleased**](./CHANGELOG.md#unreleased) section of the change log. Give yourself some credit, and please link back to the PR for future reference. This is especially helpful for resolver changes, as the resolvers are less frequently modified and published.
 
-Note also that the change log can't magically link back to Github entities (i.e. PRs,
-issues, users) or rules; there are a handful of footnote URL definitions at the bottom.
-You may need to add one or more URL if you've square-bracketed any such items.
+Note also that the change log can't magically link back to Github entities (i.e. PRs, issues, users) or rules; there are a handful of footnote URL definitions at the bottom. You may need to add one or more URL if you've square-bracketed any such items.
 
 ## Code of Conduct
 
-This is not so much a set of guidelines as a reference for what I hope may become
-a shared perspective on the project. I hope to write a longer essay to this end
-in the future. Comments are welcome, I'd like this to be as clear as possible.
+Please familiarize yourself with the [Code of Conduct](https://github.com/import-js/.github/blob/main/CODE_OF_CONDUCT.md).
 
-### Empathy
-
-People have feelings and perspectives, and people say and believe things for good reasons.
-
-If you find that you summarily disagree with a perspective stated by someone else,
-you likely each have histories that have moved you in opposite directions on a continuum
-that probably does not have a "wrong" or "right" end. It may be that you simply
-are working toward different goals that require different strategies. Every decision
-has pros and cons, and could result in some winners and some losers. It's great to
-discuss this so that both are well-known, and realize that even with infinite discussion,
-cons and losers will likely never go to zero.
-
-Also note that we're not doing brain surgery here, so while it's fine if we spend some time
-understanding each other, cordial disagreement should not be expensive in the
-long run, and we can accept that we will get some things wrong before we get them right (if ever!).
-
-If we can all get together behind the common goal of embracing empathy, everything else should be able to work itself out.
-
-#### Attribution
-
-Thanks for help from https://mozillascience.github.io/working-open-workshop/contributing/
-for inspiration before I wrote this. --ben
-
-[README.md]: ./README.md
+[README.md]: ./README.md
\ No newline at end of file

From cf9313ced7e37dbf3f2974d6b29176002d88e016 Mon Sep 17 00:00:00 2001
From: stropho <3704482+stropho@users.noreply.github.com>
Date: Tue, 6 Sep 2022 11:09:57 +0200
Subject: [PATCH 519/767] [meta] `CONTRIBUTING.md`: mention inactive PRs

---
 CHANGELOG.md    | 2 ++
 CONTRIBUTING.md | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22a5c386b2..b13d7170cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] [`no-useless-path-segments`]: fix paths ([#2424], thanks [@s-h-a-d-o-w])
 - [Tests] [`no-cycle`]: add passing test cases ([#2438], thanks [@georeith])
 - [Refactor] [`no-extraneous-dependencies`] improve performance using cache ([#2374], thanks [@meowtec])
+- [meta] `CONTRIBUTING.md`: mention inactive PRs ([#2546], thanks [@stropho])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1013,6 +1014,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2546]: https://github.com/import-js/eslint-plugin-import/pull/2546
 [#2541]: https://github.com/import-js/eslint-plugin-import/pull/2541
 [#2531]: https://github.com/import-js/eslint-plugin-import/pull/2531
 [#2511]: https://github.com/import-js/eslint-plugin-import/pull/2511
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 04e9265050..0606b4a63b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -44,6 +44,10 @@ You can learn how from this _free_ series [How to Contribute to an Open Source P
 
 Here are some things to keep in mind when working on a PR:
 
+**Trying to update an inactive Pull Request?**
+If a PR is open, but unfortunately the author is, for any reason, not available to apply code review fixes or rebase the source branch, then please **do not open a new PR**.
+Instead, paste a link to your own branch in the PR, and the maintainers can pull in your changes and update the existing PR in-place.
+
 #### Tests
 
 A PR that is just failing test cases for an existing issue is very helpful, as this can take as much time (if not more) as it takes to implement a new feature or fix a bug.

From 753505d062f7ae6736eb4ffb2cc35c3f699c5b6f Mon Sep 17 00:00:00 2001
From: Varun Sharma <varunsh@stepsecurity.io>
Date: Sat, 10 Sep 2022 11:19:59 -0700
Subject: [PATCH 520/767] [actions] add minimum GitHub token permissions for
 workflows

Signed-off-by: Varun Sharma <varunsh@stepsecurity.io>
---
 .github/workflows/node-4+.yml             | 3 +++
 .github/workflows/node-pretest.yml        | 3 +++
 .github/workflows/packages.yml            | 3 +++
 .github/workflows/rebase.yml              | 6 ++++++
 .github/workflows/require-allow-edits.yml | 5 +++++
 5 files changed, 20 insertions(+)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 6762bf0bbd..01344668fa 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -2,6 +2,9 @@ name: 'Tests: node.js'
 
 on: [pull_request, push]
 
+permissions:
+  contents: read
+
 jobs:
   matrix:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml
index cea20ec385..07e4b9d10a 100644
--- a/.github/workflows/node-pretest.yml
+++ b/.github/workflows/node-pretest.yml
@@ -2,6 +2,9 @@ name: 'Tests: pretest/posttest'
 
 on: [pull_request, push]
 
+permissions:
+  contents: read
+
 jobs:
   # pretest:
   #   runs-on: ubuntu-latest
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index e8cfaa8100..a383a14f61 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -2,6 +2,9 @@ name: 'Tests: packages'
 
 on: [pull_request, push]
 
+permissions:
+  contents: read
+
 jobs:
   matrix:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml
index 027aed0797..323387ccab 100644
--- a/.github/workflows/rebase.yml
+++ b/.github/workflows/rebase.yml
@@ -2,8 +2,14 @@ name: Automatic Rebase
 
 on: [pull_request_target]
 
+permissions:
+  contents: read
+
 jobs:
   _:
+    permissions:
+      contents: write  # for ljharb/rebase to push code to rebase
+      pull-requests: read  # for ljharb/rebase to get info about PR
     name: "Automatic Rebase"
 
     runs-on: ubuntu-latest
diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml
index 549d7b4823..eb3631b9e3 100644
--- a/.github/workflows/require-allow-edits.yml
+++ b/.github/workflows/require-allow-edits.yml
@@ -2,8 +2,13 @@ name: Require “Allow Edits”
 
 on: [pull_request_target]
 
+permissions:
+  contents: read
+
 jobs:
   _:
+    permissions:
+      pull-requests: read  # for ljharb/require-allow-edits to check 'allow edits' on PR
     name: "Require “Allow Edits”"
 
     runs-on: ubuntu-latest

From 4bfe644ec697d0a4fe0227e5ff09b869650eb35f Mon Sep 17 00:00:00 2001
From: Bert Verhelst <verhelstbert@gmail.com>
Date: Thu, 13 Oct 2022 10:36:01 +0200
Subject: [PATCH 521/767] [readme] make json for setting groups multiline

---
 CHANGELOG.md        |  3 +++
 docs/rules/order.md | 16 +++++++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b13d7170cb..06d0ebf2f9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,6 +41,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Tests] [`no-cycle`]: add passing test cases ([#2438], thanks [@georeith])
 - [Refactor] [`no-extraneous-dependencies`] improve performance using cache ([#2374], thanks [@meowtec])
 - [meta] `CONTRIBUTING.md`: mention inactive PRs ([#2546], thanks [@stropho])
+- [readme] make json for setting groups multiline ([#2570], thanks [@bertyhell])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1014,6 +1015,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2570]: https://github.com/import-js/eslint-plugin-import/pull/2570
 [#2546]: https://github.com/import-js/eslint-plugin-import/pull/2546
 [#2541]: https://github.com/import-js/eslint-plugin-import/pull/2541
 [#2531]: https://github.com/import-js/eslint-plugin-import/pull/2531
@@ -1555,6 +1557,7 @@ for info on changes for earlier releases.
 [@benmosher]: https://github.com/benmosher
 [@benmunro]: https://github.com/benmunro
 [@BenoitZugmeyer]: https://github.com/BenoitZugmeyer
+[@bertyhell]: https://github.com/bertyhell
 [@bicstone]: https://github.com/bicstone
 [@Blasz]: https://github.com/Blasz
 [@bmish]: https://github.com/bmish
diff --git a/docs/rules/order.md b/docs/rules/order.md
index c525dfbbac..dbda8b2d77 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -99,7 +99,21 @@ The default value is `["builtin", "external", "parent", "sibling", "index"]`.
 You can set the options like this:
 
 ```ts
-"import/order": ["error", {"groups": ["index", "sibling", "parent", "internal", "external", "builtin", "object", "type"]}]
+"import/order": [
+  "error",
+  {
+    "groups": [
+      "index",
+      "sibling",
+      "parent",
+      "internal",
+      "external",
+      "builtin",
+      "object",
+      "type"
+    ]
+  }
+]
 ```
 
 ### `pathGroups: [array of objects]`:

From 2e1edd6f3ab1787f037de05b2d7171f8410295db Mon Sep 17 00:00:00 2001
From: Guilherme Kammsetzer <guilherme@kammsetzer.dev>
Date: Mon, 10 Oct 2022 23:07:39 -0400
Subject: [PATCH 522/767] [New] Add `no-empty-named-blocks` rule

---
 CHANGELOG.md                             |  6 +-
 README.md                                |  2 +
 docs/rules/no-empty-named-blocks.md      | 39 ++++++++++
 src/index.js                             |  1 +
 src/rules/no-empty-named-blocks.js       | 91 ++++++++++++++++++++++
 tests/files/empty-named-blocks.js        |  1 +
 tests/src/rules/no-empty-named-blocks.js | 98 ++++++++++++++++++++++++
 7 files changed, 237 insertions(+), 1 deletion(-)
 create mode 100644 docs/rules/no-empty-named-blocks.md
 create mode 100644 src/rules/no-empty-named-blocks.js
 create mode 100644 tests/files/empty-named-blocks.js
 create mode 100644 tests/src/rules/no-empty-named-blocks.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 06d0ebf2f9..86df0edd43 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-extraneous-dependencies`]: Add `includeTypes` option ([#2543], thanks [@bdwain])
 - [`order`]: new `alphabetize.orderImportKind` option to sort imports with same path based on their kind (`type`, `typeof`) ([#2544], thanks [@stropho])
 - [`consistent-type-specifier-style`]: add rule ([#2473], thanks [@bradzacher])
+- Add [`no-empty-named-blocks`] rule ([#2568], thanks [@guilhermelimak])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -990,6 +991,7 @@ for info on changes for earlier releases.
 [`no-deprecated`]: ./docs/rules/no-deprecated.md
 [`no-duplicates`]: ./docs/rules/no-duplicates.md
 [`no-dynamic-require`]: ./docs/rules/no-dynamic-require.md
+[`no-empty-named-blocks`]: ./docs/rules/no-empty-named-blocks.md
 [`no-extraneous-dependencies`]: ./docs/rules/no-extraneous-dependencies.md
 [`no-import-module-exports`]: ./docs/rules/no-import-module-exports.md
 [`no-internal-modules`]: ./docs/rules/no-internal-modules.md
@@ -1016,6 +1018,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2570]: https://github.com/import-js/eslint-plugin-import/pull/2570
+[#2568]: https://github.com/import-js/eslint-plugin-import/pull/2568
 [#2546]: https://github.com/import-js/eslint-plugin-import/pull/2546
 [#2541]: https://github.com/import-js/eslint-plugin-import/pull/2541
 [#2531]: https://github.com/import-js/eslint-plugin-import/pull/2531
@@ -1603,13 +1606,14 @@ for info on changes for earlier releases.
 [@futpib]: https://github.com/futpib
 [@gajus]: https://github.com/gajus
 [@gausie]: https://github.com/gausie
-[@georeith]: https://github.com/georeith
 [@gavriguy]: https://github.com/gavriguy
+[@georeith]: https://github.com/georeith
 [@giodamelio]: https://github.com/giodamelio
 [@golopot]: https://github.com/golopot
 [@GoodForOneFare]: https://github.com/GoodForOneFare
 [@graingert]: https://github.com/graingert
 [@grit96]: https://github.com/grit96
+[@guilhermelimak]: https://github.com/guilhermelimak
 [@guillaumewuip]: https://github.com/guillaumewuip
 [@hayes]: https://github.com/hayes
 [@himynameisdave]: https://github.com/himynameisdave
diff --git a/README.md b/README.md
index 775fc198b5..0e550f8f8e 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 * Forbid the use of extraneous packages ([`no-extraneous-dependencies`])
 * Forbid the use of mutable exports with `var` or `let`. ([`no-mutable-exports`])
 * Report modules without exports, or exports without matching import in another module ([`no-unused-modules`])
+* Prevent empty named import blocks ([`no-empty-named-blocks`])
 
 [`export`]: ./docs/rules/export.md
 [`no-named-as-default`]: ./docs/rules/no-named-as-default.md
@@ -63,6 +64,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 [`no-extraneous-dependencies`]: ./docs/rules/no-extraneous-dependencies.md
 [`no-mutable-exports`]: ./docs/rules/no-mutable-exports.md
 [`no-unused-modules`]: ./docs/rules/no-unused-modules.md
+[`no-empty-named-blocks`]: ./docs/rules/no-empty-named-blocks.md
 
 ### Module systems
 
diff --git a/docs/rules/no-empty-named-blocks.md b/docs/rules/no-empty-named-blocks.md
new file mode 100644
index 0000000000..229d927478
--- /dev/null
+++ b/docs/rules/no-empty-named-blocks.md
@@ -0,0 +1,39 @@
+# import/no-empty-named-blocks
+
+Reports the use of empty named import blocks.
+
+## Rule Details
+
+### Valid
+```js
+import { mod } from 'mod'
+import Default, { mod } from 'mod'
+```
+
+When using typescript
+```js
+import type { mod } from 'mod'
+```
+
+When using flow
+```js
+import typeof { mod } from 'mod'
+```
+
+### Invalid
+```js
+import {} from 'mod'
+import Default, {} from 'mod'
+```
+
+When using typescript
+```js
+import type Default, {} from 'mod'
+import type {} from 'mod'
+```
+
+When using flow
+```js
+import typeof {} from 'mod'
+import typeof Default, {} from 'mod'
+```
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index fd83a4aaf8..15f98d96f2 100644
--- a/src/index.js
+++ b/src/index.js
@@ -42,6 +42,7 @@ export const rules = {
   'no-useless-path-segments': require('./rules/no-useless-path-segments'),
   'dynamic-import-chunkname': require('./rules/dynamic-import-chunkname'),
   'no-import-module-exports': require('./rules/no-import-module-exports'),
+  'no-empty-named-blocks': require('./rules/no-empty-named-blocks'),
 
   // export
   'exports-last': require('./rules/exports-last'),
diff --git a/src/rules/no-empty-named-blocks.js b/src/rules/no-empty-named-blocks.js
new file mode 100644
index 0000000000..65a8515cf0
--- /dev/null
+++ b/src/rules/no-empty-named-blocks.js
@@ -0,0 +1,91 @@
+import docsUrl from '../docsUrl';
+
+function getEmptyBlockRange(tokens, index) {
+  const token = tokens[index];
+  const nextToken = tokens[index + 1];
+  const prevToken = tokens[index - 1];
+  let start = token.range[0];
+  const end = nextToken.range[1];
+
+  // Remove block tokens and the previous comma
+  if (prevToken.value === ','|| prevToken.value === 'type' || prevToken.value === 'typeof') {
+    start = prevToken.range[0];
+  }
+
+  return [start, end];
+}
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      url: docsUrl('no-empty-named-blocks'),
+    },
+    fixable: 'code',
+    schema: [],
+    hasSuggestions: true,
+  },
+
+  create(context) {
+    return {
+      Program(node) {
+        node.tokens.forEach((token, idx) => {
+          const nextToken = node.tokens[idx + 1];
+
+          if (nextToken && token.value === '{' && nextToken.value === '}') {
+            const hasOtherIdentifiers = node.tokens.some((token) => (
+              token.type === 'Identifier'
+                && token.value !== 'from'
+                && token.value !== 'type'
+                && token.value !== 'typeof'
+            ));
+
+            // If it has no other identifiers it's the only thing in the import, so we can either remove the import
+            // completely or transform it in a side-effects only import
+            if (!hasOtherIdentifiers) {
+              context.report({
+                node,
+                message: 'Unexpected empty named import block',
+                suggest: [
+                  {
+                    desc: 'Remove unused import',
+                    fix(fixer) {
+                      // Remove the whole import
+                      return fixer.remove(node);
+                    },
+                  },
+                  {
+                    desc: 'Remove empty import block',
+                    fix(fixer) {
+                      // Remove the empty block and the 'from' token, leaving the import only for its side
+                      // effects, e.g. `import 'mod'`
+                      const sourceCode = context.getSourceCode();
+                      const fromToken = node.tokens.find(t => t.value === 'from');
+                      const importToken = node.tokens.find(t => t.value === 'import');
+                      const hasSpaceAfterFrom = sourceCode.isSpaceBetween(fromToken, sourceCode.getTokenAfter(fromToken));
+                      const hasSpaceAfterImport = sourceCode.isSpaceBetween(importToken, sourceCode.getTokenAfter(fromToken));
+
+                      const [start] = getEmptyBlockRange(node.tokens, idx);
+                      const [, end] = fromToken.range;
+                      const range = [start, hasSpaceAfterFrom ? end + 1 : end];
+
+                      return fixer.replaceTextRange(range, hasSpaceAfterImport ? '' : ' ');
+                    },
+                  },
+                ],
+              });
+            } else {
+              context.report({
+                node,
+                message: 'Unexpected empty named import block',
+                fix(fixer) {
+                  return fixer.removeRange(getEmptyBlockRange(node.tokens, idx));
+                },
+              });
+            }
+          }
+        });
+      },
+    };
+  },
+};
diff --git a/tests/files/empty-named-blocks.js b/tests/files/empty-named-blocks.js
new file mode 100644
index 0000000000..4640c7f8d8
--- /dev/null
+++ b/tests/files/empty-named-blocks.js
@@ -0,0 +1 @@
+import {} from './bar.js';
diff --git a/tests/src/rules/no-empty-named-blocks.js b/tests/src/rules/no-empty-named-blocks.js
new file mode 100644
index 0000000000..ee21db3478
--- /dev/null
+++ b/tests/src/rules/no-empty-named-blocks.js
@@ -0,0 +1,98 @@
+import { parsers, test } from '../utils';
+
+import { RuleTester } from 'eslint';
+
+const ruleTester = new RuleTester();
+const rule = require('rules/no-empty-named-blocks');
+
+
+function generateSuggestionsTestCases(cases, parser) {
+  return cases.map(code => test({
+    code,
+    parser,
+    errors: [{
+      suggestions: [
+        {
+          desc: 'Remove unused import',
+          output: '',
+        },
+        {
+          desc: 'Remove empty import block',
+          output: `import 'mod';`,
+        },
+      ],
+    }],
+  }));
+}
+
+ruleTester.run('no-empty-named-blocks', rule, {
+  valid: [].concat(
+    test({ code: `import 'mod';` }),
+    test({ code: `import Default from 'mod';` }),
+    test({ code: `import { Named } from 'mod';` }),
+    test({ code: `import Default, { Named } from 'mod';` }),
+    test({ code: `import * as Namespace from 'mod';` }),
+
+    // Typescript
+    parsers.TS_NEW ? [
+      test({ code: `import type Default from 'mod';`, parser: parsers.TS_NEW }),
+      test({ code: `import type { Named } from 'mod';`, parser: parsers.TS_NEW }),
+      test({ code: `import type Default, { Named } from 'mod';`, parser: parsers.TS_NEW }),
+      test({ code: `import type * as Namespace from 'mod';`, parser: parsers.TS_NEW }),
+    ] : [],
+
+    // Flow
+    test({ code: `import typeof Default from 'mod';`, parser: parsers.BABEL_OLD }),
+    test({ code: `import typeof { Named } from 'mod';`, parser: parsers.BABEL_OLD }),
+    test({ code: `import typeof Default, { Named } from 'mod';`, parser: parsers.BABEL_OLD }),
+  ),
+  invalid: [].concat(
+    test({
+      code: `import Default, {} from 'mod';`,
+      output: `import Default from 'mod';`,
+      errors: ['Unexpected empty named import block'],
+    }),
+    generateSuggestionsTestCases([
+      `import {} from 'mod';`,
+      `import{}from'mod';`,
+      `import {} from'mod';`,
+      `import {}from 'mod';`,
+    ]),
+
+    // Typescript
+    parsers.TS_NEW ? [].concat(
+      generateSuggestionsTestCases(
+        [
+          `import type {} from 'mod';`,
+          `import type {}from 'mod';`,
+          `import type{}from 'mod';`,
+          `import type {}from'mod';`,
+        ],
+        parsers.TS_NEW,
+      ),
+      test({
+        code: `import type Default, {} from 'mod';`,
+        output: `import type Default from 'mod';`,
+        parser: parsers.TS_NEW,
+        errors: ['Unexpected empty named import block'],
+      }),
+    ) : [],
+
+    // Flow
+    generateSuggestionsTestCases(
+      [
+        `import typeof {} from 'mod';`,
+        `import typeof {}from 'mod';`,
+        `import typeof {} from'mod';`,
+        `import typeof{}from'mod';`,
+      ],
+      parsers.BABEL_OLD,
+    ),
+    test({
+      code: `import typeof Default, {} from 'mod';`,
+      output: `import typeof Default from 'mod';`,
+      parser: parsers.BABEL_OLD,
+      errors: ['Unexpected empty named import block'],
+    }),
+  ),
+});

From c3d14cb920bdc6d277134973d37364db22c3a8b8 Mon Sep 17 00:00:00 2001
From: Max <golergka@gmail.com>
Date: Thu, 19 May 2022 15:02:28 +0400
Subject: [PATCH 523/767] [Tests] `no-restricted-paths`: `import type` tests

Co-authored-by: Max <golergka@gmail.com>
Co-authored-by: Aziz Abdullaev <aziz.saidmuratov@duke.edu>
---
 CHANGELOG.md                             |   5 +
 tests/files/restricted-paths/server/c.ts |   0
 tests/src/rules/no-restricted-paths.js   | 274 ++++++++++++++++++++++-
 3 files changed, 276 insertions(+), 3 deletions(-)
 create mode 100644 tests/files/restricted-paths/server/c.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86df0edd43..318dbef80a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -43,6 +43,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Refactor] [`no-extraneous-dependencies`] improve performance using cache ([#2374], thanks [@meowtec])
 - [meta] `CONTRIBUTING.md`: mention inactive PRs ([#2546], thanks [@stropho])
 - [readme] make json for setting groups multiline ([#2570], thanks [@bertyhell])
+- [Tests] [`no-restricted-paths`]: Tests for `import type` statements ([#2459], thanks [@golergka])
+- [Tests] [`no-restricted-paths`]: fix one failing `import type` test case, submitted by [@golergka], thanks [@azyzz228]
 
 ## [2.26.0] - 2022-04-05
 
@@ -1028,6 +1030,7 @@ for info on changes for earlier releases.
 [#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
 [#2473]: https://github.com/import-js/eslint-plugin-import/pull/2473
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
+[#2459]: https://github.com/import-js/eslint-plugin-import/pull/2459
 [#2440]: https://github.com/import-js/eslint-plugin-import/pull/2440
 [#2438]: https://github.com/import-js/eslint-plugin-import/pull/2438
 [#2436]: https://github.com/import-js/eslint-plugin-import/pull/2436
@@ -1554,6 +1557,7 @@ for info on changes for earlier releases.
 [@atav32]: https://github.com/atav32
 [@atikenny]: https://github.com/atikenny
 [@atos1990]: https://github.com/atos1990
+[@azyzz228]: https://github.com/azyzz228
 [@barbogast]: https://github.com/barbogast
 [@be5invis]: https://github.com/be5invis
 [@beatrizrezener]: https://github.com/beatrizrezener
@@ -1609,6 +1613,7 @@ for info on changes for earlier releases.
 [@gavriguy]: https://github.com/gavriguy
 [@georeith]: https://github.com/georeith
 [@giodamelio]: https://github.com/giodamelio
+[@golergka]: https://github.com/golergka
 [@golopot]: https://github.com/golopot
 [@GoodForOneFare]: https://github.com/GoodForOneFare
 [@graingert]: https://github.com/graingert
diff --git a/tests/files/restricted-paths/server/c.ts b/tests/files/restricted-paths/server/c.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index d782a14472..81182189f2 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -1,7 +1,7 @@
 import { RuleTester } from 'eslint';
 import rule from 'rules/no-restricted-paths';
 
-import { test, testFilePath } from '../utils';
+import { getTSParsers, test, testFilePath } from '../utils';
 
 const ruleTester = new RuleTester();
 
@@ -474,8 +474,7 @@ ruleTester.run('no-restricted-paths', rule, {
       ],
       errors: [
         {
-          message: 'Restricted path exceptions must be descendants of the configured ' +
-          '`from` path for that zone.',
+          message: 'Restricted path exceptions must be descendants of the configured `from` path for that zone.',
           line: 1,
           column: 15,
         },
@@ -712,3 +711,272 @@ ruleTester.run('no-restricted-paths', rule, {
     }),
   ),
 });
+
+context('Typescript', function () {
+  getTSParsers().forEach(parser => {
+    const settings = {
+      'import/parsers': { [parser]: ['.ts'] },
+      'import/resolver': { 'eslint-import-resolver-typescript': true },
+    };
+    ruleTester.run('no-restricted-paths', rule, {
+      valid: [
+        test({
+          code: 'import type a from "../client/a.ts"',
+          filename: testFilePath('./restricted-paths/server/b.ts'),
+          options: [{
+            zones: [{ target: './tests/files/restricted-paths/server', from: './tests/files/restricted-paths/other' }],
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type a from "../client/a.ts"',
+          filename: testFilePath('./restricted-paths/server/b.ts'),
+          options: [{
+            zones: [{ target: '**/*', from: './tests/files/restricted-paths/other' }],
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type a from "../client/a.ts"',
+          filename: testFilePath('./restricted-paths/client/b.ts'),
+          options: [{
+            zones: [{
+              target: './tests/files/restricted-paths/!(client)/**/*',
+              from: './tests/files/restricted-paths/client/**/*',
+            }],
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type b from "../server/b.ts"',
+          filename: testFilePath('./restricted-paths/client/a.ts'),
+          options: [{
+            zones: [{ target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/other' }],
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type a from "./a.ts"',
+          filename: testFilePath('./restricted-paths/server/one/a.ts'),
+          options: [{
+            zones: [{
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['./one'],
+            }],
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type a from "../two/a.ts"',
+          filename: testFilePath('./restricted-paths/server/one/a.ts'),
+          options: [{
+            zones: [{
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['./two'],
+            }],
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type a from "../one/a.ts"',
+          filename: testFilePath('./restricted-paths/server/two-new/a.ts'),
+          options: [{
+            zones: [{
+              target: './tests/files/restricted-paths/server/two',
+              from: './tests/files/restricted-paths/server',
+              except: [],
+            }],
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type A from "../two/a.ts"',
+          filename: testFilePath('./restricted-paths/server/one/a.ts'),
+          options: [{
+            zones: [{
+              target: '**/*',
+              from: './tests/files/restricted-paths/server/**/*',
+              except: ['**/a.js'],
+            }],
+          }],
+          parser,
+          settings,
+        }),
+        // no config
+        test({ code: 'import type b from "../server/b.js"', parser, settings }),
+        test({ code: 'import type * as b from "../server/b.js"', parser, settings }),
+      ],
+      invalid: [
+        test({
+          code: 'import type b from "../server/b"',
+          filename: testFilePath('./restricted-paths/client/a.ts'),
+          options: [{
+            zones: [{ target: './tests/files/restricted-paths/client', from: './tests/files/restricted-paths/server' }],
+          }],
+          errors: [{
+            message: 'Unexpected path "../server/b" imported in restricted zone.',
+            line: 1,
+            column: 20,
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type b from "../server/b"',
+          filename: testFilePath('./restricted-paths/client/a.ts'),
+          options: [{
+            zones: [{ target: './tests/files/restricted-paths/client/**/*', from: './tests/files/restricted-paths/server' }],
+          }],
+          errors: [{
+            message: 'Unexpected path "../server/b" imported in restricted zone.',
+            line: 1,
+            column: 20,
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type a from "../client/a"\nimport type c from "./c.ts"',
+          filename: testFilePath('./restricted-paths/server/b.ts'),
+          options: [{
+            zones: [
+              {
+                target: './tests/files/restricted-paths/server',
+                from: ['./tests/files/restricted-paths/client', './tests/files/restricted-paths/server/c.ts'],
+              },
+            ],
+          }],
+          errors: [
+            {
+              message: 'Unexpected path "../client/a" imported in restricted zone.',
+              line: 1,
+              column: 20,
+            },
+            {
+              message: 'Unexpected path "./c.ts" imported in restricted zone.',
+              line: 2,
+              column: 20,
+            },
+          ],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type b from "../server/b"',
+          filename: testFilePath('./restricted-paths/client/a'),
+          options: [{
+            zones: [{ target: './client', from: './server' }],
+            basePath: testFilePath('./restricted-paths'),
+          }],
+          errors: [{
+            message: 'Unexpected path "../server/b" imported in restricted zone.',
+            line: 1,
+            column: 20,
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type b from "../two/a"',
+          filename: testFilePath('./restricted-paths/server/one/a.ts'),
+          options: [{
+            zones: [{
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['./one'],
+            }],
+          }],
+          errors: [{
+            message: 'Unexpected path "../two/a" imported in restricted zone.',
+            line: 1,
+            column: 20,
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type b from "../two/a"',
+          filename: testFilePath('./restricted-paths/server/one/a'),
+          options: [{
+            zones: [{
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['./one'],
+              message: 'Custom message',
+            }],
+          }],
+          errors: [{
+            message: 'Unexpected path "../two/a" imported in restricted zone. Custom message',
+            line: 1,
+            column: 20,
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type b from "../two/a"',
+          filename: testFilePath('./restricted-paths/server/one/a.ts'),
+          options: [{
+            zones: [{
+              target: './tests/files/restricted-paths/server/one',
+              from: './tests/files/restricted-paths/server',
+              except: ['../client/a'],
+            }],
+          }],
+          errors: [{
+            message: 'Restricted path exceptions must be descendants of the configured ' +
+              '`from` path for that zone.',
+            line: 1,
+            column: 20,
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type A from "../two/a"',
+          filename: testFilePath('./restricted-paths/server/one/a.ts'),
+          options: [{
+            zones: [{
+              target: '**/*',
+              from: './tests/files/restricted-paths/server/**/*',
+            }],
+          }],
+          errors: [{
+            message: 'Unexpected path "../two/a" imported in restricted zone.',
+            line: 1,
+            column: 20,
+          }],
+          parser,
+          settings,
+        }),
+        test({
+          code: 'import type A from "../two/a"',
+          filename: testFilePath('./restricted-paths/server/one/a.ts'),
+          options: [{
+            zones: [{
+              target: '**/*',
+              from: './tests/files/restricted-paths/server/**/*',
+              except: ['a.ts'],
+            }],
+          }],
+          errors: [{
+            message: 'Restricted path exceptions must be glob patterns when `from` contains glob patterns',
+            line: 1,
+            column: 20,
+          }],
+          parser,
+          settings,
+        }),
+      ],
+    });
+  });
+});

From e85c694fd1ca190b4da72711cfe3813463882fe1 Mon Sep 17 00:00:00 2001
From: Bryan Mishkin <698306+bmish@users.noreply.github.com>
Date: Sat, 29 Oct 2022 11:57:27 -0400
Subject: [PATCH 524/767] [Docs] automate docs with eslint-doc-generator

---
 .eslintrc                                     |   1 +
 CHANGELOG.md                                  |   1 +
 CONTRIBUTING.md                               |  18 +-
 README.md                                     | 187 ++++++++----------
 docs/rules/consistent-type-specifier-style.md |   4 +
 docs/rules/default.md                         |   4 +
 docs/rules/dynamic-import-chunkname.md        |   2 +
 docs/rules/export.md                          |   4 +
 docs/rules/exports-last.md                    |   2 +
 docs/rules/extensions.md                      |   7 +-
 docs/rules/first.md                           |   4 +
 docs/rules/group-exports.md                   |   2 +
 docs/rules/imports-first.md                   |   6 +
 docs/rules/max-dependencies.md                |   2 +
 docs/rules/named.md                           |   4 +
 docs/rules/namespace.md                       |   4 +
 docs/rules/newline-after-import.md            |   4 +
 docs/rules/no-absolute-path.md                |   6 +-
 docs/rules/no-amd.md                          |   2 +
 docs/rules/no-anonymous-default-export.md     |   2 +
 docs/rules/no-commonjs.md                     |   2 +
 docs/rules/no-cycle.md                        |   2 +
 docs/rules/no-default-export.md               |   4 +-
 docs/rules/no-deprecated.md                   |   4 +-
 docs/rules/no-duplicates.md                   |   6 +
 docs/rules/no-dynamic-require.md              |   6 +-
 docs/rules/no-empty-named-blocks.md           |   4 +
 docs/rules/no-extraneous-dependencies.md      |   4 +-
 docs/rules/no-import-module-exports.md        |   4 +
 docs/rules/no-internal-modules.md             |   2 +
 docs/rules/no-mutable-exports.md              |   2 +
 docs/rules/no-named-as-default-member.md      |   4 +
 docs/rules/no-named-as-default.md             |   4 +
 docs/rules/no-named-default.md                |   2 +
 docs/rules/no-named-export.md                 |   4 +-
 docs/rules/no-namespace.md                    |   4 +
 docs/rules/no-nodejs-modules.md               |   4 +-
 docs/rules/no-relative-packages.md            |   4 +
 docs/rules/no-relative-parent-imports.md      |   2 +
 docs/rules/no-restricted-paths.md             |   4 +-
 docs/rules/no-self-import.md                  |   4 +-
 docs/rules/no-unassigned-import.md            |   4 +-
 docs/rules/no-unresolved.md                   |   4 +
 docs/rules/no-unused-modules.md               |   2 +
 docs/rules/no-useless-path-segments.md        |   4 +
 docs/rules/no-webpack-loader-syntax.md        |   2 +
 docs/rules/order.md                           |   6 +-
 docs/rules/prefer-default-export.md           |   2 +
 docs/rules/unambiguous.md                     |   2 +
 package.json                                  |   7 +-
 src/rules/consistent-type-specifier-style.js  |   3 +-
 src/rules/default.js                          |   2 +
 src/rules/dynamic-import-chunkname.js         |   2 +
 src/rules/export.js                           |   2 +
 src/rules/exports-last.js                     |   2 +
 src/rules/extensions.js                       |   2 +
 src/rules/first.js                            |   2 +
 src/rules/group-exports.js                    |   2 +
 src/rules/imports-first.js                    |   2 +
 src/rules/max-dependencies.js                 |   2 +
 src/rules/named.js                            |   2 +
 src/rules/namespace.js                        |   2 +
 src/rules/newline-after-import.js             |   2 +
 src/rules/no-absolute-path.js                 |   2 +
 src/rules/no-amd.js                           |   2 +
 src/rules/no-anonymous-default-export.js      |   2 +
 src/rules/no-commonjs.js                      |   2 +
 src/rules/no-cycle.js                         |   6 +-
 src/rules/no-default-export.js                |   2 +
 src/rules/no-deprecated.js                    |   2 +
 src/rules/no-duplicates.js                    |   2 +
 src/rules/no-dynamic-require.js               |   2 +
 src/rules/no-empty-named-blocks.js            |   2 +
 src/rules/no-extraneous-dependencies.js       |   2 +
 src/rules/no-import-module-exports.js         |   4 +-
 src/rules/no-internal-modules.js              |   2 +
 src/rules/no-mutable-exports.js               |   2 +
 src/rules/no-named-as-default-member.js       |   2 +
 src/rules/no-named-as-default.js              |   2 +
 src/rules/no-named-default.js                 |   2 +
 src/rules/no-named-export.js                  |   6 +-
 src/rules/no-namespace.js                     |   2 +
 src/rules/no-nodejs-modules.js                |   2 +
 src/rules/no-relative-packages.js             |   2 +
 src/rules/no-relative-parent-imports.js       |   2 +
 src/rules/no-restricted-paths.js              |   2 +
 src/rules/no-self-import.js                   |   3 +-
 src/rules/no-unassigned-import.js             |   2 +
 src/rules/no-unresolved.js                    |   2 +
 src/rules/no-unused-modules.js                |  10 +-
 src/rules/no-useless-path-segments.js         |   2 +
 src/rules/no-webpack-loader-syntax.js         |   2 +
 src/rules/order.js                            |   2 +
 src/rules/prefer-default-export.js            |   2 +
 src/rules/unambiguous.js                      |   2 +
 95 files changed, 344 insertions(+), 141 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 2cbfd59cea..a90ba1d4be 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -71,6 +71,7 @@
         "eslint-plugin/no-deprecated-report-api": "off",
         "eslint-plugin/prefer-replace-text": "error",
         "eslint-plugin/report-message-format": "error",
+        "eslint-plugin/require-meta-docs-description": ["error", { "pattern": "^(Enforce|Ensure|Prefer|Forbid).+\\.$" }],
         "eslint-plugin/require-meta-schema": "error",
         "eslint-plugin/require-meta-type": "error",
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 318dbef80a..78bd21cf3e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [readme] make json for setting groups multiline ([#2570], thanks [@bertyhell])
 - [Tests] [`no-restricted-paths`]: Tests for `import type` statements ([#2459], thanks [@golergka])
 - [Tests] [`no-restricted-paths`]: fix one failing `import type` test case, submitted by [@golergka], thanks [@azyzz228]
+- [Docs] automate docs with eslint-doc-generator ([#2582], thanks [@bmish])
 
 ## [2.26.0] - 2022-04-05
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0606b4a63b..eba44f51ac 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,10 +5,12 @@ Thanks for your interest in helping out! Here are a **few** _weird_ tricks to ~~
 ## TL;DR: Checklist
 
 When opening an [issue](#issues):
+
 - [ ] search open/closed issues
 - [ ] discuss bug/enhancement in new or old issue
 
 [PR](#prs) time:
+
 - [ ] write tests
 - [ ] implement feature/fix bug
 - [ ] update docs
@@ -18,13 +20,13 @@ Remember, you don't need to do it all yourself; any of these are helpful! 😎
 
 ## Issues
 
-### Search open + closed issues for similar cases.
+### Search open + closed issues for similar cases
 
   You may find an open issue that closely matches what you are thinking. You may also find a closed issue with discussion that either solves your problem or explains why we are unlikely to solve it in the near future.
 
   If you find a matching issue that is open, and marked `accepted` and/or `help wanted`, you might want to [open a PR](#prs).
 
-### Open an issue.
+### Open an issue
 
   Let's discuss your issue. Could be as simple as unclear documentation or a wonky config file.
   If you're suggesting a feature, it might exist and need better documentation, or it might be in process. Even given those, some discussion might be warranted to ensure the enhancement is clear.
@@ -48,21 +50,19 @@ Here are some things to keep in mind when working on a PR:
 If a PR is open, but unfortunately the author is, for any reason, not available to apply code review fixes or rebase the source branch, then please **do not open a new PR**.
 Instead, paste a link to your own branch in the PR, and the maintainers can pull in your changes and update the existing PR in-place.
 
-#### Tests
+### Tests
 
 A PR that is just failing test cases for an existing issue is very helpful, as this can take as much time (if not more) as it takes to implement a new feature or fix a bug.
 
 If you only have enough time to write tests, fantastic! Submit away. This is a great jumping-off point for a core contributor or even another PR to continue what you've started.
 
-#### Docs
-
-For enhancements to rules, please update the docs in `docs/rules` matching the rule filename from `src/rules`.
+### Docs
 
-Also, take a quick look at the rule summary in [README.md] in case it could use tweaking, or add a line if you've implemented a new rule.
+For enhancements to rules, please update the docs in `docs/rules` matching the rule filename from `src/rules` or the rule description in `meta.docs.description`. Running `npm run update:eslint-docs` will update the [README.md] and rule doc header.
 
 Bugfixes may not warrant docs changes, though it's worth skimming the existing docs to see if there are any relevant caveats that need to be removed.
 
-#### Changelog
+### Changelog
 
 Please add a quick blurb to the [**Unreleased**](./CHANGELOG.md#unreleased) section of the change log. Give yourself some credit, and please link back to the PR for future reference. This is especially helpful for resolver changes, as the resolvers are less frequently modified and published.
 
@@ -72,4 +72,4 @@ Note also that the change log can't magically link back to Github entities (i.e.
 
 Please familiarize yourself with the [Code of Conduct](https://github.com/import-js/.github/blob/main/CODE_OF_CONDUCT.md).
 
-[README.md]: ./README.md
\ No newline at end of file
+[README.md]: ./README.md
diff --git a/README.md b/README.md
index 0e550f8f8e..78344f35e3 100644
--- a/README.md
+++ b/README.md
@@ -13,111 +13,85 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 
 ## Rules
 
-### Static analysis
-
-* Ensure imports point to a file/module that can be resolved. ([`no-unresolved`])
-* Ensure named imports correspond to a named export in the remote file. ([`named`])
-* Ensure a default export is present, given a default import. ([`default`])
-* Ensure imported namespaces contain dereferenced properties as they are dereferenced. ([`namespace`])
-* Restrict which files can be imported in a given folder ([`no-restricted-paths`])
-* Forbid import of modules using absolute paths ([`no-absolute-path`])
-* Forbid `require()` calls with expressions ([`no-dynamic-require`])
-* Prevent importing the submodules of other modules ([`no-internal-modules`])
-* Forbid webpack loader syntax in imports ([`no-webpack-loader-syntax`])
-* Forbid a module from importing itself ([`no-self-import`])
-* Forbid a module from importing a module with a dependency path back to itself ([`no-cycle`])
-* Prevent unnecessary path segments in import and require statements ([`no-useless-path-segments`])
-* Forbid importing modules from parent directories ([`no-relative-parent-imports`])
-* Prevent importing packages through relative paths ([`no-relative-packages`])
-
-[`no-unresolved`]: ./docs/rules/no-unresolved.md
-[`named`]: ./docs/rules/named.md
-[`default`]: ./docs/rules/default.md
-[`namespace`]: ./docs/rules/namespace.md
-[`no-restricted-paths`]: ./docs/rules/no-restricted-paths.md
-[`no-absolute-path`]: ./docs/rules/no-absolute-path.md
-[`no-dynamic-require`]: ./docs/rules/no-dynamic-require.md
-[`no-internal-modules`]: ./docs/rules/no-internal-modules.md
-[`no-webpack-loader-syntax`]: ./docs/rules/no-webpack-loader-syntax.md
-[`no-self-import`]: ./docs/rules/no-self-import.md
-[`no-cycle`]: ./docs/rules/no-cycle.md
-[`no-useless-path-segments`]: ./docs/rules/no-useless-path-segments.md
-[`no-relative-parent-imports`]: ./docs/rules/no-relative-parent-imports.md
-[`no-relative-packages`]: ./docs/rules/no-relative-packages.md
+<!-- begin auto-generated rules list -->
+
+💼 Configurations enabled in.\
+⚠️ Configurations set to warn in.\
+🚫 Configurations disabled in.\
+❗ Set in the `errors` configuration.\
+☑️ Set in the `recommended` configuration.\
+⌨️ Set in the `typescript` configuration.\
+🚸 Set in the `warnings` configuration.\
+🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
+💡 Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).\
+❌ Deprecated.
 
 ### Helpful warnings
 
-
-* Report any invalid exports, i.e. re-export of the same name ([`export`])
-* Report use of exported name as identifier of default export ([`no-named-as-default`])
-* Report use of exported name as property of default export ([`no-named-as-default-member`])
-* Report imported names marked with `@deprecated` documentation tag ([`no-deprecated`])
-* Forbid the use of extraneous packages ([`no-extraneous-dependencies`])
-* Forbid the use of mutable exports with `var` or `let`. ([`no-mutable-exports`])
-* Report modules without exports, or exports without matching import in another module ([`no-unused-modules`])
-* Prevent empty named import blocks ([`no-empty-named-blocks`])
-
-[`export`]: ./docs/rules/export.md
-[`no-named-as-default`]: ./docs/rules/no-named-as-default.md
-[`no-named-as-default-member`]: ./docs/rules/no-named-as-default-member.md
-[`no-deprecated`]: ./docs/rules/no-deprecated.md
-[`no-extraneous-dependencies`]: ./docs/rules/no-extraneous-dependencies.md
-[`no-mutable-exports`]: ./docs/rules/no-mutable-exports.md
-[`no-unused-modules`]: ./docs/rules/no-unused-modules.md
-[`no-empty-named-blocks`]: ./docs/rules/no-empty-named-blocks.md
+| Name                                                                   | Description                                                                           | 💼   | ⚠️    | 🚫 | 🔧 | 💡 | ❌  |
+| :--------------------------------------------------------------------- | :------------------------------------------------------------------------------------ | :--- | :---- | :- | :- | :- | :- |
+| [export](docs/rules/export.md)                                         | Forbid any invalid exports, i.e. re-export of the same name.                          | ❗ ☑️ |       |    |    |    |    |
+| [no-deprecated](docs/rules/no-deprecated.md)                           | Forbid imported names marked with `@deprecated` documentation tag.                    |      |       |    |    |    |    |
+| [no-empty-named-blocks](docs/rules/no-empty-named-blocks.md)           | Forbid empty named import blocks.                                                     |      |       |    | 🔧 | 💡 |    |
+| [no-extraneous-dependencies](docs/rules/no-extraneous-dependencies.md) | Forbid the use of extraneous packages.                                                |      |       |    |    |    |    |
+| [no-mutable-exports](docs/rules/no-mutable-exports.md)                 | Forbid the use of mutable exports with `var` or `let`.                                |      |       |    |    |    |    |
+| [no-named-as-default](docs/rules/no-named-as-default.md)               | Forbid use of exported name as identifier of default export.                          |      | ☑️ 🚸 |    |    |    |    |
+| [no-named-as-default-member](docs/rules/no-named-as-default-member.md) | Forbid use of exported name as property of default export.                            |      | ☑️ 🚸 |    |    |    |    |
+| [no-unused-modules](docs/rules/no-unused-modules.md)                   | Forbid modules without exports, or exports without matching import in another module. |      |       |    |    |    |    |
 
 ### Module systems
 
-* Report potentially ambiguous parse goal (`script` vs. `module`) ([`unambiguous`])
-* Report CommonJS `require` calls and `module.exports` or `exports.*`. ([`no-commonjs`])
-* Report AMD `require` and `define` calls. ([`no-amd`])
-* No Node.js builtin modules. ([`no-nodejs-modules`])
-* Forbid imports with CommonJS exports ([`no-import-module-exports`])
+| Name                                                               | Description                                                          | 💼 | ⚠️ | 🚫 | 🔧 | 💡 | ❌  |
+| :----------------------------------------------------------------- | :------------------------------------------------------------------- | :- | :- | :- | :- | :- | :- |
+| [no-amd](docs/rules/no-amd.md)                                     | Forbid AMD `require` and `define` calls.                             |    |    |    |    |    |    |
+| [no-commonjs](docs/rules/no-commonjs.md)                           | Forbid CommonJS `require` calls and `module.exports` or `exports.*`. |    |    |    |    |    |    |
+| [no-import-module-exports](docs/rules/no-import-module-exports.md) | Forbid import statements with CommonJS module.exports.               |    |    |    | 🔧 |    |    |
+| [no-nodejs-modules](docs/rules/no-nodejs-modules.md)               | Forbid Node.js builtin modules.                                      |    |    |    |    |    |    |
+| [unambiguous](docs/rules/unambiguous.md)                           | Forbid potentially ambiguous parse goal (`script` vs. `module`).     |    |    |    |    |    |    |
 
-[`unambiguous`]: ./docs/rules/unambiguous.md
-[`no-commonjs`]: ./docs/rules/no-commonjs.md
-[`no-amd`]: ./docs/rules/no-amd.md
-[`no-nodejs-modules`]: ./docs/rules/no-nodejs-modules.md
-[`no-import-module-exports`]: ./docs/rules/no-import-module-exports.md
+### Static analysis
 
+| Name                                                                   | Description                                                                          | 💼   | ⚠️ | 🚫 | 🔧 | 💡 | ❌  |
+| :--------------------------------------------------------------------- | :----------------------------------------------------------------------------------- | :--- | :- | :- | :- | :- | :- |
+| [default](docs/rules/default.md)                                       | Ensure a default export is present, given a default import.                          | ❗ ☑️ |    |    |    |    |    |
+| [named](docs/rules/named.md)                                           | Ensure named imports correspond to a named export in the remote file.                | ❗ ☑️ |    | ⌨️ |    |    |    |
+| [namespace](docs/rules/namespace.md)                                   | Ensure imported namespaces contain dereferenced properties as they are dereferenced. | ❗ ☑️ |    |    |    |    |    |
+| [no-absolute-path](docs/rules/no-absolute-path.md)                     | Forbid import of modules using absolute paths.                                       |      |    |    |    |    |    |
+| [no-cycle](docs/rules/no-cycle.md)                                     | Forbid a module from importing a module with a dependency path back to itself.       |      |    |    |    |    |    |
+| [no-dynamic-require](docs/rules/no-dynamic-require.md)                 | Forbid `require()` calls with expressions.                                           |      |    |    |    |    |    |
+| [no-internal-modules](docs/rules/no-internal-modules.md)               | Forbid importing the submodules of other modules.                                    |      |    |    |    |    |    |
+| [no-relative-packages](docs/rules/no-relative-packages.md)             | Forbid importing packages through relative paths.                                    |      |    |    | 🔧 |    |    |
+| [no-relative-parent-imports](docs/rules/no-relative-parent-imports.md) | Forbid importing modules from parent directories.                                    |      |    |    |    |    |    |
+| [no-restricted-paths](docs/rules/no-restricted-paths.md)               | Enforce which files can be imported in a given folder.                               |      |    |    |    |    |    |
+| [no-self-import](docs/rules/no-self-import.md)                         | Forbid a module from importing itself.                                               |      |    |    |    |    |    |
+| [no-unresolved](docs/rules/no-unresolved.md)                           | Ensure imports point to a file/module that can be resolved.                          | ❗ ☑️ |    |    |    |    |    |
+| [no-useless-path-segments](docs/rules/no-useless-path-segments.md)     | Forbid unnecessary path segments in import and require statements.                   |      |    |    | 🔧 |    |    |
+| [no-webpack-loader-syntax](docs/rules/no-webpack-loader-syntax.md)     | Forbid webpack loader syntax in imports.                                             |      |    |    |    |    |    |
 
 ### Style guide
 
-* Ensure all imports appear before other statements ([`first`])
-* Ensure all exports appear after other statements ([`exports-last`])
-* Report repeated import of the same module in multiple places ([`no-duplicates`])
-* Forbid namespace (a.k.a. "wildcard" `*`) imports ([`no-namespace`])
-* Ensure consistent use of file extension within the import path ([`extensions`])
-* Enforce a convention in module import order ([`order`])
-* Enforce a newline after import statements ([`newline-after-import`])
-* Prefer a default export if module exports a single name ([`prefer-default-export`])
-* Limit the maximum number of dependencies a module can have ([`max-dependencies`])
-* Forbid unassigned imports ([`no-unassigned-import`])
-* Forbid named default exports ([`no-named-default`])
-* Forbid default exports ([`no-default-export`])
-* Forbid named exports ([`no-named-export`])
-* Forbid anonymous values as default exports ([`no-anonymous-default-export`])
-* Prefer named exports to be grouped together in a single export declaration ([`group-exports`])
-* Enforce a leading comment with the webpackChunkName for dynamic imports ([`dynamic-import-chunkname`])
-* Enforce or ban the use of inline type-only markers for named imports ([`consistent-type-specifier-style`])
-
-[`first`]: ./docs/rules/first.md
-[`exports-last`]: ./docs/rules/exports-last.md
-[`no-duplicates`]: ./docs/rules/no-duplicates.md
-[`no-namespace`]: ./docs/rules/no-namespace.md
-[`extensions`]: ./docs/rules/extensions.md
-[`order`]: ./docs/rules/order.md
-[`newline-after-import`]: ./docs/rules/newline-after-import.md
-[`prefer-default-export`]: ./docs/rules/prefer-default-export.md
-[`max-dependencies`]: ./docs/rules/max-dependencies.md
-[`no-unassigned-import`]: ./docs/rules/no-unassigned-import.md
-[`no-named-default`]: ./docs/rules/no-named-default.md
-[`no-anonymous-default-export`]: ./docs/rules/no-anonymous-default-export.md
-[`group-exports`]: ./docs/rules/group-exports.md
-[`no-default-export`]: ./docs/rules/no-default-export.md
-[`no-named-export`]: ./docs/rules/no-named-export.md
-[`dynamic-import-chunkname`]: ./docs/rules/dynamic-import-chunkname.md
-[`consistent-type-specifier-style`]: ./docs/rules/consistent-type-specifier-style.md
+| Name                                                                             | Description                                                                | 💼 | ⚠️    | 🚫 | 🔧 | 💡 | ❌  |
+| :------------------------------------------------------------------------------- | :------------------------------------------------------------------------- | :- | :---- | :- | :- | :- | :- |
+| [consistent-type-specifier-style](docs/rules/consistent-type-specifier-style.md) | Enforce or ban the use of inline type-only markers for named imports.      |    |       |    | 🔧 |    |    |
+| [dynamic-import-chunkname](docs/rules/dynamic-import-chunkname.md)               | Enforce a leading comment with the webpackChunkName for dynamic imports.   |    |       |    |    |    |    |
+| [exports-last](docs/rules/exports-last.md)                                       | Ensure all exports appear after other statements.                          |    |       |    |    |    |    |
+| [extensions](docs/rules/extensions.md)                                           | Ensure consistent use of file extension within the import path.            |    |       |    |    |    |    |
+| [first](docs/rules/first.md)                                                     | Ensure all imports appear before other statements.                         |    |       |    | 🔧 |    |    |
+| [group-exports](docs/rules/group-exports.md)                                     | Prefer named exports to be grouped together in a single export declaration |    |       |    |    |    |    |
+| [imports-first](docs/rules/imports-first.md)                                     | Replaced by `import/first`.                                                |    |       |    | 🔧 |    | ❌  |
+| [max-dependencies](docs/rules/max-dependencies.md)                               | Enforce the maximum number of dependencies a module can have.              |    |       |    |    |    |    |
+| [newline-after-import](docs/rules/newline-after-import.md)                       | Enforce a newline after import statements.                                 |    |       |    | 🔧 |    |    |
+| [no-anonymous-default-export](docs/rules/no-anonymous-default-export.md)         | Forbid anonymous values as default exports.                                |    |       |    |    |    |    |
+| [no-default-export](docs/rules/no-default-export.md)                             | Forbid default exports.                                                    |    |       |    |    |    |    |
+| [no-duplicates](docs/rules/no-duplicates.md)                                     | Forbid repeated import of the same module in multiple places.              |    | ☑️ 🚸 |    | 🔧 |    |    |
+| [no-named-default](docs/rules/no-named-default.md)                               | Forbid named default exports.                                              |    |       |    |    |    |    |
+| [no-named-export](docs/rules/no-named-export.md)                                 | Forbid named exports.                                                      |    |       |    |    |    |    |
+| [no-namespace](docs/rules/no-namespace.md)                                       | Forbid namespace (a.k.a. "wildcard" `*`) imports.                          |    |       |    | 🔧 |    |    |
+| [no-unassigned-import](docs/rules/no-unassigned-import.md)                       | Forbid unassigned imports                                                  |    |       |    |    |    |    |
+| [order](docs/rules/order.md)                                                     | Enforce a convention in module import order.                               |    |       |    | 🔧 |    |    |
+| [prefer-default-export](docs/rules/prefer-default-export.md)                     | Prefer a default export if module exports a single name.                   |    |       |    |    |    |    |
+
+<!-- end auto-generated rules list -->
 
 ## `eslint-plugin-import` for enterprise
 
@@ -209,6 +183,7 @@ settings:
   # uses 'eslint-import-resolver-foo':
   import/resolver: foo
 ```
+
 ```js
 // .eslintrc.js
 module.exports = {
@@ -227,6 +202,7 @@ module.exports = {
 settings:
   import/resolver: 'my-awesome-npm-module'
 ```
+
 ```js
 // .eslintrc.js
 module.exports = {
@@ -254,8 +230,6 @@ module.exports = {
 Relative paths will be resolved relative to the source's nearest `package.json` or
 the process's current working directory if no `package.json` is found.
 
-
-
 If you are interesting in writing a resolver, see the [spec](./resolvers/README.md) for more details.
 
 [`resolve`]: https://www.npmjs.com/package/resolve
@@ -264,11 +238,11 @@ If you are interesting in writing a resolver, see the [spec](./resolvers/README.
 [Node]: https://www.npmjs.com/package/eslint-import-resolver-node
 [webpack]: https://www.npmjs.com/package/eslint-import-resolver-webpack
 
-# Settings
+## Settings
 
 You may set the following settings in your `.eslintrc`:
 
-#### `import/extensions`
+### `import/extensions`
 
 A list of file extensions that will be parsed as modules and inspected for
 `export`s.
@@ -309,7 +283,7 @@ factor into the `no-unresolved` rule.
 
 Also, the following `import/ignore` patterns will overrule this list.
 
-#### `import/ignore`
+### `import/ignore`
 
 A list of regex strings that, if matched by a path, will
 not report the matching module if no `export`s are found.
@@ -325,7 +299,7 @@ settings:
     - \.(scss|less|css)$ # can't parse unprocessed CSS modules, either
 ```
 
-#### `import/core-modules`
+### `import/core-modules`
 
 An array of additional modules to consider as "core" modules--modules that should
 be considered resolved but have no path on the filesystem. Your resolver may
@@ -352,7 +326,7 @@ that specifies this for you.
 
 Contribution of more such shared configs for other platforms are welcome!
 
-#### `import/external-module-folders`
+### `import/external-module-folders`
 
 An array of folders. Resolved modules only from those folders will be considered as "external". By default - `["node_modules"]`. Makes sense if you have configured your path or webpack to handle your internal paths differently and want to consider modules from some folders, for example `bower_components` or `jspm_modules`, as "external".
 
@@ -370,7 +344,7 @@ Each item in this array is either a folder's name, its subpath, or its absolute
 
 Please note that incomplete names are not allowed here so `components` won't match `bower_components` and `packages/ui` won't match `packages/ui-utils` (but will match `packages/ui/utils`).
 
-#### `import/parsers`
+### `import/parsers`
 
 A map from parsers to file extension arrays. If a file extension is matched, the
 dependency parser will require and use the map key as the parser instead of the
@@ -397,12 +371,11 @@ depending on how far down the rabbit hole goes. Submit an issue if you find stra
 behavior beyond here, but steel your heart against the likely outcome of closing
 with `wontfix`.
 
-
-#### `import/resolver`
+### `import/resolver`
 
 See [resolvers](#resolvers).
 
-#### `import/cache`
+### `import/cache`
 
 Settings for cache behavior. Memoization is used at various levels to avoid the copious amount of `fs.statSync`/module parse calls required to correctly report errors.
 
@@ -431,7 +404,7 @@ settings:
 [`eslint_d`]: https://www.npmjs.com/package/eslint_d
 [`eslint-loader`]: https://www.npmjs.com/package/eslint-loader
 
-#### `import/internal-regex`
+### `import/internal-regex`
 
 A regex for packages should be treated as internal. Useful when you are utilizing a monorepo setup or developing a set of packages that depend on each other.
 
@@ -445,7 +418,6 @@ settings:
   import/internal-regex: ^@scope/
 ```
 
-
 ## SublimeLinter-eslint
 
 SublimeLinter-eslint introduced a change to support `.eslintignore` files
@@ -510,6 +482,7 @@ I also found that I needed to set `rc_search_limit` to `null`, which removes the
 hierarchy search limit when looking up the directory tree for `.sublimelinterrc`:
 
 In Package Settings / SublimeLinter / User Settings:
+
 ```json
 {
   "user": {
diff --git a/docs/rules/consistent-type-specifier-style.md b/docs/rules/consistent-type-specifier-style.md
index 4314e33867..54c09049ef 100644
--- a/docs/rules/consistent-type-specifier-style.md
+++ b/docs/rules/consistent-type-specifier-style.md
@@ -1,5 +1,9 @@
 # import/consistent-type-specifier-style
 
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 In both Flow and TypeScript you can mark an import as a type-only import by adding a "kind" marker to the import. Both languages support two positions for marker.
 
 **At the top-level** which marks all names in the import as type-only and applies to named, default, and namespace (for TypeScript) specifiers:
diff --git a/docs/rules/default.md b/docs/rules/default.md
index f69934468a..ffbbdc166a 100644
--- a/docs/rules/default.md
+++ b/docs/rules/default.md
@@ -1,5 +1,9 @@
 # import/default
 
+💼 This rule is enabled in the following configs: ❗ `errors`, ☑️ `recommended`.
+
+<!-- end auto-generated rule header -->
+
 If a default import is requested, this rule will report if there is no default
 export in the imported module.
 
diff --git a/docs/rules/dynamic-import-chunkname.md b/docs/rules/dynamic-import-chunkname.md
index 6b43074f19..472a366485 100644
--- a/docs/rules/dynamic-import-chunkname.md
+++ b/docs/rules/dynamic-import-chunkname.md
@@ -1,5 +1,7 @@
 # import/dynamic-import-chunkname
 
+<!-- end auto-generated rule header -->
+
 This rule reports any dynamic imports without a webpackChunkName specified in a leading block comment in the proper format.
 
 This rule enforces naming of webpack chunks in dynamic imports. When you don't explicitly name chunks, webpack will autogenerate chunk names that are not consistent across builds, which prevents long-term browser caching.
diff --git a/docs/rules/export.md b/docs/rules/export.md
index e99882be85..115d2d8b29 100644
--- a/docs/rules/export.md
+++ b/docs/rules/export.md
@@ -1,5 +1,9 @@
 # import/export
 
+💼 This rule is enabled in the following configs: ❗ `errors`, ☑️ `recommended`.
+
+<!-- end auto-generated rule header -->
+
 Reports funny business with exports, like repeated exports of names or defaults.
 
 ## Rule Details
diff --git a/docs/rules/exports-last.md b/docs/rules/exports-last.md
index 291daee484..6b3e4bac40 100644
--- a/docs/rules/exports-last.md
+++ b/docs/rules/exports-last.md
@@ -1,5 +1,7 @@
 # import/exports-last
 
+<!-- end auto-generated rule header -->
+
 This rule enforces that all exports are declared at the bottom of the file. This rule will report any export declarations that comes before any non-export statements.
 
 
diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md
index 575895c5a0..9e78b8c70f 100644
--- a/docs/rules/extensions.md
+++ b/docs/rules/extensions.md
@@ -1,4 +1,6 @@
-# import/extensions - Ensure consistent use of file extension within the import path
+# import/extensions
+
+<!-- end auto-generated rule header -->
 
 Some file resolve algorithms allow you to omit the file extension within the import source path. For example the `node` resolver can resolve `./foo/bar` to the absolute path `/User/someone/foo/bar.js` because the `.js` extension is resolved automatically by default. Depending on the resolver you can configure more extensions to get resolved automatically.
 
@@ -37,6 +39,7 @@ By providing both a string and an object, the string will set the default settin
 For example, `["error", "never", { "svg": "always" }]` would require that all extensions are omitted, except for "svg".
 
 `ignorePackages` can be set as a separate boolean option like this:
+
 ```
 "import/extensions": [
   <severity>,
@@ -49,10 +52,10 @@ For example, `["error", "never", { "svg": "always" }]` would require that all ex
   }
 ]
 ```
+
 In that case, if you still want to specify extensions, you can do so inside the **pattern** property.
 Default value of `ignorePackages` is `false`.
 
-
 ### Exception
 
 When disallowing the use of certain extensions this rule makes an exception and allows the use of extension when the file would not be resolvable without extension.
diff --git a/docs/rules/first.md b/docs/rules/first.md
index c71ab7d8ab..21904e2fa1 100644
--- a/docs/rules/first.md
+++ b/docs/rules/first.md
@@ -1,5 +1,9 @@
 # import/first
 
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 This rule reports any imports that come after non-import
 statements.
 
diff --git a/docs/rules/group-exports.md b/docs/rules/group-exports.md
index e6b9887b24..c5a23cd218 100644
--- a/docs/rules/group-exports.md
+++ b/docs/rules/group-exports.md
@@ -1,5 +1,7 @@
 # import/group-exports
 
+<!-- end auto-generated rule header -->
+
 Reports when named exports are not grouped together in a single `export` declaration or when multiple assignments to CommonJS `module.exports` or `exports` object are present in a single file.
 
 **Rationale:** An `export` declaration or `module.exports` assignment can appear anywhere in the code. By requiring a single export declaration all your exports will remain at one place, making it easier to see what exports a module provides.
diff --git a/docs/rules/imports-first.md b/docs/rules/imports-first.md
index 4b90f04ea8..278e4c4725 100644
--- a/docs/rules/imports-first.md
+++ b/docs/rules/imports-first.md
@@ -1,3 +1,9 @@
 # import/imports-first
 
+❌ This rule is deprecated.
+
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/import-js/eslint-plugin-import/blob/HEAD/docs/rules/first.md).
diff --git a/docs/rules/max-dependencies.md b/docs/rules/max-dependencies.md
index 3bead8273d..1da74f6818 100644
--- a/docs/rules/max-dependencies.md
+++ b/docs/rules/max-dependencies.md
@@ -1,5 +1,7 @@
 # import/max-dependencies
 
+<!-- end auto-generated rule header -->
+
 Forbid modules to have too many dependencies (`import` or `require` statements).
 
 This is a useful rule because a module with too many dependencies is a code smell, and usually indicates the module is doing too much and/or should be broken up into smaller modules.
diff --git a/docs/rules/named.md b/docs/rules/named.md
index 0f697cc254..6d376defac 100644
--- a/docs/rules/named.md
+++ b/docs/rules/named.md
@@ -1,5 +1,9 @@
 # import/named
 
+💼🚫 This rule is enabled in the following configs: ❗ `errors`, ☑️ `recommended`. This rule is _disabled_ in the ⌨️ `typescript` config.
+
+<!-- end auto-generated rule header -->
+
 Verifies that all named imports are part of the set of named exports in the referenced module.
 
 For `export`, verifies that all named exports exist in the referenced module.
diff --git a/docs/rules/namespace.md b/docs/rules/namespace.md
index 4bbbd378e9..5ac25b750d 100644
--- a/docs/rules/namespace.md
+++ b/docs/rules/namespace.md
@@ -1,5 +1,9 @@
 # import/namespace
 
+💼 This rule is enabled in the following configs: ❗ `errors`, ☑️ `recommended`.
+
+<!-- end auto-generated rule header -->
+
 Enforces names exist at the time they are dereferenced, when imported as a full namespace (i.e. `import * as foo from './foo'; foo.bar();` will report if `bar` is not exported by `./foo`.).
 
 Will report at the import declaration if there are _no_ exported names found.
diff --git a/docs/rules/newline-after-import.md b/docs/rules/newline-after-import.md
index ab454e4bdc..ed0a5b678f 100644
--- a/docs/rules/newline-after-import.md
+++ b/docs/rules/newline-after-import.md
@@ -1,5 +1,9 @@
 # import/newline-after-import
 
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 Enforces having one or more empty lines after the last top-level import statement or require call.
 +(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule.
 
diff --git a/docs/rules/no-absolute-path.md b/docs/rules/no-absolute-path.md
index 305e8e6050..3d85b9eba7 100644
--- a/docs/rules/no-absolute-path.md
+++ b/docs/rules/no-absolute-path.md
@@ -1,7 +1,11 @@
-# import/no-absolute-path: Forbid import of modules using absolute paths
+# import/no-absolute-path
+
+<!-- end auto-generated rule header -->
 
 Node.js allows the import of modules using an absolute path such as `/home/xyz/file.js`. That is a bad practice as it ties the code using it to your computer, and therefore makes it unusable in packages distributed on `npm` for instance.
 
+This rule forbids the import of modules using absolute paths.
+
 ## Rule Details
 
 ### Fail
diff --git a/docs/rules/no-amd.md b/docs/rules/no-amd.md
index f7146c1347..155c19b3ca 100644
--- a/docs/rules/no-amd.md
+++ b/docs/rules/no-amd.md
@@ -1,5 +1,7 @@
 # import/no-amd
 
+<!-- end auto-generated rule header -->
+
 Reports `require([array], ...)` and `define([array], ...)` function calls at the
 module scope. Will not report if !=2 arguments, or first argument is not a literal array.
 
diff --git a/docs/rules/no-anonymous-default-export.md b/docs/rules/no-anonymous-default-export.md
index 3edac63135..d3c88f94e0 100644
--- a/docs/rules/no-anonymous-default-export.md
+++ b/docs/rules/no-anonymous-default-export.md
@@ -1,5 +1,7 @@
 # import/no-anonymous-default-export
 
+<!-- end auto-generated rule header -->
+
 Reports if a module's default export is unnamed. This includes several types of unnamed data types; literals, object expressions, arrays, anonymous functions, arrow functions, and anonymous class declarations.
 
 Ensuring that default exports are named helps improve the grepability of the codebase by encouraging the re-use of the same identifier for the module's default export at its declaration site and at its import sites.
diff --git a/docs/rules/no-commonjs.md b/docs/rules/no-commonjs.md
index 7be4bb3993..09a6b44010 100644
--- a/docs/rules/no-commonjs.md
+++ b/docs/rules/no-commonjs.md
@@ -1,5 +1,7 @@
 # import/no-commonjs
 
+<!-- end auto-generated rule header -->
+
 Reports `require([string])` function calls. Will not report if >1 argument,
 or single argument is not a literal string.
 
diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md
index 70b2ceb9b8..1593842df8 100644
--- a/docs/rules/no-cycle.md
+++ b/docs/rules/no-cycle.md
@@ -1,5 +1,7 @@
 # import/no-cycle
 
+<!-- end auto-generated rule header -->
+
 Ensures that there is no resolvable path back to this module via its dependencies.
 
 This includes cycles of depth 1 (imported module imports me) to `"∞"` (or `Infinity`), if the
diff --git a/docs/rules/no-default-export.md b/docs/rules/no-default-export.md
index 4f1a300a26..586d5e7451 100644
--- a/docs/rules/no-default-export.md
+++ b/docs/rules/no-default-export.md
@@ -1,4 +1,6 @@
-# `import/no-default-export`
+# import/no-default-export
+
+<!-- end auto-generated rule header -->
 
 Prohibit default exports. Mostly an inverse of [`prefer-default-export`].
 
diff --git a/docs/rules/no-deprecated.md b/docs/rules/no-deprecated.md
index c948b51781..641fc1a8f4 100644
--- a/docs/rules/no-deprecated.md
+++ b/docs/rules/no-deprecated.md
@@ -1,4 +1,6 @@
-# `import/no-deprecated`
+# import/no-deprecated
+
+<!-- end auto-generated rule header -->
 
 Reports use of a deprecated name, as indicated by a JSDoc block with a `@deprecated`
 tag or TomDoc `Deprecated: ` comment.
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index 5252db1b79..3ca8d1af26 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -1,5 +1,11 @@
 # import/no-duplicates
 
+⚠️ This rule _warns_ in the following configs: ☑️ `recommended`, 🚸 `warnings`.
+
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 Reports if a resolved path is imported more than once.
 +(fixable) The `--fix` option on the [command line] automatically fixes some problems reported by this rule.
 
diff --git a/docs/rules/no-dynamic-require.md b/docs/rules/no-dynamic-require.md
index 0f7bb6d371..292055fcdc 100644
--- a/docs/rules/no-dynamic-require.md
+++ b/docs/rules/no-dynamic-require.md
@@ -1,8 +1,10 @@
-# import/no-dynamic-require: Forbid `require()` calls with expressions
+# import/no-dynamic-require
+
+<!-- end auto-generated rule header -->
 
 The `require` method from CommonJS is used to import modules from different files. Unlike the ES6 `import` syntax, it can be given expressions that will be resolved at runtime. While this is sometimes necessary and useful, in most cases it isn't. Using expressions (for instance, concatenating a path and variable) as the argument makes it harder for tools to do static code analysis, or to find where in the codebase a module is used.
 
-This rule checks every call to `require()` that uses expressions for the module name argument.
+This rule forbids every call to `require()` that uses expressions for the module name argument.
 
 ## Rule Details
 
diff --git a/docs/rules/no-empty-named-blocks.md b/docs/rules/no-empty-named-blocks.md
index 229d927478..7bf4d695cf 100644
--- a/docs/rules/no-empty-named-blocks.md
+++ b/docs/rules/no-empty-named-blocks.md
@@ -1,5 +1,9 @@
 # import/no-empty-named-blocks
 
+🔧💡 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) and manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
+
+<!-- end auto-generated rule header -->
+
 Reports the use of empty named import blocks.
 
 ## Rule Details
diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index 70c08809cf..68cd4b154f 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -1,4 +1,6 @@
-# import/no-extraneous-dependencies: Forbid the use of extraneous packages
+# import/no-extraneous-dependencies
+
+<!-- end auto-generated rule header -->
 
 Forbid the import of external modules that are not declared in the `package.json`'s `dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`, or `bundledDependencies`.
 The closest parent `package.json` will be used. If no `package.json` is found, the rule will not lint anything. This behavior can be changed with the rule option `packageDir`. Normally ignores imports of modules marked internal, but this can be changed with the rule option `includeInternal`. Type imports can be verified by specifying `includeTypes`.
diff --git a/docs/rules/no-import-module-exports.md b/docs/rules/no-import-module-exports.md
index d658deb566..08aacfcc34 100644
--- a/docs/rules/no-import-module-exports.md
+++ b/docs/rules/no-import-module-exports.md
@@ -1,5 +1,9 @@
 # import/no-import-module-exports
 
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 Reports the use of import declarations with CommonJS exports in any module
 except for the [main module](https://docs.npmjs.com/files/package.json#main).
 
diff --git a/docs/rules/no-internal-modules.md b/docs/rules/no-internal-modules.md
index d957e26f36..47f7490da6 100644
--- a/docs/rules/no-internal-modules.md
+++ b/docs/rules/no-internal-modules.md
@@ -1,5 +1,7 @@
 # import/no-internal-modules
 
+<!-- end auto-generated rule header -->
+
 Use this rule to prevent importing the submodules of other modules.
 
 ## Rule Details
diff --git a/docs/rules/no-mutable-exports.md b/docs/rules/no-mutable-exports.md
index f4cc7843ad..f0a6251c19 100644
--- a/docs/rules/no-mutable-exports.md
+++ b/docs/rules/no-mutable-exports.md
@@ -1,5 +1,7 @@
 # import/no-mutable-exports
 
+<!-- end auto-generated rule header -->
+
 Forbids the use of mutable exports with `var` or `let`.
 
 ## Rule Details
diff --git a/docs/rules/no-named-as-default-member.md b/docs/rules/no-named-as-default-member.md
index da6ae3f1d4..5e0f5069e9 100644
--- a/docs/rules/no-named-as-default-member.md
+++ b/docs/rules/no-named-as-default-member.md
@@ -1,5 +1,9 @@
 # import/no-named-as-default-member
 
+⚠️ This rule _warns_ in the following configs: ☑️ `recommended`, 🚸 `warnings`.
+
+<!-- end auto-generated rule header -->
+
 Reports use of an exported name as a property on the default export.
 
 Rationale: Accessing a property that has a name that is shared by an exported
diff --git a/docs/rules/no-named-as-default.md b/docs/rules/no-named-as-default.md
index 0421413833..b3715e6c44 100644
--- a/docs/rules/no-named-as-default.md
+++ b/docs/rules/no-named-as-default.md
@@ -1,5 +1,9 @@
 # import/no-named-as-default
 
+⚠️ This rule _warns_ in the following configs: ☑️ `recommended`, 🚸 `warnings`.
+
+<!-- end auto-generated rule header -->
+
 Reports use of an exported name as the locally imported name of a default export.
 
 Rationale: using an exported name as the name of the default export is likely...
diff --git a/docs/rules/no-named-default.md b/docs/rules/no-named-default.md
index bb8b13bca4..2f3d54b807 100644
--- a/docs/rules/no-named-default.md
+++ b/docs/rules/no-named-default.md
@@ -1,5 +1,7 @@
 # import/no-named-default
 
+<!-- end auto-generated rule header -->
+
 Reports use of a default export as a locally named import.
 
 Rationale: the syntax exists to import default exports expressively, let's use it.
diff --git a/docs/rules/no-named-export.md b/docs/rules/no-named-export.md
index 0ff881e349..13ea63ad73 100644
--- a/docs/rules/no-named-export.md
+++ b/docs/rules/no-named-export.md
@@ -1,4 +1,6 @@
-# `import/no-named-export`
+# import/no-named-export
+
+<!-- end auto-generated rule header -->
 
 Prohibit named exports. Mostly an inverse of [`no-default-export`].
 
diff --git a/docs/rules/no-namespace.md b/docs/rules/no-namespace.md
index 854f65d6f9..5545bce229 100644
--- a/docs/rules/no-namespace.md
+++ b/docs/rules/no-namespace.md
@@ -1,5 +1,9 @@
 # import/no-namespace
 
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 Enforce a convention of not using namespace (a.k.a. "wildcard" `*`) imports.
 
 +(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule, provided that the namespace object is only used for direct member access, e.g. `namespace.a`.
diff --git a/docs/rules/no-nodejs-modules.md b/docs/rules/no-nodejs-modules.md
index 225adab222..624c27e059 100644
--- a/docs/rules/no-nodejs-modules.md
+++ b/docs/rules/no-nodejs-modules.md
@@ -1,4 +1,6 @@
-# import/no-nodejs-modules: No Node.js builtin modules
+# import/no-nodejs-modules
+
+<!-- end auto-generated rule header -->
 
 Forbid the use of Node.js builtin modules. Can be useful for client-side web projects that do not have access to those modules.
 
diff --git a/docs/rules/no-relative-packages.md b/docs/rules/no-relative-packages.md
index a989c12a23..4919de94e5 100644
--- a/docs/rules/no-relative-packages.md
+++ b/docs/rules/no-relative-packages.md
@@ -1,5 +1,9 @@
 # import/no-relative-packages
 
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 Use this rule to prevent importing packages through relative paths.
 
 It's useful in Yarn/Lerna workspaces, were it's possible to import a sibling
diff --git a/docs/rules/no-relative-parent-imports.md b/docs/rules/no-relative-parent-imports.md
index 7d6e883cff..e5684eb1cf 100644
--- a/docs/rules/no-relative-parent-imports.md
+++ b/docs/rules/no-relative-parent-imports.md
@@ -1,5 +1,7 @@
 # import/no-relative-parent-imports
 
+<!-- end auto-generated rule header -->
+
 Use this rule to prevent imports to folders in relative parent paths.
 
 This rule is useful for enforcing tree-like folder structures instead of complex graph-like folder structures. While this restriction might be a departure from Node's default resolution style, it can lead large, complex codebases to be easier to maintain. If you've ever had debates over "where to put files" this rule is for you.
diff --git a/docs/rules/no-restricted-paths.md b/docs/rules/no-restricted-paths.md
index d22a8b3ea3..344c33bb67 100644
--- a/docs/rules/no-restricted-paths.md
+++ b/docs/rules/no-restricted-paths.md
@@ -1,4 +1,6 @@
-# import/no-restricted-paths: Restrict which files can be imported in a given folder
+# import/no-restricted-paths
+
+<!-- end auto-generated rule header -->
 
 Some projects contain files which are not always meant to be executed in the same environment.
 For example consider a web application that contains specific code for the server and some specific code for the browser/client. In this case you don’t want to import server-only files in your client code.
diff --git a/docs/rules/no-self-import.md b/docs/rules/no-self-import.md
index bde063f5d3..8d8491c508 100644
--- a/docs/rules/no-self-import.md
+++ b/docs/rules/no-self-import.md
@@ -1,4 +1,6 @@
-# Forbid a module from importing itself (`import/no-self-import`)
+# import/no-self-import
+
+<!-- end auto-generated rule header -->
 
 Forbid a module from importing itself. This can sometimes happen during refactoring.
 
diff --git a/docs/rules/no-unassigned-import.md b/docs/rules/no-unassigned-import.md
index fb3065c48f..6f763e9737 100644
--- a/docs/rules/no-unassigned-import.md
+++ b/docs/rules/no-unassigned-import.md
@@ -1,4 +1,6 @@
-# import/no-unassigned-import: Forbid unassigned imports
+# import/no-unassigned-import
+
+<!-- end auto-generated rule header -->
 
 With both CommonJS' `require` and the ES6 modules' `import` syntax, it is possible to import a module but not to use its result. This can be done explicitly by not assigning the module to as variable. Doing so can mean either of the following things:
 - The module is imported but not used
diff --git a/docs/rules/no-unresolved.md b/docs/rules/no-unresolved.md
index 08522deb4c..13f7928877 100644
--- a/docs/rules/no-unresolved.md
+++ b/docs/rules/no-unresolved.md
@@ -1,5 +1,9 @@
 # import/no-unresolved
 
+💼 This rule is enabled in the following configs: ❗ `errors`, ☑️ `recommended`.
+
+<!-- end auto-generated rule header -->
+
 Ensures an imported module can be resolved to a module on the local filesystem,
 as defined by standard Node `require.resolve` behavior.
 
diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index 0bd805612b..5cd24bef41 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -1,5 +1,7 @@
 # import/no-unused-modules
 
+<!-- end auto-generated rule header -->
+
 Reports:
   - modules without any exports
   - individual exports not being statically `import`ed or `require`ed from other modules in the same project
diff --git a/docs/rules/no-useless-path-segments.md b/docs/rules/no-useless-path-segments.md
index 5f01dcb4a2..c8dc67727a 100644
--- a/docs/rules/no-useless-path-segments.md
+++ b/docs/rules/no-useless-path-segments.md
@@ -1,5 +1,9 @@
 # import/no-useless-path-segments
 
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
 Use this rule to prevent unnecessary path segments in import and require statements.
 
 ## Rule Details
diff --git a/docs/rules/no-webpack-loader-syntax.md b/docs/rules/no-webpack-loader-syntax.md
index 271c76ca82..e1b7a4bd9d 100644
--- a/docs/rules/no-webpack-loader-syntax.md
+++ b/docs/rules/no-webpack-loader-syntax.md
@@ -1,5 +1,7 @@
 # import/no-webpack-loader-syntax
 
+<!-- end auto-generated rule header -->
+
 Forbid Webpack loader syntax in imports.
 
 [Webpack](https://webpack.js.org) allows specifying the [loaders](https://webpack.js.org/concepts/loaders/) to use in the import source string using a special syntax like this:
diff --git a/docs/rules/order.md b/docs/rules/order.md
index dbda8b2d77..e3deacaf24 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -1,4 +1,8 @@
-# import/order: Enforce a convention in module import order
+# import/order
+
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
 
 Enforce a convention in the order of `require()` / `import` statements.
 +(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule.
diff --git a/docs/rules/prefer-default-export.md b/docs/rules/prefer-default-export.md
index 4dabb695a2..38ec166e69 100644
--- a/docs/rules/prefer-default-export.md
+++ b/docs/rules/prefer-default-export.md
@@ -1,5 +1,7 @@
 # import/prefer-default-export
 
+<!-- end auto-generated rule header -->
+
 When there is only a single export from a module, prefer using default export over named export.
 
 ## Rule Details
diff --git a/docs/rules/unambiguous.md b/docs/rules/unambiguous.md
index 5be7d3df22..da77a7453f 100644
--- a/docs/rules/unambiguous.md
+++ b/docs/rules/unambiguous.md
@@ -1,5 +1,7 @@
 # import/unambiguous
 
+<!-- end auto-generated rule header -->
+
 Warn if a `module` could be mistakenly parsed as a `script` by a consumer leveraging
 [Unambiguous JavaScript Grammar] to determine correct parsing goal.
 
diff --git a/package.json b/package.json
index c3ffef586e..c48fade822 100644
--- a/package.json
+++ b/package.json
@@ -24,14 +24,16 @@
     "copy-metafiles": "node --require babel-register ./scripts/copyMetafiles",
     "watch": "npm run tests-only -- -- --watch",
     "pretest": "linklocal",
-    "posttest": "eslint .",
+    "posttest": "eslint . && npm run update:eslint-docs -- --check",
     "mocha": "cross-env BABEL_ENV=test nyc mocha",
     "tests-only": "npm run mocha tests/src",
     "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
     "test-all": "node --require babel-register ./scripts/testAll",
     "prepublishOnly": "safe-publish-latest && npm run build",
-    "prepublish": "not-in-publish || npm run prepublishOnly"
+    "prepublish": "not-in-publish || npm run prepublishOnly",
+    "preupdate:eslint-docs": "npm run build",
+    "update:eslint-docs": "eslint-doc-generator --rule-doc-title-format prefix-name --rule-doc-section-options false --split-by meta.docs.category --ignore-config stage-0 --config-emoji recommended,☑️"
   },
   "repository": {
     "type": "git",
@@ -71,6 +73,7 @@
     "cross-env": "^4.0.0",
     "escope": "^3.6.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8",
+    "eslint-doc-generator": "^0.19.0",
     "eslint-import-resolver-node": "file:./resolvers/node",
     "eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
diff --git a/src/rules/consistent-type-specifier-style.js b/src/rules/consistent-type-specifier-style.js
index 73e0ba92f2..869eea91ff 100644
--- a/src/rules/consistent-type-specifier-style.js
+++ b/src/rules/consistent-type-specifier-style.js
@@ -40,7 +40,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
-      description: 'Enforce or ban the use of inline type-only markers for named imports',
+      category: 'Style guide',
+      description: 'Enforce or ban the use of inline type-only markers for named imports.',
       url: docsUrl('consistent-type-specifier-style'),
     },
     fixable: 'code',
diff --git a/src/rules/default.js b/src/rules/default.js
index 6b917ccae3..6ca918ef66 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -5,6 +5,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Static analysis',
+      description: 'Ensure a default export is present, given a default import.',
       url: docsUrl('default'),
     },
     schema: [],
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 2c59d35e59..87a8523dad 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -5,6 +5,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Enforce a leading comment with the webpackChunkName for dynamic imports.',
       url: docsUrl('dynamic-import-chunkname'),
     },
     schema: [{
diff --git a/src/rules/export.js b/src/rules/export.js
index 5d430360a2..da0df1ee75 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -115,6 +115,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Helpful warnings',
+      description: 'Forbid any invalid exports, i.e. re-export of the same name.',
       url: docsUrl('export'),
     },
     schema: [],
diff --git a/src/rules/exports-last.js b/src/rules/exports-last.js
index e89aa7eefe..ed77758d20 100644
--- a/src/rules/exports-last.js
+++ b/src/rules/exports-last.js
@@ -10,6 +10,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Ensure all exports appear after other statements.',
       url: docsUrl('exports-last'),
     },
     schema: [],
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 9dad56f863..7d026c787f 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -63,6 +63,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Ensure consistent use of file extension within the import path.',
       url: docsUrl('extensions'),
     },
 
diff --git a/src/rules/first.js b/src/rules/first.js
index 285a377f27..ebead6cf27 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -10,6 +10,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Ensure all imports appear before other statements.',
       url: docsUrl('first'),
     },
     fixable: 'code',
diff --git a/src/rules/group-exports.js b/src/rules/group-exports.js
index e9fc432977..63af9d9141 100644
--- a/src/rules/group-exports.js
+++ b/src/rules/group-exports.js
@@ -5,6 +5,8 @@ import flat from 'array.prototype.flat';
 const meta = {
   type: 'suggestion',
   docs: {
+    category: 'Style guide',
+    description: 'Prefer named exports to be grouped together in a single export declaration',
     url: docsUrl('group-exports'),
   },
 };
diff --git a/src/rules/imports-first.js b/src/rules/imports-first.js
index ba8af48f00..07bb4633de 100644
--- a/src/rules/imports-first.js
+++ b/src/rules/imports-first.js
@@ -5,6 +5,8 @@ const first = require('./first');
 const newMeta = Object.assign({}, first.meta, {
   deprecated: true,
   docs: {
+    category: 'Style guide',
+    description: 'Replaced by `import/first`.',
     url: docsUrl('imports-first', '7b25c1cb95ee18acc1531002fd343e1e6031f9ed'),
   },
 });
diff --git a/src/rules/max-dependencies.js b/src/rules/max-dependencies.js
index f9bdd12e51..95f34176f5 100644
--- a/src/rules/max-dependencies.js
+++ b/src/rules/max-dependencies.js
@@ -17,6 +17,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Enforce the maximum number of dependencies a module can have.',
       url: docsUrl('max-dependencies'),
     },
 
diff --git a/src/rules/named.js b/src/rules/named.js
index ad1b5e1728..050f835056 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -6,6 +6,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Static analysis',
+      description: 'Ensure named imports correspond to a named export in the remote file.',
       url: docsUrl('named'),
     },
     schema: [
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 405c415cea..3b6019da8d 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -45,6 +45,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Static analysis',
+      description: 'Ensure imported namespaces contain dereferenced properties as they are dereferenced.',
       url: docsUrl('namespace'),
     },
 
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 3f285345f9..36678bfc4e 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -56,6 +56,8 @@ module.exports = {
   meta: {
     type: 'layout',
     docs: {
+      category: 'Style guide',
+      description: 'Enforce a newline after import statements.',
       url: docsUrl('newline-after-import'),
     },
     fixable: 'whitespace',
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index fe0a1b6d31..171419d844 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -6,6 +6,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Static analysis',
+      description: 'Forbid import of modules using absolute paths.',
       url: docsUrl('no-absolute-path'),
     },
     schema: [ makeOptionsSchema() ],
diff --git a/src/rules/no-amd.js b/src/rules/no-amd.js
index 187273589c..90359cd5fd 100644
--- a/src/rules/no-amd.js
+++ b/src/rules/no-amd.js
@@ -13,6 +13,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Module systems',
+      description: 'Forbid AMD `require` and `define` calls.',
       url: docsUrl('no-amd'),
     },
     schema: [],
diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js
index 106f43b091..d9edcc2b36 100644
--- a/src/rules/no-anonymous-default-export.js
+++ b/src/rules/no-anonymous-default-export.js
@@ -79,6 +79,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Forbid anonymous values as default exports.',
       url: docsUrl('no-anonymous-default-export'),
     },
 
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index 9e157f46db..7a35fc8a08 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -69,6 +69,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Module systems',
+      description: 'Forbid CommonJS `require` calls and `module.exports` or `exports.*`.',
       url: docsUrl('no-commonjs'),
     },
 
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index e261ac40b7..63765c863c 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -14,7 +14,11 @@ const traversed = new Set();
 module.exports = {
   meta: {
     type: 'suggestion',
-    docs: { url: docsUrl('no-cycle') },
+    docs: {
+      category: 'Static analysis',
+      description: 'Forbid a module from importing a module with a dependency path back to itself.',
+      url: docsUrl('no-cycle'),
+    },
     schema: [makeOptionsSchema({
       maxDepth: {
         oneOf: [
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index ed1aaf8db6..5fc8c40e4c 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -4,6 +4,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Forbid default exports.',
       url: docsUrl('no-default-export'),
     },
     schema: [],
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index 4913d389b5..7a35a8e673 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -16,6 +16,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Helpful warnings',
+      description: 'Forbid imported names marked with `@deprecated` documentation tag.',
       url: docsUrl('no-deprecated'),
     },
     schema: [],
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index efd9583fbc..4aec2d1e77 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -245,6 +245,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Style guide',
+      description: 'Forbid repeated import of the same module in multiple places.',
       url: docsUrl('no-duplicates'),
     },
     fixable: 'code',
diff --git a/src/rules/no-dynamic-require.js b/src/rules/no-dynamic-require.js
index 27e9a957a7..f334adec67 100644
--- a/src/rules/no-dynamic-require.js
+++ b/src/rules/no-dynamic-require.js
@@ -25,6 +25,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Static analysis',
+      description: 'Forbid `require()` calls with expressions.',
       url: docsUrl('no-dynamic-require'),
     },
     schema: [
diff --git a/src/rules/no-empty-named-blocks.js b/src/rules/no-empty-named-blocks.js
index 65a8515cf0..114736f168 100644
--- a/src/rules/no-empty-named-blocks.js
+++ b/src/rules/no-empty-named-blocks.js
@@ -19,6 +19,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Helpful warnings',
+      description: 'Forbid empty named import blocks.',
       url: docsUrl('no-empty-named-blocks'),
     },
     fixable: 'code',
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 65c396e672..d6437c2fd1 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -254,6 +254,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Helpful warnings',
+      description: 'Forbid the use of extraneous packages.',
       url: docsUrl('no-extraneous-dependencies'),
     },
 
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index 4af1e7b453..d40bae88ce 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -23,8 +23,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
-      description: 'Disallow import statements with module.exports',
-      category: 'Best Practices',
+      category: 'Module systems',
+      description: 'Forbid import statements with CommonJS module.exports.',
       recommended: true,
     },
     fixable: 'code',
diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index a33f23b475..9d44f5859a 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -9,6 +9,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Static analysis',
+      description: 'Forbid importing the submodules of other modules.',
       url: docsUrl('no-internal-modules'),
     },
 
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index c506c997cc..75a321b62a 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -4,6 +4,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Helpful warnings',
+      description: 'Forbid the use of mutable exports with `var` or `let`.',
       url: docsUrl('no-mutable-exports'),
     },
     schema: [],
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index ef2000e229..0fb0927249 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -16,6 +16,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Helpful warnings',
+      description: 'Forbid use of exported name as property of default export.',
       url: docsUrl('no-named-as-default-member'),
     },
     schema: [],
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index 7c1ef0e04c..c3a35ff64a 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -6,6 +6,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Helpful warnings',
+      description: 'Forbid use of exported name as identifier of default export.',
       url: docsUrl('no-named-as-default'),
     },
     schema: [],
diff --git a/src/rules/no-named-default.js b/src/rules/no-named-default.js
index 6a5c1db703..8745ce3890 100644
--- a/src/rules/no-named-default.js
+++ b/src/rules/no-named-default.js
@@ -4,6 +4,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Forbid named default exports.',
       url: docsUrl('no-named-default'),
     },
     schema: [],
diff --git a/src/rules/no-named-export.js b/src/rules/no-named-export.js
index 6c92ad9cae..b0722f3596 100644
--- a/src/rules/no-named-export.js
+++ b/src/rules/no-named-export.js
@@ -3,7 +3,11 @@ import docsUrl from '../docsUrl';
 module.exports = {
   meta: {
     type: 'suggestion',
-    docs: { url: docsUrl('no-named-export') },
+    docs: {
+      category: 'Style guide',
+      description: 'Forbid named exports.',
+      url: docsUrl('no-named-export'),
+    },
     schema: [],
   },
 
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index c615dfff52..4382007a59 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -15,6 +15,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Forbid namespace (a.k.a. "wildcard" `*`) imports.',
       url: docsUrl('no-namespace'),
     },
     fixable: 'code',
diff --git a/src/rules/no-nodejs-modules.js b/src/rules/no-nodejs-modules.js
index 1e3207d208..a87bff796f 100644
--- a/src/rules/no-nodejs-modules.js
+++ b/src/rules/no-nodejs-modules.js
@@ -12,6 +12,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Module systems',
+      description: 'Forbid Node.js builtin modules.',
       url: docsUrl('no-nodejs-modules'),
     },
     schema: [
diff --git a/src/rules/no-relative-packages.js b/src/rules/no-relative-packages.js
index 7bf1ce5cea..6b0a627670 100644
--- a/src/rules/no-relative-packages.js
+++ b/src/rules/no-relative-packages.js
@@ -57,6 +57,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Static analysis',
+      description: 'Forbid importing packages through relative paths.',
       url: docsUrl('no-relative-packages'),
     },
     fixable: 'code',
diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js
index 8e3696275b..fd8dcb302f 100644
--- a/src/rules/no-relative-parent-imports.js
+++ b/src/rules/no-relative-parent-imports.js
@@ -9,6 +9,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Static analysis',
+      description: 'Forbid importing modules from parent directories.',
       url: docsUrl('no-relative-parent-imports'),
     },
     schema: [makeOptionsSchema()],
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 9b17975b5c..b8a461fa2d 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -16,6 +16,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Static analysis',
+      description: 'Enforce which files can be imported in a given folder.',
       url: docsUrl('no-restricted-paths'),
     },
 
diff --git a/src/rules/no-self-import.js b/src/rules/no-self-import.js
index a5f464b242..0ba0f66694 100644
--- a/src/rules/no-self-import.js
+++ b/src/rules/no-self-import.js
@@ -23,7 +23,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
-      description: 'Forbid a module from importing itself',
+      category: 'Static analysis',
+      description: 'Forbid a module from importing itself.',
       recommended: true,
       url: docsUrl('no-self-import'),
     },
diff --git a/src/rules/no-unassigned-import.js b/src/rules/no-unassigned-import.js
index 37be903e0b..b790141927 100644
--- a/src/rules/no-unassigned-import.js
+++ b/src/rules/no-unassigned-import.js
@@ -56,6 +56,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Forbid unassigned imports',
       url: docsUrl('no-unassigned-import'),
     },
     schema: [
diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js
index dafc7cb13f..8216cdf1f2 100644
--- a/src/rules/no-unresolved.js
+++ b/src/rules/no-unresolved.js
@@ -12,6 +12,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Static analysis',
+      description: 'Ensure imports point to a file/module that can be resolved.',
       url: docsUrl('no-unresolved'),
     },
 
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 5feb319036..8f8b4b634c 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -38,14 +38,14 @@ try {
       };
     } catch (e) {
       const { listFilesToProcess: originalListFilesToProcess } = require('eslint/lib/util/glob-util');
-      
+
       listFilesToProcess = function (src, extensions) {
         const patterns = src.reduce((carry, pattern) => {
           return carry.concat(extensions.map((extension) => {
             return /\*\*|\*\./.test(pattern) ? pattern : `${pattern}/**/*${extension}`;
           }));
         }, src.slice());
-    
+
         return originalListFilesToProcess(patterns);
       };
     }
@@ -408,7 +408,11 @@ const fileIsInPkg = file => {
 module.exports = {
   meta: {
     type: 'suggestion',
-    docs: { url: docsUrl('no-unused-modules') },
+    docs: {
+      category: 'Helpful warnings',
+      description: 'Forbid modules without exports, or exports without matching import in another module.',
+      url: docsUrl('no-unused-modules'),
+    },
     schema: [{
       properties: {
         src: {
diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index c0156d09f8..a328be2465 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -40,6 +40,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Static analysis',
+      description: 'Forbid unnecessary path segments in import and require statements.',
       url: docsUrl('no-useless-path-segments'),
     },
 
diff --git a/src/rules/no-webpack-loader-syntax.js b/src/rules/no-webpack-loader-syntax.js
index e517207bac..faedeb4373 100644
--- a/src/rules/no-webpack-loader-syntax.js
+++ b/src/rules/no-webpack-loader-syntax.js
@@ -13,6 +13,8 @@ module.exports = {
   meta: {
     type: 'problem',
     docs: {
+      category: 'Static analysis',
+      description: 'Forbid webpack loader syntax in imports.',
       url: docsUrl('no-webpack-loader-syntax'),
     },
     schema: [],
diff --git a/src/rules/order.js b/src/rules/order.js
index e8d023dfe6..dc9da64f22 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -589,6 +589,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Enforce a convention in module import order.',
       url: docsUrl('order'),
     },
 
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 230efad12f..d1b134cfc1 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -6,6 +6,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Style guide',
+      description: 'Prefer a default export if module exports a single name.',
       url: docsUrl('prefer-default-export'),
     },
     schema: [],
diff --git a/src/rules/unambiguous.js b/src/rules/unambiguous.js
index 576b3379ee..91152ea2af 100644
--- a/src/rules/unambiguous.js
+++ b/src/rules/unambiguous.js
@@ -10,6 +10,8 @@ module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
+      category: 'Module systems',
+      description: 'Forbid potentially ambiguous parse goal (`script` vs. `module`).',
       url: docsUrl('unambiguous'),
     },
     schema: [],

From 2e9379effb153e1989ffac9363a09b5a4e35dfdc Mon Sep 17 00:00:00 2001
From: Adam Trager <hello@adamtrager.com>
Date: Fri, 4 Nov 2022 12:37:31 -0400
Subject: [PATCH 525/767] [readme] Increase clarity around typescript
 configuration

---
 CHANGELOG.md | 6 +++++-
 README.md    | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 78bd21cf3e..c2885b8c3e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -46,6 +46,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Tests] [`no-restricted-paths`]: Tests for `import type` statements ([#2459], thanks [@golergka])
 - [Tests] [`no-restricted-paths`]: fix one failing `import type` test case, submitted by [@golergka], thanks [@azyzz228]
 - [Docs] automate docs with eslint-doc-generator ([#2582], thanks [@bmish])
+- [readme] Increase clarity around typescript configuration ([#2588], thanks [@Nfinished])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1020,6 +1021,8 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2588]: https://github.com/import-js/eslint-plugin-import/pull/2588
+[#2582]: https://github.com/import-js/eslint-plugin-import/pull/2582
 [#2570]: https://github.com/import-js/eslint-plugin-import/pull/2570
 [#2568]: https://github.com/import-js/eslint-plugin-import/pull/2568
 [#2546]: https://github.com/import-js/eslint-plugin-import/pull/2546
@@ -1051,9 +1054,9 @@ for info on changes for earlier releases.
 [#2374]: https://github.com/import-js/eslint-plugin-import/pull/2374
 [#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
 [#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
-[#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
 [#2358]: https://github.com/import-js/eslint-plugin-import/pull/2358
 [#2341]: https://github.com/import-js/eslint-plugin-import/pull/2341
+[#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
 [#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
 [#2330]: https://github.com/import-js/eslint-plugin-import/pull/2330
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
@@ -1695,6 +1698,7 @@ for info on changes for earlier releases.
 [@mrmckeb]: https://github.com/mrmckeb
 [@msvab]: https://github.com/msvab
 [@mx-bernhard]: https://github.com/mx-bernhard
+[@Nfinished]: https://github.com/Nfinished
 [@nickofthyme]: https://github.com/nickofthyme
 [@nicolashenry]: https://github.com/nicolashenry
 [@noelebrun]: https://github.com/noelebrun
diff --git a/README.md b/README.md
index 78344f35e3..ed1e4f822f 100644
--- a/README.md
+++ b/README.md
@@ -133,7 +133,7 @@ rules:
 
 # TypeScript
 
-You may use the following shortcut or assemble your own config using the granular settings described below.
+You may use the following snippet or assemble your own config using the granular settings described below it.
 
 Make sure you have installed [`@typescript-eslint/parser`] and [`eslint-import-resolver-typescript`] which are used in the following configuration.
 

From 6a9d6f2a6da8c8d8b84b13a7505562f6bc88fa1a Mon Sep 17 00:00:00 2001
From: Frazer Smith <frazer.dev@outlook.com>
Date: Sun, 6 Nov 2022 07:51:37 +0000
Subject: [PATCH 526/767] [Fix] `ExportMap`: add missing param to function

---
 CHANGELOG.md     | 3 +++
 src/ExportMap.js | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2885b8c3e..948bbbc530 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`dynamic-import-chunkname`]: prevent false report on a valid webpack magic comment ([#2330], thanks [@mhmadhamster])
 - [`export`]: do not error on TS export overloads ([#1590], thanks [@ljharb])
 - [`no-unresolved`], [`extensions`]: ignore type only exports ([#2436], thanks [@Lukas-Kullmann])
+- [Fix] `ExportMap`: add missing param to function ([#2589], thanks [@Fdawgs])
 
 ### Changed
 - [Tests] [`named`]: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -1021,6 +1022,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2589]: https://github.com/import-js/eslint-plugin-import/pull/2589
 [#2588]: https://github.com/import-js/eslint-plugin-import/pull/2588
 [#2582]: https://github.com/import-js/eslint-plugin-import/pull/2582
 [#2570]: https://github.com/import-js/eslint-plugin-import/pull/2570
@@ -1601,6 +1603,7 @@ for info on changes for earlier releases.
 [@ernestostifano]: https://github.com/ernestostifano
 [@ertrzyiks]: https://github.com/ertrzyiks
 [@fa93hws]: https://github.com/fa93hws
+[@Fdawgs]: https://github.com/Fdawgs
 [@fengkfengk]: https://github.com/fengkfengk
 [@fernandopasik]: https://github.com/fernandopasik
 [@feychenie]: https://github.com/feychenie
diff --git a/src/ExportMap.js b/src/ExportMap.js
index bbf43cf038..a39434bc94 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -547,7 +547,7 @@ ExportMap.parse = function (path, content, context) {
 
   const source = makeSourceCode(content, ast);
 
-  function readTsConfig() {
+  function readTsConfig(context) {
     const tsConfigInfo = tsConfigLoader({
       cwd:
         (context.parserOptions && context.parserOptions.tsconfigRootDir) ||

From 31a802a6d769c8c1db6a518dae0984b785af75fa Mon Sep 17 00:00:00 2001
From: Scott Newcomer <snewcomer24@gmail.com>
Date: Sat, 12 Nov 2022 21:43:18 -0600
Subject: [PATCH 527/767] [Tests] npm 9 defaults `install-links` to `true`,
 which breaks us

---
 .npmrc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.npmrc b/.npmrc
index 43c97e719a..6c93bcba75 100644
--- a/.npmrc
+++ b/.npmrc
@@ -1 +1,2 @@
 package-lock=false
+install-links=false

From 8b0fb989ae08161499a478ab23fb10b68e3cd828 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 15 Nov 2022 23:06:26 -0800
Subject: [PATCH 528/767] [Tests] update nvm in travis

---
 .travis.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.travis.yml b/.travis.yml
index 21a7070fb7..f57222a8ff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,6 +25,7 @@ matrix:
   fast_finish: true
 
 before_install:
+  - 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash && . $NVM_DIR/nvm.sh'
   - 'nvm install-latest-npm'
   - 'NPM_CONFIG_LEGACY_PEER_DEPS=true npm install'
   - 'npm run copy-metafiles'

From 9964463d2c8952120ad7390518f613eb150d0a4d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 17 Nov 2022 09:25:55 -0800
Subject: [PATCH 529/767] [Tests] increase timeouts

---
 tests/src/core/getExports.js         | 10 +++++-----
 tests/src/core/resolve.js            |  4 ++--
 tests/src/rules/no-unused-modules.js |  4 +++-
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 6dea6e0210..86c1915968 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -367,7 +367,7 @@ describe('ExportMap', function () {
 
         let imports;
         before('load imports', function () {
-          this.timeout(20000);  // takes a long time :shrug:
+          this.timeout(20e3);  // takes a long time :shrug:
           sinon.spy(tsConfigLoader, 'tsConfigLoader');
           imports = ExportMap.get('./typescript.ts', context);
         });
@@ -436,13 +436,13 @@ describe('ExportMap', function () {
         it('should cache after parsing for an ambiguous module', function () {
           const source = './typescript-declare-module.ts';
           const parseSpy = sinon.spy(ExportMap, 'parse');
-      
+
           expect(ExportMap.get(source, context)).to.be.null;
-      
+
           ExportMap.get(source, context);
-      
+
           expect(parseSpy.callCount).to.equal(1);
-      
+
           parseSpy.restore();
         });
       });
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index 360d4a2e70..05a6aaeb68 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -401,7 +401,7 @@ describe('resolve', function () {
 
         // special behavior for infinity
         describe('infinite cache', function () {
-          this.timeout(1500);
+          this.timeout(1.5e3);
 
           before((done) => setTimeout(done, 1100));
 
@@ -414,7 +414,7 @@ describe('resolve', function () {
         });
 
         describe('finite cache', function () {
-          this.timeout(1200);
+          this.timeout(1.2e3);
           before((done) => setTimeout(done, 1000));
           it('gets correct values after cache lifetime', function () {
             expect(resolve(original, context)).not.to.exist;
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 8c8fc7c4ed..de169c65da 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -243,7 +243,7 @@ ruleTester.run('no-unused-modules', rule, {
 });
 
 
-describe('dynamic imports', () => {
+describe('dynamic imports', function () {
   if (semver.satisfies(eslintPkg.version, '< 6')) {
     beforeEach(function () {
       this.skip();
@@ -251,6 +251,8 @@ describe('dynamic imports', () => {
     return;
   }
 
+  this.timeout(10e3);
+
   // test for unused exports with `import()`
   ruleTester.run('no-unused-modules', rule, {
     valid: [

From 48e8130a9f33afd0f9d06635c25d4f1df4d63340 Mon Sep 17 00:00:00 2001
From: Michael Pinter <mpinter@ripple.com>
Date: Tue, 15 Nov 2022 16:45:02 -0600
Subject: [PATCH 530/767] [Fix] `no-unused-modules`: `checkPkgFieldObject`
 filters boolean fields from checks

---
 CHANGELOG.md                                             | 5 ++++-
 src/rules/no-unused-modules.js                           | 5 ++++-
 tests/files/no-unused-modules/browserObject/package.json | 3 ++-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 948bbbc530..c9ee1593af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,7 +28,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`dynamic-import-chunkname`]: prevent false report on a valid webpack magic comment ([#2330], thanks [@mhmadhamster])
 - [`export`]: do not error on TS export overloads ([#1590], thanks [@ljharb])
 - [`no-unresolved`], [`extensions`]: ignore type only exports ([#2436], thanks [@Lukas-Kullmann])
-- [Fix] `ExportMap`: add missing param to function ([#2589], thanks [@Fdawgs])
+- `ExportMap`: add missing param to function ([#2589], thanks [@Fdawgs])
+- [`no-unused-modules`]: `checkPkgFieldObject` filters boolean fields from checks ([#2598], thanks [@mpint])
 
 ### Changed
 - [Tests] [`named`]: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -1022,6 +1023,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2598]: https://github.com/import-js/eslint-plugin-import/pull/2598
 [#2589]: https://github.com/import-js/eslint-plugin-import/pull/2589
 [#2588]: https://github.com/import-js/eslint-plugin-import/pull/2588
 [#2582]: https://github.com/import-js/eslint-plugin-import/pull/2582
@@ -1697,6 +1699,7 @@ for info on changes for earlier releases.
 [@mgwalker]: https://github.com/mgwalker
 [@mhmadhamster]: https://github.com/MhMadHamster
 [@MikeyBeLike]: https://github.com/MikeyBeLike
+[@mpint]: https://github.com/mpint
 [@mplewis]: https://github.com/mplewis
 [@mrmckeb]: https://github.com/mrmckeb
 [@msvab]: https://github.com/msvab
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 8f8b4b634c..bd8c524abb 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -364,7 +364,10 @@ const fileIsInPkg = file => {
   };
 
   const checkPkgFieldObject = pkgField => {
-    const pkgFieldFiles = values(pkgField).map(value => join(basePath, value));
+    const pkgFieldFiles = values(pkgField)
+      .filter((value) => typeof value !== 'boolean')
+      .map(value => join(basePath, value));
+
     if (includes(pkgFieldFiles, file)) {
       return true;
     }
diff --git a/tests/files/no-unused-modules/browserObject/package.json b/tests/files/no-unused-modules/browserObject/package.json
index 28272c6fef..7cf213f812 100644
--- a/tests/files/no-unused-modules/browserObject/package.json
+++ b/tests/files/no-unused-modules/browserObject/package.json
@@ -1,5 +1,6 @@
 {
   "browser": {
-    "browserObject": "./index.js"
+    "browserObject": "./index.js",
+    "an-ignored-module": false
   }
 }

From a07dfcb2665dec8c082af16d009fe777a3c4176a Mon Sep 17 00:00:00 2001
From: Frazer Smith <frazer.dev@outlook.com>
Date: Tue, 8 Nov 2022 07:39:14 +0000
Subject: [PATCH 531/767] [actions] update GitHub Actions

---
 .github/workflows/node-4+.yml      |  4 ++--
 .github/workflows/node-pretest.yml |  4 ++--
 .github/workflows/packages.yml     |  4 ++--
 .github/workflows/rebase.yml       | 18 +++---------------
 4 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 01344668fa..2925adda8a 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -99,7 +99,7 @@ jobs:
             eslint: 5
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: ljharb/actions/node/install@main
         continue-on-error: ${{ matrix.eslint == 4 && matrix.node-version == 4 }}
         name: 'nvm install ${{ matrix.node-version }} && npm install, with eslint ${{ matrix.eslint }}'
@@ -113,7 +113,7 @@ jobs:
           skip-ls-check: true
       - run: npm run pretest
       - run: npm run tests-only
-      - uses: codecov/codecov-action@v2
+      - uses: codecov/codecov-action@v3
 
   node:
     name: 'node 4+'
diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml
index 07e4b9d10a..e4340018e4 100644
--- a/.github/workflows/node-pretest.yml
+++ b/.github/workflows/node-pretest.yml
@@ -10,7 +10,7 @@ jobs:
   #   runs-on: ubuntu-latest
 
   #   steps:
-  #     - uses: actions/checkout@v2
+  #     - uses: actions/checkout@v3
   #     - uses: ljharb/actions/node/install@main
   #       name: 'nvm install lts/* && npm install'
   #       with:
@@ -22,7 +22,7 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: ljharb/actions/node/install@main
         name: 'nvm install lts/* && npm install'
         with:
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index a383a14f61..a6fb4e4cb5 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -38,7 +38,7 @@ jobs:
           # - utils
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: ljharb/actions/node/install@main
         name: 'nvm install ${{ matrix.node-version }} && npm install'
         env:
@@ -50,7 +50,7 @@ jobs:
           after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh && cd ${{ matrix.package }} && npm install
           skip-ls-check: true
       - run: cd ${{ matrix.package }} && npm run tests-only
-      - uses: codecov/codecov-action@v2
+      - uses: codecov/codecov-action@v3
 
   packages:
     name: 'packages: all tests'
diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml
index 323387ccab..b9e1712fc4 100644
--- a/.github/workflows/rebase.yml
+++ b/.github/workflows/rebase.yml
@@ -2,20 +2,8 @@ name: Automatic Rebase
 
 on: [pull_request_target]
 
-permissions:
-  contents: read
-
 jobs:
   _:
-    permissions:
-      contents: write  # for ljharb/rebase to push code to rebase
-      pull-requests: read  # for ljharb/rebase to get info about PR
-    name: "Automatic Rebase"
-
-    runs-on: ubuntu-latest
-
-    steps:
-    - uses: actions/checkout@v2
-    - uses: ljharb/rebase@master
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ljharb/actions/.github/workflows/rebase.yml@main
+    secrets:
+      token: ${{ secrets.GITHUB_TOKEN }}

From 1c738f8b3472cefa734eda0e86acf7608d287f2d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 20 Nov 2022 15:31:25 -0800
Subject: [PATCH 532/767] [Deps] update `array-includes`,
 `array.prototype.flat`, `is-core-module`, `object.values`

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index c48fade822..d68c25e310 100644
--- a/package.json
+++ b/package.json
@@ -102,17 +102,17 @@
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
   },
   "dependencies": {
-    "array-includes": "^3.1.5",
-    "array.prototype.flat": "^1.3.0",
+    "array-includes": "^3.1.6",
+    "array.prototype.flat": "^1.3.1",
     "debug": "^2.6.9",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
     "eslint-module-utils": "^2.7.4",
     "has": "^1.0.3",
-    "is-core-module": "^2.10.0",
+    "is-core-module": "^2.11.0",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
-    "object.values": "^1.1.5",
+    "object.values": "^1.1.6",
     "resolve": "^1.22.1",
     "tsconfig-paths": "^3.14.1"
   }

From afa2cc29e4d00e56ea820fd89cf9439d41a4e4c3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 24 Nov 2022 14:48:56 -0800
Subject: [PATCH 533/767] [resolvers/*] [deps] update `is-core-module`,
 `resolve`

---
 resolvers/node/package.json    | 2 +-
 resolvers/webpack/package.json | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 51a7d49cc8..54c1217e79 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -30,7 +30,7 @@
   "homepage": "https://github.com/import-js/eslint-plugin-import",
   "dependencies": {
     "debug": "^3.2.7",
-    "resolve": "^1.20.0"
+    "resolve": "^1.22.1"
   },
   "devDependencies": {
     "chai": "^3.5.0",
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 693950d23a..42d5e7470e 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -36,10 +36,10 @@
     "find-root": "^1.1.0",
     "has": "^1.0.3",
     "interpret": "^1.4.0",
-    "is-core-module": "^2.7.0",
+    "is-core-module": "^2.11.0",
     "is-regex": "^1.1.4",
     "lodash": "^4.17.21",
-    "resolve": "^1.20.0",
+    "resolve": "^1.22.1",
     "semver": "^5.7.1"
   },
   "peerDependencies": {

From 519d2567cd5d13f615e4af4a5f848fc1a02d04ad Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 24 Nov 2022 23:14:23 -0800
Subject: [PATCH 534/767] [Tests] `no-duplicates`: add passing test case from
 #2601

---
 tests/src/rules/no-duplicates.js | 39 ++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index cde41b3a07..14a9f20091 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -1,5 +1,6 @@
 import * as path from 'path';
 import { test as testUtil, getNonDefaultParsers, parsers } from '../utils';
+import jsxConfig from '../../../config/react';
 
 import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
@@ -412,6 +413,44 @@ import {x,y} from './foo'
       output: "import Bar, { Foo } from './foo';\nexport const value = {}",
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
+
+    test({
+      code: `
+        import {
+          DEFAULT_FILTER_KEYS,
+          BULK_DISABLED,
+        } from '../constants';
+        import React from 'react';
+        import {
+          BULK_ACTIONS_ENABLED
+        } from '../constants';
+        
+        const TestComponent = () => {
+          return <div>
+          </div>;
+        }
+        
+        export default TestComponent;
+      `,
+      output: `
+        import {
+          DEFAULT_FILTER_KEYS,
+          BULK_DISABLED,
+        
+          BULK_ACTIONS_ENABLED
+        } from '../constants';
+        import React from 'react';
+                
+        const TestComponent = () => {
+          return <div>
+          </div>;
+        }
+        
+        export default TestComponent;
+      `,
+      errors: ["'../constants' imported multiple times.", "'../constants' imported multiple times."],
+      ...jsxConfig,
+    }),
   ],
 });
 

From 280b736c0db0f2581b0e74250a8ee99618a00d28 Mon Sep 17 00:00:00 2001
From: Aziz Abdullaev <aziz.saidmuratov@duke.edu>
Date: Fri, 11 Nov 2022 00:34:36 -0500
Subject: [PATCH 535/767] [Tests] `namespace`: add passing test case to close
 #2572

---
 tests/files/jsx/bar/baz.jsx  | 16 ++++++++++++++++
 tests/files/jsx/bar/index.js |  2 ++
 tests/files/jsx/bar/qux.jsx  | 16 ++++++++++++++++
 tests/files/jsx/re-export.js |  1 +
 tests/src/rules/namespace.js | 29 +++++++++++++++++++++++++++++
 5 files changed, 64 insertions(+)
 create mode 100644 tests/files/jsx/bar/baz.jsx
 create mode 100644 tests/files/jsx/bar/index.js
 create mode 100644 tests/files/jsx/bar/qux.jsx
 create mode 100644 tests/files/jsx/re-export.js

diff --git a/tests/files/jsx/bar/baz.jsx b/tests/files/jsx/bar/baz.jsx
new file mode 100644
index 0000000000..ab0eb07e92
--- /dev/null
+++ b/tests/files/jsx/bar/baz.jsx
@@ -0,0 +1,16 @@
+
+export function Baz1() {
+  return (
+    <div>
+    </div>
+  );
+}
+
+// Fragment Syntax
+export function Baz2() {
+  return (
+    <div>
+      <span>Baz2</span>
+    </div>
+  );
+}
\ No newline at end of file
diff --git a/tests/files/jsx/bar/index.js b/tests/files/jsx/bar/index.js
new file mode 100644
index 0000000000..2d36b837ed
--- /dev/null
+++ b/tests/files/jsx/bar/index.js
@@ -0,0 +1,2 @@
+export * from "./baz.jsx";
+export { Qux1, Qux2 } from "./qux.jsx";
\ No newline at end of file
diff --git a/tests/files/jsx/bar/qux.jsx b/tests/files/jsx/bar/qux.jsx
new file mode 100644
index 0000000000..9325207d74
--- /dev/null
+++ b/tests/files/jsx/bar/qux.jsx
@@ -0,0 +1,16 @@
+
+export function Qux1() {
+  return (
+    <div>
+      <p>Qux1</p>
+    </div>
+  );
+}
+
+export function Qux2() {
+  return (
+    <div>
+      <p>Qux1</p>
+    </div>
+  );;
+}
\ No newline at end of file
diff --git a/tests/files/jsx/re-export.js b/tests/files/jsx/re-export.js
new file mode 100644
index 0000000000..70f8509aac
--- /dev/null
+++ b/tests/files/jsx/re-export.js
@@ -0,0 +1 @@
+export * from './named.jsx'
\ No newline at end of file
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 1465d21363..163ff163ea 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -29,6 +29,35 @@ const valid = [
       ecmaVersion: 2015,
     },
   }),
+  // import re-exported jsx files, where jsx file exports a string
+  test({
+    code: `
+      import * as foo from "./jsx/re-export.js";
+      console.log(foo.jsxFoo);
+    `,
+    settings: {
+      'import/extensions': ['.js', '.jsx'],
+    },
+  }),
+  // import re-exported jsx files, where jsx files export functions that return html tags
+  test({
+    code: `
+      import * as foo from "./jsx/bar/index.js";
+      console.log(foo.Baz1);
+      console.log(foo.Baz2);
+      console.log(foo.Qux1);
+      console.log(foo.Qux2);
+    `,
+    settings: {
+      'import/extensions': ['.js', '.jsx'],
+    },
+    parserOptions: {
+      ecmaFeatures: {
+        jsx: true,
+      },
+    },
+  }),
+
   test({ code: "import * as foo from './common';" }),
 
   // destructuring namespaces

From 4e83dcb47beb59386a34b8012e729cdc75ff0e5c Mon Sep 17 00:00:00 2001
From: Bryan Mishkin <698306+bmish@users.noreply.github.com>
Date: Mon, 28 Nov 2022 19:06:34 -0500
Subject: [PATCH 536/767] [Docs] update `eslint-doc-generator` to v1.0.0

---
 CHANGELOG.md | 2 ++
 package.json | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c9ee1593af..f87541e9c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -49,6 +49,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Tests] [`no-restricted-paths`]: fix one failing `import type` test case, submitted by [@golergka], thanks [@azyzz228]
 - [Docs] automate docs with eslint-doc-generator ([#2582], thanks [@bmish])
 - [readme] Increase clarity around typescript configuration ([#2588], thanks [@Nfinished])
+- [Docs] update `eslint-doc-generator` to v1.0.0 ([#2605], thanks [@bmish])
 
 ## [2.26.0] - 2022-04-05
 
@@ -1023,6 +1024,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2605]: https://github.com/import-js/eslint-plugin-import/pull/2605
 [#2598]: https://github.com/import-js/eslint-plugin-import/pull/2598
 [#2589]: https://github.com/import-js/eslint-plugin-import/pull/2589
 [#2588]: https://github.com/import-js/eslint-plugin-import/pull/2588
diff --git a/package.json b/package.json
index d68c25e310..c1044f1ea5 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,7 @@
     "prepublishOnly": "safe-publish-latest && npm run build",
     "prepublish": "not-in-publish || npm run prepublishOnly",
     "preupdate:eslint-docs": "npm run build",
-    "update:eslint-docs": "eslint-doc-generator --rule-doc-title-format prefix-name --rule-doc-section-options false --split-by meta.docs.category --ignore-config stage-0 --config-emoji recommended,☑️"
+    "update:eslint-docs": "eslint-doc-generator --rule-doc-title-format prefix-name --rule-doc-section-options false --rule-list-split meta.docs.category --ignore-config stage-0 --config-emoji recommended,☑️"
   },
   "repository": {
     "type": "git",
@@ -73,7 +73,7 @@
     "cross-env": "^4.0.0",
     "escope": "^3.6.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8",
-    "eslint-doc-generator": "^0.19.0",
+    "eslint-doc-generator": "^1.0.0",
     "eslint-import-resolver-node": "file:./resolvers/node",
     "eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",

From f4f305b865736308b0afe748a93967e943b94a85 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 28 Nov 2022 19:49:18 -0800
Subject: [PATCH 537/767] [resolvers/node] [Refactor] use `is-core-module`
 directly

---
 resolvers/README.md         | 11 ++++++-----
 resolvers/node/index.js     |  3 ++-
 resolvers/node/package.json |  1 +
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/resolvers/README.md b/resolvers/README.md
index 05ef4ef327..b664721b83 100644
--- a/resolvers/README.md
+++ b/resolvers/README.md
@@ -68,16 +68,17 @@ If the resolver cannot resolve `source` relative to `file`, it should just retur
 Here is most of the [Node resolver] at the time of this writing. It is just a wrapper around substack/Browserify's synchronous [`resolve`]:
 
 ```js
-var resolve = require('resolve')
+var resolve = require('resolve');
+var isCoreModule = require('is-core-module');
 
 exports.resolve = function (source, file, config) {
-  if (resolve.isCore(source)) return { found: true, path: null }
+  if (isCoreModule(source)) return { found: true, path: null };
   try {
-    return { found: true, path: resolve.sync(source, opts(file, config)) }
+    return { found: true, path: resolve.sync(source, opts(file, config)) };
   } catch (err) {
-    return { found: false }
+    return { found: false };
   }
-}
+};
 ```
 
 [Node resolver]: ./node/index.js
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index 899e552e96..ac478ef029 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -1,6 +1,7 @@
 'use strict';
 
 const resolve = require('resolve');
+const isCoreModule = require('is-core-module');
 const path = require('path');
 
 const log = require('debug')('eslint-plugin-import:resolver:node');
@@ -11,7 +12,7 @@ exports.resolve = function (source, file, config) {
   log('Resolving:', source, 'from:', file);
   let resolvedPath;
 
-  if (resolve.isCore(source)) {
+  if (isCoreModule(source)) {
     log('resolved to core');
     return { found: true, path: null };
   }
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 54c1217e79..771249ee58 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -30,6 +30,7 @@
   "homepage": "https://github.com/import-js/eslint-plugin-import",
   "dependencies": {
     "debug": "^3.2.7",
+    "is-core-module": "^2.11.0",
     "resolve": "^1.22.1"
   },
   "devDependencies": {

From 922819f448634ae81f7a1a59304dfc09066b612a Mon Sep 17 00:00:00 2001
From: Aziz Abdullaev <aziz.saidmuratov@duke.edu>
Date: Wed, 23 Nov 2022 20:25:24 -0500
Subject: [PATCH 538/767] [New] `prefer-default-export`: add "target" option

Fixes #2600.
---
 CHANGELOG.md                             |   2 +
 README.md                                |   2 +-
 docs/rules/prefer-default-export.md      | 128 ++++++++++++++-
 src/rules/prefer-default-export.js       |  29 +++-
 tests/src/rules/prefer-default-export.js | 189 ++++++++++++++++++++++-
 5 files changed, 337 insertions(+), 13 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f87541e9c0..66d4665372 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: new `alphabetize.orderImportKind` option to sort imports with same path based on their kind (`type`, `typeof`) ([#2544], thanks [@stropho])
 - [`consistent-type-specifier-style`]: add rule ([#2473], thanks [@bradzacher])
 - Add [`no-empty-named-blocks`] rule ([#2568], thanks [@guilhermelimak])
+- [`prefer-default-export`]: add "target" option ([#2602], thanks [@azyzz228])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -1025,6 +1026,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2605]: https://github.com/import-js/eslint-plugin-import/pull/2605
+[#2602]: https://github.com/import-js/eslint-plugin-import/pull/2602
 [#2598]: https://github.com/import-js/eslint-plugin-import/pull/2598
 [#2589]: https://github.com/import-js/eslint-plugin-import/pull/2589
 [#2588]: https://github.com/import-js/eslint-plugin-import/pull/2588
diff --git a/README.md b/README.md
index ed1e4f822f..640929c062 100644
--- a/README.md
+++ b/README.md
@@ -89,7 +89,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 | [no-namespace](docs/rules/no-namespace.md)                                       | Forbid namespace (a.k.a. "wildcard" `*`) imports.                          |    |       |    | 🔧 |    |    |
 | [no-unassigned-import](docs/rules/no-unassigned-import.md)                       | Forbid unassigned imports                                                  |    |       |    |    |    |    |
 | [order](docs/rules/order.md)                                                     | Enforce a convention in module import order.                               |    |       |    | 🔧 |    |    |
-| [prefer-default-export](docs/rules/prefer-default-export.md)                     | Prefer a default export if module exports a single name.                   |    |       |    |    |    |    |
+| [prefer-default-export](docs/rules/prefer-default-export.md)                     | Prefer a default export if module exports a single name or multiple names. |    |       |    |    |    |    |
 
 <!-- end auto-generated rules list -->
 
diff --git a/docs/rules/prefer-default-export.md b/docs/rules/prefer-default-export.md
index 38ec166e69..5d335f4c12 100644
--- a/docs/rules/prefer-default-export.md
+++ b/docs/rules/prefer-default-export.md
@@ -2,10 +2,44 @@
 
 <!-- end auto-generated rule header -->
 
-When there is only a single export from a module, prefer using default export over named export.
+In exporting files, this rule checks if there is default export or not.
 
 ## Rule Details
 
+##### rule schema:
+
+```javascript
+"import/prefer-default-export": [
+    ( "off" | "warn" | "error" ),
+	{ "target": "single" | "any" } // default is "single"
+]
+```
+
+### Config Options
+
+There are two options available: `single` and `any`. By default, if you do not specify the option, rule will assume it is `single`.
+
+#### single
+
+**Definition**: When there is only a single export from a module, prefer using default export over named export.
+
+How to setup config file for this rule:
+
+```javascript
+// you can manually specify it
+"rules": {
+    "import/prefer-default-export": [
+        ( "off" | "warn" | "error" ),
+        { "target": "single" }
+    ]
+}
+
+// config setup below will also work
+"rules": {
+    "import/prefer-default-export": "off" | "warn" | "error"
+}
+```
+
 The following patterns are considered warnings:
 
 ```javascript
@@ -58,3 +92,95 @@ export { foo as default }
 // Any batch export will disable this rule. The remote module is not inspected.
 export * from './other-module'
 ```
+
+#### any
+
+**Definition**: any exporting file must contain a default export.
+
+How to setup config file for this rule:
+
+```javascript
+// you have to manually specify it
+"rules": {
+    "import/prefer-default-export": [
+        ( "off" | "warn" | "error" ),
+        { "target": "any" }
+    ]
+}
+```
+
+
+The following patterns are *not* considered warnings:
+
+```javascript
+// good1.js
+
+//has default export
+export default function bar() {};
+```
+
+```javascript
+// good2.js
+
+// has default export
+let foo;
+export { foo as default }
+```
+
+```javascript
+// good3.js
+
+//contains multiple exports AND default export
+export const a = 5;
+export function bar(){};
+let foo;
+export { foo as default }
+```
+
+```javascript
+// good4.js
+
+// does not contain any exports => file is not checked by the rule
+import * as foo from './foo';
+```
+
+```javascript
+// export-star.js
+
+// Any batch export will disable this rule. The remote module is not inspected.
+export * from './other-module'
+```
+
+The following patterns are considered warnings:
+
+```javascript
+// bad1.js
+
+//has 2 named exports, but no default export
+export const foo = 'foo';
+export const bar = 'bar';
+```
+
+```javascript
+// bad2.js
+
+// does not have default export
+let foo, bar;
+export { foo, bar }
+```
+
+```javascript
+// bad3.js
+
+// does not have default export
+export { a, b } from "foo.js"
+```
+
+```javascript
+// bad4.js
+
+// does not have default export
+let item;
+export const foo = item;
+export { item };
+```
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index d1b134cfc1..32ef5004fa 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -2,15 +2,28 @@
 
 import docsUrl from '../docsUrl';
 
+const SINGLE_EXPORT_ERROR_MESSAGE = 'Prefer default export on a file with single export.';
+const ANY_EXPORT_ERROR_MESSAGE = 'Prefer default export to be present on every file that has export.';
+
 module.exports = {
   meta: {
     type: 'suggestion',
     docs: {
       category: 'Style guide',
-      description: 'Prefer a default export if module exports a single name.',
+      description: 'Prefer a default export if module exports a single name or multiple names.',
       url: docsUrl('prefer-default-export'),
     },
-    schema: [],
+    schema: [{
+      type: 'object',
+      properties:{
+        target: {
+          type: 'string',
+          enum: ['single', 'any'],
+          default: 'single',
+        },
+      },
+      additionalProperties: false,
+    }],
   },
 
   create(context) {
@@ -19,7 +32,8 @@ module.exports = {
     let hasStarExport = false;
     let hasTypeExport = false;
     let namedExportNode = null;
-
+    // get options. by default we look into files with single export
+    const { target = 'single' } =  context.options[0] || {};
     function captureDeclaration(identifierOrPattern) {
       if (identifierOrPattern && identifierOrPattern.type === 'ObjectPattern') {
         // recursively capture
@@ -88,8 +102,13 @@ module.exports = {
       },
 
       'Program:exit': function () {
-        if (specifierExportCount === 1 && !hasDefaultExport && !hasStarExport && !hasTypeExport) {
-          context.report(namedExportNode, 'Prefer default export.');
+        if (hasDefaultExport || hasStarExport || hasTypeExport) {
+          return;
+        }
+        if (target === 'single' && specifierExportCount === 1) {
+          context.report(namedExportNode, SINGLE_EXPORT_ERROR_MESSAGE);
+        } else if (target === 'any' && specifierExportCount > 0) {
+          context.report(namedExportNode, ANY_EXPORT_ERROR_MESSAGE);
         }
       },
     };
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index 6ecd2e3afd..ae7c16a40e 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -7,6 +7,10 @@ import { version as tsEslintVersion } from 'typescript-eslint-parser/package.jso
 const ruleTester = new RuleTester();
 const rule = require('../../../src/rules/prefer-default-export');
 
+const SINGLE_EXPORT_ERROR_MESSAGE = 'Prefer default export on a file with single export.';
+const ANY_EXPORT_ERROR_MESSAGE = 'Prefer default export to be present on every file that has export.';
+
+// test cases for default option { target: 'single' }
 ruleTester.run('prefer-default-export', rule, {
   valid: [].concat(
     test({
@@ -108,7 +112,7 @@ ruleTester.run('prefer-default-export', rule, {
         export function bar() {};`,
       errors: [{
         type: 'ExportNamedDeclaration',
-        message: 'Prefer default export.',
+        message: SINGLE_EXPORT_ERROR_MESSAGE,
       }],
     }),
     test({
@@ -116,7 +120,7 @@ ruleTester.run('prefer-default-export', rule, {
         export const foo = 'foo';`,
       errors: [{
         type: 'ExportNamedDeclaration',
-        message: 'Prefer default export.',
+        message: SINGLE_EXPORT_ERROR_MESSAGE,
       }],
     }),
     test({
@@ -125,7 +129,7 @@ ruleTester.run('prefer-default-export', rule, {
         export { foo };`,
       errors: [{
         type: 'ExportSpecifier',
-        message: 'Prefer default export.',
+        message: SINGLE_EXPORT_ERROR_MESSAGE,
       }],
     }),
     test({
@@ -133,7 +137,7 @@ ruleTester.run('prefer-default-export', rule, {
         export const { foo } = { foo: "bar" };`,
       errors: [{
         type: 'ExportNamedDeclaration',
-        message: 'Prefer default export.',
+        message: SINGLE_EXPORT_ERROR_MESSAGE,
       }],
     }),
     test({
@@ -141,7 +145,7 @@ ruleTester.run('prefer-default-export', rule, {
         export const { foo: { bar } } = { foo: { bar: "baz" } };`,
       errors: [{
         type: 'ExportNamedDeclaration',
-        message: 'Prefer default export.',
+        message: SINGLE_EXPORT_ERROR_MESSAGE,
       }],
     }),
     test({
@@ -149,12 +153,185 @@ ruleTester.run('prefer-default-export', rule, {
         export const [a] = ["foo"]`,
       errors: [{
         type: 'ExportNamedDeclaration',
-        message: 'Prefer default export.',
+        message: SINGLE_EXPORT_ERROR_MESSAGE,
       }],
     }),
   ],
 });
 
+// test cases for { target: 'any' }
+ruleTester.run('prefer-default-export', rule, {
+  // Any exporting file must contain default export
+  valid: [].concat(
+    test({
+      code: `
+          export default function bar() {};`,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    test({
+      code: `
+              export const foo = 'foo';
+              export const bar = 'bar';
+              export default 42;`,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    test({
+      code: `
+            export default a = 2;`,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    test({
+      code: `
+            export const a = 2;
+            export default function foo() {};`,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    test({
+      code: `
+          export const a = 5;
+          export function bar(){};
+          let foo;
+          export { foo as default }`,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    test({
+      code: `
+          export * from './foo';`,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    test({
+      code: `export Memory, { MemoryValue } from './Memory'`,
+      parser: parsers.BABEL_OLD,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    // no exports at all
+    test({
+      code: `
+            import * as foo from './foo';`,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    test({
+      code: `const a = 5;`,
+      options: [{
+        target: 'any',
+      }],
+    }),
+    // es2022: Arbitrary module namespae identifier names
+    testVersion('>= 8.7', () => ({
+      code: 'export const a = 4; let foo; export { foo as "default" };',
+      options: [{
+        target: 'any',
+      }],
+      parserOptions: { ecmaVersion: 2022 },
+    })),
+  ),
+  // { target: 'any' } invalid cases when any exporting file must contain default export but does not
+  invalid: [].concat(
+    test({
+      code: `
+        export const foo = 'foo';
+        export const bar = 'bar';`,
+      options: [{
+        target: 'any',
+      }],
+      errors: [{
+        message: ANY_EXPORT_ERROR_MESSAGE,
+      }],
+    }),
+    test({
+      code: `
+        export const foo = 'foo';
+        export function bar() {};`,
+      options: [{
+        target: 'any',
+      }],
+      errors: [{
+        message: ANY_EXPORT_ERROR_MESSAGE,
+      }],
+    }),
+    test({
+      code: `
+        let foo, bar;
+        export { foo, bar }`,
+      options: [{
+        target: 'any',
+      }],
+      errors: [{
+        message: ANY_EXPORT_ERROR_MESSAGE,
+      }],
+    }),
+    test({
+      code: `
+        let item;
+        export const foo = item;
+        export { item };`,
+      options: [{
+        target: 'any',
+      }],
+      errors: [{
+        message: ANY_EXPORT_ERROR_MESSAGE,
+      }],
+    }),
+    test({
+      code: 'export { a, b } from "foo.js"',
+      parser: parsers.BABEL_OLD,
+      options: [{
+        target: 'any',
+      }],
+      errors: [{
+        message: ANY_EXPORT_ERROR_MESSAGE,
+      }],
+    }),
+    test({
+      code: `
+        const foo = 'foo';
+        export { foo };`,
+      options: [{
+        target: 'any',
+      }],
+      errors: [{
+        message: ANY_EXPORT_ERROR_MESSAGE,
+      }],
+    }),
+    test({
+      code: `
+        export const { foo } = { foo: "bar" };`,
+      options: [{
+        target: 'any',
+      }],
+      errors: [{
+        message: ANY_EXPORT_ERROR_MESSAGE,
+      }],
+    }),
+    test({
+      code: `
+        export const { foo: { bar } } = { foo: { bar: "baz" } };`,
+      options: [{
+        target: 'any',
+      }],
+      errors: [{
+        message: ANY_EXPORT_ERROR_MESSAGE,
+      }],
+    }),
+  ),
+});
+
 context('TypeScript', function () {
   getNonDefaultParsers().forEach((parser) => {
     const parserConfig = {

From 5a37196b008b318f5ada9d911eab27fab3c9aedf Mon Sep 17 00:00:00 2001
From: Greg Price <gnprice@gmail.com>
Date: Wed, 30 Nov 2022 13:45:00 -0800
Subject: [PATCH 539/767] [Fix] `no-cycle`: Accept `import typeof`, like
 `import type`

Fixes #2607.
---
 CHANGELOG.md                      | 3 +++
 docs/rules/no-cycle.md            | 2 ++
 src/ExportMap.js                  | 9 +++++----
 tests/files/cycles/flow-typeof.js | 4 ++++
 tests/src/rules/no-cycle.js       | 4 ++++
 5 files changed, 18 insertions(+), 4 deletions(-)
 create mode 100644 tests/files/cycles/flow-typeof.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 66d4665372..58bfe0ab3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-unresolved`], [`extensions`]: ignore type only exports ([#2436], thanks [@Lukas-Kullmann])
 - `ExportMap`: add missing param to function ([#2589], thanks [@Fdawgs])
 - [`no-unused-modules`]: `checkPkgFieldObject` filters boolean fields from checks ([#2598], thanks [@mpint])
+- [`no-cycle`]: accept Flow `typeof` imports, just like `type` ([#2608], thanks [@gnprice])
 
 ### Changed
 - [Tests] [`named`]: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -1025,6 +1026,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2608]: https://github.com/import-js/eslint-plugin-import/pull/2608
 [#2605]: https://github.com/import-js/eslint-plugin-import/pull/2605
 [#2602]: https://github.com/import-js/eslint-plugin-import/pull/2602
 [#2598]: https://github.com/import-js/eslint-plugin-import/pull/2598
@@ -1626,6 +1628,7 @@ for info on changes for earlier releases.
 [@gavriguy]: https://github.com/gavriguy
 [@georeith]: https://github.com/georeith
 [@giodamelio]: https://github.com/giodamelio
+[@gnprice]: https://github.com/gnprice
 [@golergka]: https://github.com/golergka
 [@golopot]: https://github.com/golopot
 [@GoodForOneFare]: https://github.com/GoodForOneFare
diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md
index 1593842df8..6635ba73f0 100644
--- a/docs/rules/no-cycle.md
+++ b/docs/rules/no-cycle.md
@@ -22,6 +22,8 @@ import { b } from './dep-b.js' // reported: Dependency cycle detected.
 This rule does _not_ detect imports that resolve directly to the linted module;
 for that, see [`no-self-import`].
 
+This rule ignores type-only imports in Flow and TypeScript syntax (`import type` and `import typeof`), which have no runtime effect.
+
 
 ## Rule Details
 
diff --git a/src/ExportMap.js b/src/ExportMap.js
index a39434bc94..d95fdb7a75 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -502,8 +502,8 @@ ExportMap.parse = function (path, content, context) {
   }
 
   function captureDependencyWithSpecifiers(n) {
-    // import type { Foo } (TS and Flow)
-    const declarationIsType = n.importKind === 'type';
+    // import type { Foo } (TS and Flow); import typeof { Foo } (Flow)
+    const declarationIsType = n.importKind === 'type' || n.importKind === 'typeof';
     // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
     // shouldn't be considered to be just importing types
     let specifiersOnlyImportingTypes = n.specifiers.length > 0;
@@ -515,8 +515,9 @@ ExportMap.parse = function (path, content, context) {
         importedSpecifiers.add(specifier.type);
       }
 
-      // import { type Foo } (Flow)
-      specifiersOnlyImportingTypes = specifiersOnlyImportingTypes && specifier.importKind === 'type';
+      // import { type Foo } (Flow); import { typeof Foo } (Flow)
+      specifiersOnlyImportingTypes = specifiersOnlyImportingTypes
+        && (specifier.importKind === 'type' || specifier.importKind === 'typeof');
     });
     captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
   }
diff --git a/tests/files/cycles/flow-typeof.js b/tests/files/cycles/flow-typeof.js
new file mode 100644
index 0000000000..7c63f9ab76
--- /dev/null
+++ b/tests/files/cycles/flow-typeof.js
@@ -0,0 +1,4 @@
+// @flow
+import typeof Foo from './depth-zero';
+import { typeof Bar } from './depth-zero';
+import typeof { Bar } from './depth-zero';
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index de0083f563..155f257b71 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -111,6 +111,10 @@ ruleTester.run('no-cycle', rule, {
       code: 'import { bar } from "./flow-types-only-importing-multiple-types"',
       parser: parsers.BABEL_OLD,
     }),
+    test({
+      code: 'import { bar } from "./flow-typeof"',
+      parser: parsers.BABEL_OLD,
+    }),
   ),
 
   invalid: [].concat(

From b96b499aa25743dbec5a9293001fb0e567433f1d Mon Sep 17 00:00:00 2001
From: Adrian Pascu <mail@adipascu.ro>
Date: Tue, 13 Dec 2022 14:50:30 +0100
Subject: [PATCH 540/767] [New] `no-absolute-path`: add fixer

---
 CHANGELOG.md                        |  2 ++
 README.md                           |  2 +-
 docs/rules/no-absolute-path.md      |  2 ++
 src/rules/no-absolute-path.js       | 16 +++++++++++++++-
 tests/src/rules/no-absolute-path.js | 26 ++++++++++++++++++++++++++
 5 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 58bfe0ab3c..5907c521cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`consistent-type-specifier-style`]: add rule ([#2473], thanks [@bradzacher])
 - Add [`no-empty-named-blocks`] rule ([#2568], thanks [@guilhermelimak])
 - [`prefer-default-export`]: add "target" option ([#2602], thanks [@azyzz228])
+- [`no-absolute-path`]: add fixer ([#2613], thanks [@adipascu])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -1026,6 +1027,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2613]: https://github.com/import-js/eslint-plugin-import/pull/2613
 [#2608]: https://github.com/import-js/eslint-plugin-import/pull/2608
 [#2605]: https://github.com/import-js/eslint-plugin-import/pull/2605
 [#2602]: https://github.com/import-js/eslint-plugin-import/pull/2602
diff --git a/README.md b/README.md
index 640929c062..5c6f1a3211 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 | [default](docs/rules/default.md)                                       | Ensure a default export is present, given a default import.                          | ❗ ☑️ |    |    |    |    |    |
 | [named](docs/rules/named.md)                                           | Ensure named imports correspond to a named export in the remote file.                | ❗ ☑️ |    | ⌨️ |    |    |    |
 | [namespace](docs/rules/namespace.md)                                   | Ensure imported namespaces contain dereferenced properties as they are dereferenced. | ❗ ☑️ |    |    |    |    |    |
-| [no-absolute-path](docs/rules/no-absolute-path.md)                     | Forbid import of modules using absolute paths.                                       |      |    |    |    |    |    |
+| [no-absolute-path](docs/rules/no-absolute-path.md)                     | Forbid import of modules using absolute paths.                                       |      |    |    | 🔧 |    |    |
 | [no-cycle](docs/rules/no-cycle.md)                                     | Forbid a module from importing a module with a dependency path back to itself.       |      |    |    |    |    |    |
 | [no-dynamic-require](docs/rules/no-dynamic-require.md)                 | Forbid `require()` calls with expressions.                                           |      |    |    |    |    |    |
 | [no-internal-modules](docs/rules/no-internal-modules.md)               | Forbid importing the submodules of other modules.                                    |      |    |    |    |    |    |
diff --git a/docs/rules/no-absolute-path.md b/docs/rules/no-absolute-path.md
index 3d85b9eba7..a796f9d574 100644
--- a/docs/rules/no-absolute-path.md
+++ b/docs/rules/no-absolute-path.md
@@ -1,5 +1,7 @@
 # import/no-absolute-path
 
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
 <!-- end auto-generated rule header -->
 
 Node.js allows the import of modules using an absolute path such as `/home/xyz/file.js`. That is a bad practice as it ties the code using it to your computer, and therefore makes it unusable in packages distributed on `npm` for instance.
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index 171419d844..19dae6b6fb 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -1,3 +1,4 @@
+import path from 'path';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import { isAbsolute } from '../core/importType';
 import docsUrl from '../docsUrl';
@@ -10,13 +11,26 @@ module.exports = {
       description: 'Forbid import of modules using absolute paths.',
       url: docsUrl('no-absolute-path'),
     },
+    fixable: 'code',
     schema: [ makeOptionsSchema() ],
   },
 
   create(context) {
     function reportIfAbsolute(source) {
       if (isAbsolute(source.value)) {
-        context.report(source, 'Do not import modules using an absolute path');
+        context.report({
+          node: source,
+          message: 'Do not import modules using an absolute path',
+          fix: fixer => {
+            const resolvedContext = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+            // node.js and web imports work with posix style paths ("/")
+            let relativePath = path.posix.relative(path.dirname(resolvedContext), source.value);
+            if (!relativePath.startsWith('.')) {
+              relativePath = './' + relativePath;
+            }
+            return fixer.replaceText(source, JSON.stringify(relativePath));
+          },
+        });
       }
     }
 
diff --git a/tests/src/rules/no-absolute-path.js b/tests/src/rules/no-absolute-path.js
index 63fb8c0b6b..bfa08465c0 100644
--- a/tests/src/rules/no-absolute-path.js
+++ b/tests/src/rules/no-absolute-path.js
@@ -53,48 +53,74 @@ ruleTester.run('no-absolute-path', rule, {
   invalid: [
     test({
       code: 'import f from "/foo"',
+      filename: '/foo/bar/index.js',
       errors: [error],
+      output: 'import f from ".."',
+    }),
+    test({
+      code: 'import f from "/foo/bar/baz.js"',
+      filename: '/foo/bar/index.js',
+      errors: [error],
+      output: 'import f from "./baz.js"',
     }),
     test({
       code: 'import f from "/foo/path"',
+      filename: '/foo/bar/index.js',
       errors: [error],
+      output: 'import f from "../path"',
     }),
     test({
       code: 'import f from "/some/path"',
+      filename: '/foo/bar/index.js',
       errors: [error],
+      output: 'import f from "../../some/path"',
     }),
     test({
       code: 'import f from "/some/path"',
+      filename: '/foo/bar/index.js',
       options: [{ amd: true }],
       errors: [error],
+      output: 'import f from "../../some/path"',
     }),
     test({
       code: 'var f = require("/foo")',
+      filename: '/foo/bar/index.js',
       errors: [error],
+      output: 'var f = require("..")',
     }),
     test({
       code: 'var f = require("/foo/path")',
+      filename: '/foo/bar/index.js',
       errors: [error],
+      output: 'var f = require("../path")',
     }),
     test({
       code: 'var f = require("/some/path")',
+      filename: '/foo/bar/index.js',
       errors: [error],
+      output: 'var f = require("../../some/path")',
     }),
     test({
       code: 'var f = require("/some/path")',
+      filename: '/foo/bar/index.js',
       options: [{ amd: true }],
       errors: [error],
+      output: 'var f = require("../../some/path")',
     }),
     // validate amd
     test({
       code: 'require(["/some/path"], function (f) { /* ... */ })',
+      filename: '/foo/bar/index.js',
       options: [{ amd: true }],
       errors: [error],
+      output: 'require(["../../some/path"], function (f) { /* ... */ })',
     }),
     test({
       code: 'define(["/some/path"], function (f) { /* ... */ })',
+      filename: '/foo/bar/index.js',
       options: [{ amd: true }],
       errors: [error],
+      output: 'define(["../../some/path"], function (f) { /* ... */ })',
     }),
   ],
 });

From 56b3ea40e727ee4eb863e9e060d2c14920978ca0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 22 Dec 2022 09:47:59 -0800
Subject: [PATCH 541/767] [Perf] `no-cycle`, `no-internal-modules`,
 `no-restricted-paths`: use `anyOf` instead of `oneOf`

See https://github.com/eslint/eslint/issues/16691
---
 CHANGELOG.md                     | 1 +
 src/rules/no-cycle.js            | 2 +-
 src/rules/no-internal-modules.js | 2 +-
 src/rules/no-restricted-paths.js | 4 ++--
 4 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5907c521cc..e35390d3f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,6 +53,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] automate docs with eslint-doc-generator ([#2582], thanks [@bmish])
 - [readme] Increase clarity around typescript configuration ([#2588], thanks [@Nfinished])
 - [Docs] update `eslint-doc-generator` to v1.0.0 ([#2605], thanks [@bmish])
+- [Perf] `no-cycle`, `no-internal-modules`, `no-restricted-paths`: use `anyOf` instead of `oneOf` (thanks [@ljharb], [@remcohaszing])
 
 ## [2.26.0] - 2022-04-05
 
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 63765c863c..e12a81cea6 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -21,7 +21,7 @@ module.exports = {
     },
     schema: [makeOptionsSchema({
       maxDepth: {
-        oneOf: [
+        anyOf: [
           {
             description: 'maximum dependency depth to traverse',
             type: 'integer',
diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index 9d44f5859a..2416c1ce3f 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -16,7 +16,7 @@ module.exports = {
 
     schema: [
       {
-        oneOf: [
+        anyOf: [
           {
             type: 'object',
             properties: {
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index b8a461fa2d..2293119592 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -32,7 +32,7 @@ module.exports = {
               type: 'object',
               properties: {
                 target: {
-                  oneOf: [
+                  anyOf: [
                     { type: 'string' },
                     {
                       type: 'array',
@@ -43,7 +43,7 @@ module.exports = {
                   ],
                 },
                 from: {
-                  oneOf: [
+                  anyOf: [
                     { type: 'string' },
                     {
                       type: 'array',

From de895ac540923a592842b467baf21044cd780c34 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 22 Dec 2022 09:52:08 -0800
Subject: [PATCH 542/767] [meta] link rule names in changelog

---
 CHANGELOG.md | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e35390d3f0..b247632c2f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,12 +53,12 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] automate docs with eslint-doc-generator ([#2582], thanks [@bmish])
 - [readme] Increase clarity around typescript configuration ([#2588], thanks [@Nfinished])
 - [Docs] update `eslint-doc-generator` to v1.0.0 ([#2605], thanks [@bmish])
-- [Perf] `no-cycle`, `no-internal-modules`, `no-restricted-paths`: use `anyOf` instead of `oneOf` (thanks [@ljharb], [@remcohaszing])
+- [Perf] [`no-cycle`], [`no-internal-modules`], [`no-restricted-paths`]: use `anyOf` instead of `oneOf` (thanks [@ljharb], [@remcohaszing])
 
 ## [2.26.0] - 2022-04-05
 
 ### Added
-- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [`no-named-default`], [`no-default-export`], [`prefer-default-export`], [`no-named-export`], [`export`], [`named`], [`namespace`], [`no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
 - [`no-relative-packages`]: add fixer ([#2381], thanks [@forivall])
 
@@ -69,13 +69,13 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-unused-modules`]: avoid a crash when processing re-exports ([#2388], thanks [@ljharb])
 
 ### Changed
-- [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
-- [Tests] `default`, `no-anonymous-default-export`, `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
+- [Tests] [`no-nodejs-modules`]: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
+- [Tests] [`default`], [`no-anonymous-default-export`], [`no-mutable-exports`], [`no-named-as-default-member`], [`no-named-as-default`]: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
 - [Docs] [`no-unresolved`]: Fix RegExp escaping in readme ([#2332], thanks [@stephtr])
-- [Refactor] `namespace`: try to improve performance ([#2340], thanks [@ljharb])
+- [Refactor] [`namespace`]: try to improve performance ([#2340], thanks [@ljharb])
 - [Docs] make rule doc titles consistent ([#2393], thanks [@TheJaredWilcurt])
-- [Docs] `order`: TS code examples should use TS code blocks ([#2411], thanks [@MM25Zamanian])
-- [Docs] `no-unresolved`: fix link ([#2417], thanks [@kylemh])
+- [Docs] [`order`]: TS code examples should use TS code blocks ([#2411], thanks [@MM25Zamanian])
+- [Docs] [`no-unresolved`]: fix link ([#2417], thanks [@kylemh])
 
 ## [2.25.4] - 2022-01-02
 
@@ -186,7 +186,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: restore default behavior unless `type` is in groups ([#2087], thanks [@grit96])
 
 ### Changed
-- [Docs] Add `no-relative-packages` to list of to the list of rules ([#2075], thanks [@arvigeus])
+- [Docs] Add [`no-relative-packages`] to list of to the list of rules ([#2075], thanks [@arvigeus])
 
 ## [2.23.2] - 2021-05-15
 
@@ -231,9 +231,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
 - [Docs] [`no-named-as-default`]: add semicolon ([#1897], thanks [@bicstone])
-- [Docs] `no-extraneous-dependencies`: correct peerDependencies option default to `true` ([#1993], thanks [@dwardu])
-- [Docs] `order`: Document options required to match ordering example ([#1992], thanks [@silviogutierrez])
-- [Tests] `no-unresolved`: add tests for `import()` ([#2012], thanks [@davidbonnet])
+- [Docs] [`no-extraneous-dependencies`]: correct peerDependencies option default to `true` ([#1993], thanks [@dwardu])
+- [Docs] [`order`]: Document options required to match ordering example ([#1992], thanks [@silviogutierrez])
+- [Tests] [`no-unresolved`]: add tests for `import()` ([#2012], thanks [@davidbonnet])
 - [Docs] Add import/recommended ruleset to README ([#2034], thanks [@edemaine])
 
 ## [2.22.1] - 2020-09-27
@@ -303,12 +303,12 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - TypeScript: [`export`]: avoid a crash with `export =` ([#1801], thanks [@ljharb])
 
 ### Changed
-- [Refactor] `no-extraneous-dependencies`: use moduleVisitor ([#1735], thanks [@adamborowski])
+- [Refactor] [`no-extraneous-dependencies`]: use moduleVisitor ([#1735], thanks [@adamborowski])
 - TypeScript config: Disable [`named`][] ([#1726], thanks [@astorije])
 - [readme] Remove duplicate [`no-unused-modules`] from docs ([#1690], thanks [@arvigeus])
-- [Docs] `order`: fix bad inline config ([#1788], thanks [@nickofthyme])
+- [Docs] [`order`]: fix bad inline config ([#1788], thanks [@nickofthyme])
 - [Tests] Add fix for Windows Subsystem for Linux ([#1786], thanks [@manuth])
-- [Docs] `no-unused-rules`: Fix docs for unused exports ([#1776], thanks [@barbogast])
+- [Docs] [`no-unused-rules`]: Fix docs for unused exports ([#1776], thanks [@barbogast])
 - [eslint] bump minimum v7 version to v7.2.0
 
 ## [2.20.2] - 2020-03-28
@@ -319,7 +319,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-duplicates`]: fix fixer on cases with default import ([#1666], thanks [@golopot])
 - [`no-unused-modules`]: Handle `export { default } from` syntax ([#1631], thanks [@richardxia])
 - [`first`]: Add a way to disable `absolute-first` explicitly ([#1664], thanks [@TheCrueltySage])
-- [Docs] `no-webpack-loader-syntax`: Updates webpack URLs ([#1751], thanks [@MikeyBeLike])
+- [Docs] [`no-webpack-loader-syntax`]: Updates webpack URLs ([#1751], thanks [@MikeyBeLike])
 
 ## [2.20.1] - 2020-02-01
 
@@ -337,7 +337,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
 - [meta] fix "files" field to include/exclude the proper files ([#1635], thanks [@ljharb])
-- [Tests] `order`: Add TS import type tests ([#1736], thanks [@kmui2])
+- [Tests] [`order`]: Add TS import type tests ([#1736], thanks [@kmui2])
 
 ## [2.20.0] - 2020-01-10
 
@@ -436,7 +436,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - Improve support for TypeScript declare structures ([#1356], thanks [@christophercurrie])
 
 ### Docs
-- add missing `no-unused-modules` in README ([#1358], thanks [@golopot])
+- add missing [`no-unused-modules`] in README ([#1358], thanks [@golopot])
 - [`no-unused-modules`]: Indicates usage, plugin defaults to no-op, and add description to main README.md ([#1352], thanks [@johndevedu])
 - Document `env` option for `eslint-import-resolver-webpack` ([#1363], thanks [@kgregory])
 

From 6304ddc70fc187e248aa65c69bc8983c5051ecd3 Mon Sep 17 00:00:00 2001
From: Scott Newcomer <snewcomer24@gmail.com>
Date: Fri, 10 Jun 2022 07:08:47 -0500
Subject: [PATCH 543/767] [New] `no-duplicates`: support inline type import
 with `inlineTypeImport` option

---
 CHANGELOG.md                     |   3 +
 docs/rules/no-duplicates.md      |  27 +++
 src/rules/no-duplicates.js       |  25 ++-
 tests/src/rules/no-duplicates.js | 307 ++++++++++++++++++++++---------
 4 files changed, 267 insertions(+), 95 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b247632c2f..3e8e889241 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - Add [`no-empty-named-blocks`] rule ([#2568], thanks [@guilhermelimak])
 - [`prefer-default-export`]: add "target" option ([#2602], thanks [@azyzz228])
 - [`no-absolute-path`]: add fixer ([#2613], thanks [@adipascu])
+- [`no-duplicates`]: support inline type import with `inlineTypeImport` option ([#2475], thanks [@snewcomer])
 
 ### Fixed
 - [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
@@ -1045,6 +1046,7 @@ for info on changes for earlier releases.
 [#2506]: https://github.com/import-js/eslint-plugin-import/pull/2506
 [#2503]: https://github.com/import-js/eslint-plugin-import/pull/2503
 [#2490]: https://github.com/import-js/eslint-plugin-import/pull/2490
+[#2475]: https://github.com/import-js/eslint-plugin-import/pull/2475
 [#2473]: https://github.com/import-js/eslint-plugin-import/pull/2473
 [#2466]: https://github.com/import-js/eslint-plugin-import/pull/2466
 [#2459]: https://github.com/import-js/eslint-plugin-import/pull/2459
@@ -1760,6 +1762,7 @@ for info on changes for earlier releases.
 [@singles]: https://github.com/singles
 [@skozin]: https://github.com/skozin
 [@skyrpex]: https://github.com/skyrpex
+[@snewcomer]: https://github.com/snewcomer
 [@sompylasar]: https://github.com/sompylasar
 [@soryy708]: https://github.com/soryy708
 [@sosukesuzuki]: https://github.com/sosukesuzuki
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index 3ca8d1af26..553fbbcc34 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -67,6 +67,33 @@ import SomeDefaultClass from './mod?minify'
 import * from './mod.js?minify'
 ```
 
+### Inline Type imports
+
+TypeScript 4.5 introduced a new [feature](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5/#type-on-import-names) that allows mixing of named value and type imports. In order to support fixing to an inline type import when duplicate imports are detected, `prefer-inline` can be set to true.
+
+Config:
+
+```json
+"import/no-duplicates": ["error", {"prefer-inline": true}]
+```
+
+<!--tabs-->
+
+❌ Invalid `["error", "prefer-inline"]`
+
+```js
+import { AValue, type AType } from './mama-mia'
+import type { BType } from './mama-mia'
+```
+
+✅ Valid with `["error", "prefer-inline"]`
+
+```js
+import { AValue, type AType, type BType } from './mama-mia'
+```
+
+<!--tabs-->
+
 ## When Not To Use It
 
 If the core ESLint version is good enough (i.e. you're _not_ using Flow and you _are_ using [`import/extensions`](./extensions.md)), keep it and don't use this.
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 4aec2d1e77..b896f442ae 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -1,5 +1,7 @@
 import resolve from 'eslint-module-utils/resolve';
 import docsUrl from '../docsUrl';
+import semver from 'semver';
+import typescriptPkg from 'typescript/package.json';
 
 function checkImports(imported, context) {
   for (const [module, nodes] of imported.entries()) {
@@ -7,7 +9,7 @@ function checkImports(imported, context) {
       const message = `'${module}' imported multiple times.`;
       const [first, ...rest] = nodes;
       const sourceCode = context.getSourceCode();
-      const fix = getFix(first, rest, sourceCode);
+      const fix = getFix(first, rest, sourceCode, context);
 
       context.report({
         node: first.source,
@@ -25,7 +27,7 @@ function checkImports(imported, context) {
   }
 }
 
-function getFix(first, rest, sourceCode) {
+function getFix(first, rest, sourceCode, context) {
   // Sorry ESLint <= 3 users, no autofix for you. Autofixing duplicate imports
   // requires multiple `fixer.whatever()` calls in the `fix`: We both need to
   // update the first one, and remove the rest. Support for multiple
@@ -108,10 +110,19 @@ function getFix(first, rest, sourceCode) {
 
     const [specifiersText] = specifiers.reduce(
       ([result, needsComma], specifier) => {
+        const isTypeSpecifier = specifier.importNode.importKind === 'type';
+
+        const preferInline = context.options[0] && context.options[0]['prefer-inline'];
+        // a user might set prefer-inline but not have a supporting TypeScript version.  Flow does not support inline types so this should fail in that case as well.
+        if (preferInline && !semver.satisfies(typescriptPkg.version, '>= 4.5')) {
+          throw new Error('Your version of TypeScript does not support inline type imports.');
+        }
+
+        const insertText = `${preferInline && isTypeSpecifier ? 'type ' : ''}${specifier.text}`;
         return [
           needsComma && !specifier.isEmpty
-            ? `${result},${specifier.text}`
-            : `${result}${specifier.text}`,
+            ? `${result},${insertText}`
+            : `${result}${insertText}`,
           specifier.isEmpty ? needsComma : true,
         ];
       },
@@ -257,6 +268,9 @@ module.exports = {
           considerQueryString: {
             type: 'boolean',
           },
+          'prefer-inline': {
+            type: 'boolean',
+          },
         },
         additionalProperties: false,
       },
@@ -291,6 +305,9 @@ module.exports = {
       if (n.importKind === 'type') {
         return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? map.defaultTypesImported : map.namedTypesImported;
       }
+      if (n.specifiers.some((spec) => spec.importKind === 'type')) {
+        return map.namedTypesImported;
+      }
 
       return hasNamespace(n) ? map.nsImported : map.imported;
     }
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 14a9f20091..f8a27a743b 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -1,5 +1,5 @@
 import * as path from 'path';
-import { test as testUtil, getNonDefaultParsers, parsers } from '../utils';
+import { test as testUtil, getNonDefaultParsers, parsers, tsVersionSatisfies, typescriptEslintParserSatisfies } from '../utils';
 import jsxConfig from '../../../config/react';
 
 import { RuleTester } from 'eslint';
@@ -467,99 +467,224 @@ context('TypeScript', function () {
         },
       };
 
-      ruleTester.run('no-duplicates', rule, {
-        valid: [
+      const valid = [
         // #1667: ignore duplicate if is a typescript type import
-          test({
-            code: "import type { x } from './foo'; import y from './foo'",
-            ...parserConfig,
-          }),
-          test({
-            code: "import type x from './foo'; import type y from './bar'",
-            ...parserConfig,
-          }),
-          test({
-            code: "import type {x} from './foo'; import type {y} from './bar'",
-            ...parserConfig,
-          }),
-          test({
-            code: "import type x from './foo'; import type {y} from './foo'",
-            ...parserConfig,
-          }),
-          test({
-            code: `
-              import type {} from './module';
-              import {} from './module2';
-            `,
-            ...parserConfig,
-          }),
-          test({
-            code: `
+        test({
+          code: "import type { x } from './foo'; import y from './foo'",
+          ...parserConfig,
+        }),
+        test({
+          code: "import type x from './foo'; import type y from './bar'",
+          ...parserConfig,
+        }),
+        test({
+          code: "import type {x} from './foo'; import type {y} from './bar'",
+          ...parserConfig,
+        }),
+        test({
+          code: "import type x from './foo'; import type {y} from './foo'",
+          ...parserConfig,
+        }),
+        test({
+          code: `
+            import type {} from './module';
+            import {} from './module2';
+          `,
+          ...parserConfig,
+        }),
+        test({
+          code: `
+            import type { Identifier } from 'module';
+
+            declare module 'module2' {
+              import type { Identifier } from 'module';
+            }
+
+            declare module 'module3' {
               import type { Identifier } from 'module';
+            }
+          `,
+          ...parserConfig,
+        }),
+      ].concat(!tsVersionSatisfies('>= 4.5') || !typescriptEslintParserSatisfies('>= 5.7.0') ? [] : [
+        // #2470: ignore duplicate if is a typescript inline type import
+        test({
+          code: "import { type x } from './foo'; import y from './foo'",
+          ...parserConfig,
+        }),
+        test({
+          code: "import { type x } from './foo'; import { y } from './foo'",
+          ...parserConfig,
+        }),
+        test({
+          code: "import { type x } from './foo'; import type y from 'foo'",
+          ...parserConfig,
+        }),
+      ]);
+
+      const invalid = [
+        test({
+          code: "import type x from './foo'; import type y from './foo'",
+          output: "import type x from './foo'; import type y from './foo'",
+          ...parserConfig,
+          errors: [
+            {
+              line: 1,
+              column: 20,
+              message: "'./foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 48,
+              message: "'./foo' imported multiple times.",
+            },
+          ],
+        }),
+        test({
+          code: "import type x from './foo'; import type x from './foo'",
+          output: "import type x from './foo'; ",
+          ...parserConfig,
+          errors: [
+            {
+              line: 1,
+              column: 20,
+              message: "'./foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 48,
+              message: "'./foo' imported multiple times.",
+            },
+          ],
+        }),
+        test({
+          code: "import type {x} from './foo'; import type {y} from './foo'",
+          ...parserConfig,
+          output: `import type {x,y} from './foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 22,
+              message: "'./foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 52,
+              message: "'./foo' imported multiple times.",
+            },
+          ],
+        }),
+      ].concat(!tsVersionSatisfies('>= 4.5') || !typescriptEslintParserSatisfies('>= 5.7.0') ? [] : [
+        test({
+          code: "import {type x} from './foo'; import type {y} from './foo'",
+          ...parserConfig,
+          options: [{ 'prefer-inline': false }],
+          output: `import {type x,y} from './foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 22,
+              message: "'./foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 52,
+              message: "'./foo' imported multiple times.",
+            },
+          ],
+        }),
+        test({
+          code: "import {type x} from 'foo'; import type {y} from 'foo'",
+          ...parserConfig,
+          options: [{ 'prefer-inline': true }],
+          output: `import {type x,type y} from 'foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 22,
+              message: "'foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 50,
+              message: "'foo' imported multiple times.",
+            },
+          ],
+        }),
+        test({
+          code: "import {type x} from 'foo'; import type {y} from 'foo'",
+          ...parserConfig,
+          output: `import {type x,y} from 'foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 22,
+              message: "'foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 50,
+              message: "'foo' imported multiple times.",
+            },
+          ],
+        }),
+        test({
+          code: "import {type x} from './foo'; import {type y} from './foo'",
+          ...parserConfig,
+          options: [{ 'prefer-inline': true }],
+          output: `import {type x,type y} from './foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 22,
+              message: "'./foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 52,
+              message: "'./foo' imported multiple times.",
+            },
+          ],
+        }),
+        test({
+          code: "import {type x} from './foo'; import {type y} from './foo'",
+          ...parserConfig,
+          output: `import {type x,type y} from './foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 22,
+              message: "'./foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 52,
+              message: "'./foo' imported multiple times.",
+            },
+          ],
+        }),
+        test({
+          code: "import {AValue, type x, BValue} from './foo'; import {type y} from './foo'",
+          ...parserConfig,
+          output: `import {AValue, type x, BValue,type y} from './foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 38,
+              message: "'./foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 68,
+              message: "'./foo' imported multiple times.",
+            },
+          ],
+        }),
+      ]);
 
-              declare module 'module2' {
-                import type { Identifier } from 'module';
-              }
-
-              declare module 'module3' {
-                import type { Identifier } from 'module';
-              }
-            `,
-            ...parserConfig,
-          }),
-        ],
-        invalid: [
-          test({
-            code: "import type x from './foo'; import type y from './foo'",
-            ...parserConfig,
-            errors: [
-              {
-                line: 1,
-                column: 20,
-                message: "'./foo' imported multiple times.",
-              },
-              {
-                line: 1,
-                column: 48,
-                message: "'./foo' imported multiple times.",
-              },
-            ],
-          }),
-          test({
-            code: "import type x from './foo'; import type x from './foo'",
-            output: "import type x from './foo'; ",
-            ...parserConfig,
-            errors: [
-              {
-                line: 1,
-                column: 20,
-                message: "'./foo' imported multiple times.",
-              },
-              {
-                line: 1,
-                column: 48,
-                message: "'./foo' imported multiple times.",
-              },
-            ],
-          }),
-          test({
-            code: "import type {x} from './foo'; import type {y} from './foo'",
-            ...parserConfig,
-            output: `import type {x,y} from './foo'; `,
-            errors: [
-              {
-                line: 1,
-                column: 22,
-                message: "'./foo' imported multiple times.",
-              },
-              {
-                line: 1,
-                column: 52,
-                message: "'./foo' imported multiple times.",
-              },
-            ],
-          }),
-        ],
+      ruleTester.run('no-duplicates', rule, {
+        valid,
+        invalid,
       });
     });
 });

From 404b5cef76ee6f5f13b678a41349ca923eb97b57 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 10 Jan 2023 16:21:00 -0800
Subject: [PATCH 544/767] [Deps] update `debug` to v3

Closes #2657. Closes #2658.
---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index c1044f1ea5..ec64bb18df 100644
--- a/package.json
+++ b/package.json
@@ -104,7 +104,7 @@
   "dependencies": {
     "array-includes": "^3.1.6",
     "array.prototype.flat": "^1.3.1",
-    "debug": "^2.6.9",
+    "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.6",
     "eslint-module-utils": "^2.7.4",

From c2f003a801f454abe0ff58f3bc5ea0b5360c036a Mon Sep 17 00:00:00 2001
From: Jonathan Haines <jonno.haines@gmail.com>
Date: Tue, 30 Nov 2021 20:50:08 +1100
Subject: [PATCH 545/767] [Fix] `no-import-module-exports`: avoid a false
 positive for import variables

---
 CHANGELOG.md                                | 3 +++
 src/rules/no-import-module-exports.js       | 9 ++++++++-
 tests/src/rules/no-import-module-exports.js | 8 +++++++-
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e8e889241..83b44e64a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - `ExportMap`: add missing param to function ([#2589], thanks [@Fdawgs])
 - [`no-unused-modules`]: `checkPkgFieldObject` filters boolean fields from checks ([#2598], thanks [@mpint])
 - [`no-cycle`]: accept Flow `typeof` imports, just like `type` ([#2608], thanks [@gnprice])
+- [`no-import-module-exports`]: avoid a false positive for import variables ([#2315], thanks [@BarryThePenguin])
 
 ### Changed
 - [Tests] [`named`]: Run all TypeScript test ([#2427], thanks [@ProdigySim])
@@ -1074,6 +1075,7 @@ for info on changes for earlier releases.
 [#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
 [#2334]: https://github.com/import-js/eslint-plugin-import/pull/2334
 [#2330]: https://github.com/import-js/eslint-plugin-import/pull/2330
+[#2315]: https://github.com/import-js/eslint-plugin-import/pull/2315
 [#2305]: https://github.com/import-js/eslint-plugin-import/pull/2305
 [#2299]: https://github.com/import-js/eslint-plugin-import/pull/2299
 [#2297]: https://github.com/import-js/eslint-plugin-import/pull/2297
@@ -1578,6 +1580,7 @@ for info on changes for earlier releases.
 [@atos1990]: https://github.com/atos1990
 [@azyzz228]: https://github.com/azyzz228
 [@barbogast]: https://github.com/barbogast
+[@BarryThePenguin]: https://github.com/BarryThePenguin
 [@be5invis]: https://github.com/be5invis
 [@beatrizrezener]: https://github.com/beatrizrezener
 [@benmosher]: https://github.com/benmosher
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index d40bae88ce..5a91acd07d 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -19,6 +19,11 @@ function findScope(context, identifier) {
   return scopeManager && scopeManager.scopes.slice().reverse().find((scope) => scope.variables.some(variable => variable.identifiers.some((node) => node.name === identifier)));
 }
 
+function findDefinition(objectScope, identifier) {
+  const variable = objectScope.variables.find(variable => variable.name === identifier);
+  return variable.defs.find(def => def.name.name === identifier);
+}
+
 module.exports = {
   meta: {
     type: 'problem',
@@ -50,10 +55,12 @@ module.exports = {
       const isIdentifier = node.object.type === 'Identifier';
       const hasKeywords = (/^(module|exports)$/).test(node.object.name);
       const objectScope = hasKeywords && findScope(context, node.object.name);
+      const variableDefinition = objectScope && findDefinition(objectScope, node.object.name);
+      const isImportBinding = variableDefinition && variableDefinition.type === 'ImportBinding';
       const hasCJSExportReference = hasKeywords && (!objectScope || objectScope.type === 'module');
       const isException = !!options.exceptions && options.exceptions.some(glob => minimatch(fileName, glob));
 
-      if (isIdentifier && hasCJSExportReference && !isEntryPoint && !isException) {
+      if (isIdentifier && hasCJSExportReference && !isEntryPoint && !isException && !isImportBinding) {
         importDeclarations.forEach(importDeclaration => {
           context.report({
             node: importDeclaration,
diff --git a/tests/src/rules/no-import-module-exports.js b/tests/src/rules/no-import-module-exports.js
index a40eb7e276..81faceba98 100644
--- a/tests/src/rules/no-import-module-exports.js
+++ b/tests/src/rules/no-import-module-exports.js
@@ -1,7 +1,7 @@
 import path from 'path';
 import { RuleTester } from 'eslint';
 
-import { test, testVersion } from '../utils';
+import { eslintVersionSatisfies, test, testVersion } from '../utils';
 
 const ruleTester = new RuleTester({
   parserOptions: { ecmaVersion: 6, sourceType: 'module' },
@@ -40,6 +40,12 @@ ruleTester.run('no-import-module-exports', rule, {
         exports.foo = bar
       `,
     }),
+    eslintVersionSatisfies('>= 4') ? test({
+      code: `
+        import { module } from 'qunit'
+        module.skip('A test', function () {})
+      `,
+    }) : [],
     test({
       code: `
         import foo from 'path';

From 9288cf77d88b836493e52a6614865b2832a1bc01 Mon Sep 17 00:00:00 2001
From: Aziz Abdullaev <aziz.saidmuratov@duke.edu>
Date: Thu, 20 Oct 2022 00:51:59 -0400
Subject: [PATCH 546/767] [meta] CONTRIBUTING.md: add resources for newcomers

---
 CONTRIBUTING.md | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index eba44f51ac..2a79e7139e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,6 +18,15 @@ When opening an [issue](#issues):
 
 Remember, you don't need to do it all yourself; any of these are helpful! 😎
 
+## How to get started
+
+If you are new to `eslint`, below are a few resources that will help you to familiarize yourself with the project.
+
+- Watch [this presentation](https://www.youtube.com/watch?v=2W9tUnALrLg) to learn the fundamental concept of Abstract Syntax Trees (AST) and the way `eslint` works under the hood.
+- Familiarize yourself with the [AST explorer](https://astexplorer.net/) tool. Look into rules in `docs/rules`, create patterns in the rules, then analyze its AST.
+- Explore the blog posts on how to create a custom rule. [One blog post](https://blog.yonatan.dev/writing-a-custom-eslint-rule-to-spot-undeclared-props/). [Second blog post](https://betterprogramming.pub/creating-custom-eslint-rules-cdc579694608).
+- Read the official `eslint` [developer guide](https://eslint.org/docs/latest/developer-guide/architecture/).
+
 ## Issues
 
 ### Search open + closed issues for similar cases

From 74e2a9562c010aa0f875c83c644e929600fa64c8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 15:10:20 -0800
Subject: [PATCH 547/767] [resolvers/node] v0.3.7

---
 resolvers/node/CHANGELOG.md | 4 ++++
 resolvers/node/package.json | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index 8812f12760..f00006fbd3 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -5,6 +5,10 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v0.3.7 - 2023-01-11
+### Changed
+- [Refactor] use `is-core-module` directly
+
 ## v0.3.6 - 2021-08-15
 ### Fixed
 - when "module" does not exist, fall back to "main" ([#2186], thanks [@ljharb])
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 771249ee58..d13b48635f 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-node",
-  "version": "0.3.6",
+  "version": "0.3.7",
   "description": "Node default behavior import resolution plugin for eslint-plugin-import.",
   "main": "index.js",
   "files": [

From 3b45d2075b24fd3aeaf73776e0eb8738880a79c0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 15:12:41 -0800
Subject: [PATCH 548/767] [Deps] update `eslint-import-resolver-node`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index ec64bb18df..2984ab210b 100644
--- a/package.json
+++ b/package.json
@@ -106,7 +106,7 @@
     "array.prototype.flat": "^1.3.1",
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
-    "eslint-import-resolver-node": "^0.3.6",
+    "eslint-import-resolver-node": "^0.3.7",
     "eslint-module-utils": "^2.7.4",
     "has": "^1.0.3",
     "is-core-module": "^2.11.0",

From 01950df8ec68824f52aca43b751621059fea51cd Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 15:13:41 -0800
Subject: [PATCH 549/767] Bump to 2.27.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83b44e64a3..22c3472144 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.27.0] - 2023-01-11
+
 ### Added
 - [`newline-after-import`]: add `considerComments` option ([#2399], thanks [@pri1311])
 - [`no-cycle`]: add `allowUnsafeDynamicCyclicDependency` option ([#2387], thanks [@GerkinDev])
@@ -1471,7 +1473,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.26.0...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.0...HEAD
+[2.27.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.26.0...v2.27.0
 [2.26.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.4...v2.26.0
 [2.25.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.3...v2.25.4
 [2.25.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.2...v2.25.3
diff --git a/package.json b/package.json
index 2984ab210b..57c18ad560 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.26.0",
+  "version": "2.27.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 7cca10b80d0afcef78c61a9337932de5630cea4f Mon Sep 17 00:00:00 2001
From: Cristobal Dabed <cristobal@dabed.org>
Date: Thu, 12 Jan 2023 01:10:22 +0100
Subject: [PATCH 550/767] [Fix] `array.prototype.flatmap` should be a prod dep

---
 CHANGELOG.md | 5 +++++
 package.json | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22c3472144..de39e9dd06 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- `array.prototype.flatmap` should be a prod dep ([#2664], thanks [@cristobal])
+
 ## [2.27.0] - 2023-01-11
 
 ### Added
@@ -1032,6 +1035,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2664]: https://github.com/import-js/eslint-plugin-import/pull/2664
 [#2613]: https://github.com/import-js/eslint-plugin-import/pull/2613
 [#2608]: https://github.com/import-js/eslint-plugin-import/pull/2608
 [#2605]: https://github.com/import-js/eslint-plugin-import/pull/2605
@@ -1604,6 +1608,7 @@ for info on changes for earlier releases.
 [@chrislloyd]: https://github.com/chrislloyd
 [@christianvuerings]: https://github.com/christianvuerings
 [@christophercurrie]: https://github.com/christophercurrie
+[@cristobal]: https://github.com/cristobal
 [@DamienCassou]: https://github.com/DamienCassou
 [@danny-andrews]: https://github.com/dany-andrews
 [@darkartur]: https://github.com/darkartur
diff --git a/package.json b/package.json
index 57c18ad560..24471e7bd8 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,6 @@
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3 || ^5.10.0",
-    "array.prototype.flatmap": "^1.3.0",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
     "babel-eslint": "=8.0.3 || ^8.2.6",
@@ -104,6 +103,7 @@
   "dependencies": {
     "array-includes": "^3.1.6",
     "array.prototype.flat": "^1.3.1",
+    "array.prototype.flatmap": "^1.3.0",    
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.7",

From 167f16c5fdbc5cd194b10f19ebb89c0834f7c2df Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 19:34:36 -0800
Subject: [PATCH 551/767] Bump to 2.27.1

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index de39e9dd06..29f0fd32ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.27.1] - 2023-01-11
+
 ### Fixed
 - `array.prototype.flatmap` should be a prod dep ([#2664], thanks [@cristobal])
 
@@ -1477,7 +1479,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.0...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.1...HEAD
+[2.27.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.0...v2.27.1
 [2.27.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.26.0...v2.27.0
 [2.26.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.4...v2.26.0
 [2.25.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.3...v2.25.4
diff --git a/package.json b/package.json
index 24471e7bd8..bf9e18c92b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.27.0",
+  "version": "2.27.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 07171efc6fa9161eeb788e2af433436f434ca05c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 19:42:55 -0800
Subject: [PATCH 552/767] [Fix] `no-duplicates`: do not unconditionally require
 `typescript`

Fixes #2665
---
 CHANGELOG.md               | 4 ++++
 src/rules/no-duplicates.js | 8 ++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 29f0fd32ff..66f2a75b5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- [`no-duplicates`]: do not unconditionally require `typescript` ([#2665])
+
 ## [2.27.1] - 2023-01-11
 
 ### Fixed
@@ -1361,6 +1364,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2665]: https://github.com/import-js/eslint-plugin-import/issues/2665
 [#2444]: https://github.com/import-js/eslint-plugin-import/issues/2444
 [#2412]: https://github.com/import-js/eslint-plugin-import/issues/2412
 [#2392]: https://github.com/import-js/eslint-plugin-import/issues/2392
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index b896f442ae..93ec36a8eb 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -1,7 +1,11 @@
 import resolve from 'eslint-module-utils/resolve';
 import docsUrl from '../docsUrl';
 import semver from 'semver';
-import typescriptPkg from 'typescript/package.json';
+
+let typescriptPkg;
+try {
+  typescriptPkg = require('typescript/package.json');
+} catch (e) { /**/ }
 
 function checkImports(imported, context) {
   for (const [module, nodes] of imported.entries()) {
@@ -114,7 +118,7 @@ function getFix(first, rest, sourceCode, context) {
 
         const preferInline = context.options[0] && context.options[0]['prefer-inline'];
         // a user might set prefer-inline but not have a supporting TypeScript version.  Flow does not support inline types so this should fail in that case as well.
-        if (preferInline && !semver.satisfies(typescriptPkg.version, '>= 4.5')) {
+        if (preferInline && (!typescriptPkg || !semver.satisfies(typescriptPkg.version, '>= 4.5'))) {
           throw new Error('Your version of TypeScript does not support inline type imports.');
         }
 

From eee88e46d9d3b6e18de419569e7d31207a2a0ba5 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 19:43:36 -0800
Subject: [PATCH 553/767] Bump to 2.27.2

---
 CHANGELOG.md | 5 ++++-
 package.json | 4 ++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 66f2a75b5a..d926098da8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.27.2] - 2023-01-11
+
 ### Fixed
 - [`no-duplicates`]: do not unconditionally require `typescript` ([#2665])
 
@@ -1483,7 +1485,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.1...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.2...HEAD
+[2.27.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.1...v2.27.2
 [2.27.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.0...v2.27.1
 [2.27.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.26.0...v2.27.0
 [2.26.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.25.4...v2.26.0
diff --git a/package.json b/package.json
index bf9e18c92b..3ddaf6ea7f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.27.1",
+  "version": "2.27.2",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"
@@ -103,7 +103,7 @@
   "dependencies": {
     "array-includes": "^3.1.6",
     "array.prototype.flat": "^1.3.1",
-    "array.prototype.flatmap": "^1.3.0",    
+    "array.prototype.flatmap": "^1.3.0",
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.7",

From 203535504eda82860c05414ac83386087fcde1a3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 23:01:21 -0800
Subject: [PATCH 554/767] [Fix] `no-empty-named-blocks`: rewrite rule to only
 check import declarations

Fixes #2666
---
 CHANGELOG.md                             |   4 +
 src/rules/no-empty-named-blocks.js       | 111 +++++++++++++----------
 tests/src/rules/no-empty-named-blocks.js |  24 ++++-
 3 files changed, 88 insertions(+), 51 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d926098da8..2607f85f42 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- [`no-empty-named-blocks`]: rewrite rule to only check import declarations ([#2666])
+
 ## [2.27.2] - 2023-01-11
 
 ### Fixed
@@ -1366,6 +1369,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2666]: https://github.com/import-js/eslint-plugin-import/issues/2666
 [#2665]: https://github.com/import-js/eslint-plugin-import/issues/2665
 [#2444]: https://github.com/import-js/eslint-plugin-import/issues/2444
 [#2412]: https://github.com/import-js/eslint-plugin-import/issues/2412
diff --git a/src/rules/no-empty-named-blocks.js b/src/rules/no-empty-named-blocks.js
index 114736f168..25567b08f8 100644
--- a/src/rules/no-empty-named-blocks.js
+++ b/src/rules/no-empty-named-blocks.js
@@ -29,63 +29,78 @@ module.exports = {
   },
 
   create(context) {
+    const importsWithoutNameds = [];
+
     return {
-      Program(node) {
-        node.tokens.forEach((token, idx) => {
-          const nextToken = node.tokens[idx + 1];
+      ImportDeclaration(node) {
+        if (!node.specifiers.some(x => x.type === 'ImportSpecifier')) {
+          importsWithoutNameds.push(node);
+        }
+      },
+
+      'Program:exit': function (program) {
+        const importsTokens = importsWithoutNameds.map((node) => {
+          return [node, program.tokens.filter(x => x.range[0] >= node.range[0] && x.range[1] <= node.range[1])];
+        });
+
+        importsTokens.forEach(([node, tokens]) => {
+          tokens.forEach((token) => {
+            const idx = program.tokens.indexOf(token);
+            const nextToken = program.tokens[idx + 1];
 
-          if (nextToken && token.value === '{' && nextToken.value === '}') {
-            const hasOtherIdentifiers = node.tokens.some((token) => (
-              token.type === 'Identifier'
-                && token.value !== 'from'
-                && token.value !== 'type'
-                && token.value !== 'typeof'
-            ));
+            if (nextToken && token.value === '{' && nextToken.value === '}') {
+              const hasOtherIdentifiers = tokens.some((token) => (
+                token.type === 'Identifier'
+                  && token.value !== 'from'
+                  && token.value !== 'type'
+                  && token.value !== 'typeof'
+              ));
 
-            // If it has no other identifiers it's the only thing in the import, so we can either remove the import
-            // completely or transform it in a side-effects only import
-            if (!hasOtherIdentifiers) {
-              context.report({
-                node,
-                message: 'Unexpected empty named import block',
-                suggest: [
-                  {
-                    desc: 'Remove unused import',
-                    fix(fixer) {
-                      // Remove the whole import
-                      return fixer.remove(node);
+              // If it has no other identifiers it's the only thing in the import, so we can either remove the import
+              // completely or transform it in a side-effects only import
+              if (!hasOtherIdentifiers) {
+                context.report({
+                  node,
+                  message: 'Unexpected empty named import block',
+                  suggest: [
+                    {
+                      desc: 'Remove unused import',
+                      fix(fixer) {
+                        // Remove the whole import
+                        return fixer.remove(node);
+                      },
                     },
-                  },
-                  {
-                    desc: 'Remove empty import block',
-                    fix(fixer) {
-                      // Remove the empty block and the 'from' token, leaving the import only for its side
-                      // effects, e.g. `import 'mod'`
-                      const sourceCode = context.getSourceCode();
-                      const fromToken = node.tokens.find(t => t.value === 'from');
-                      const importToken = node.tokens.find(t => t.value === 'import');
-                      const hasSpaceAfterFrom = sourceCode.isSpaceBetween(fromToken, sourceCode.getTokenAfter(fromToken));
-                      const hasSpaceAfterImport = sourceCode.isSpaceBetween(importToken, sourceCode.getTokenAfter(fromToken));
+                    {
+                      desc: 'Remove empty import block',
+                      fix(fixer) {
+                        // Remove the empty block and the 'from' token, leaving the import only for its side
+                        // effects, e.g. `import 'mod'`
+                        const sourceCode = context.getSourceCode();
+                        const fromToken = program.tokens.find(t => t.value === 'from');
+                        const importToken = program.tokens.find(t => t.value === 'import');
+                        const hasSpaceAfterFrom = sourceCode.isSpaceBetween(fromToken, sourceCode.getTokenAfter(fromToken));
+                        const hasSpaceAfterImport = sourceCode.isSpaceBetween(importToken, sourceCode.getTokenAfter(fromToken));
 
-                      const [start] = getEmptyBlockRange(node.tokens, idx);
-                      const [, end] = fromToken.range;
-                      const range = [start, hasSpaceAfterFrom ? end + 1 : end];
+                        const [start] = getEmptyBlockRange(program.tokens, idx);
+                        const [, end] = fromToken.range;
+                        const range = [start, hasSpaceAfterFrom ? end + 1 : end];
 
-                      return fixer.replaceTextRange(range, hasSpaceAfterImport ? '' : ' ');
+                        return fixer.replaceTextRange(range, hasSpaceAfterImport ? '' : ' ');
+                      },
                     },
+                  ],
+                });
+              } else {
+                context.report({
+                  node,
+                  message: 'Unexpected empty named import block',
+                  fix(fixer) {
+                    return fixer.removeRange(getEmptyBlockRange(program.tokens, idx));
                   },
-                ],
-              });
-            } else {
-              context.report({
-                node,
-                message: 'Unexpected empty named import block',
-                fix(fixer) {
-                  return fixer.removeRange(getEmptyBlockRange(node.tokens, idx));
-                },
-              });
+                });
+              }
             }
-          }
+          });
         });
       },
     };
diff --git a/tests/src/rules/no-empty-named-blocks.js b/tests/src/rules/no-empty-named-blocks.js
index ee21db3478..87a0a3e7c9 100644
--- a/tests/src/rules/no-empty-named-blocks.js
+++ b/tests/src/rules/no-empty-named-blocks.js
@@ -42,9 +42,27 @@ ruleTester.run('no-empty-named-blocks', rule, {
     ] : [],
 
     // Flow
-    test({ code: `import typeof Default from 'mod';`, parser: parsers.BABEL_OLD }),
-    test({ code: `import typeof { Named } from 'mod';`, parser: parsers.BABEL_OLD }),
-    test({ code: `import typeof Default, { Named } from 'mod';`, parser: parsers.BABEL_OLD }),
+    test({ code: `import typeof Default from 'mod'; // babel old`, parser: parsers.BABEL_OLD }),
+    test({ code: `import typeof { Named } from 'mod'; // babel old`, parser: parsers.BABEL_OLD }),
+    test({ code: `import typeof Default, { Named } from 'mod'; // babel old`, parser: parsers.BABEL_OLD }),
+    test({
+      code: `
+        module.exports = {
+          rules: {
+            'keyword-spacing': ['error', {overrides: {}}],
+          }
+        };
+      `,
+    }),
+    test({
+      code: `
+        import { DESCRIPTORS, NODE } from '../helpers/constants';
+        // ...
+        import { timeLimitedPromise } from '../helpers/helpers';
+        // ...
+        import { DESCRIPTORS2 } from '../helpers/constants';
+      `,
+    }),
   ),
   invalid: [].concat(
     test({

From 82d81f19abe9988b0c91e650c61161ec6c0f50e7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 23:13:03 -0800
Subject: [PATCH 555/767] Bump to 2.27.3

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2607f85f42..4c4f66a850 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.27.3] - 2023-01-11
+
 ### Fixed
 - [`no-empty-named-blocks`]: rewrite rule to only check import declarations ([#2666])
 
@@ -1489,7 +1491,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.2...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.3...HEAD
+[2.27.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.2...v2.27.3
 [2.27.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.1...v2.27.2
 [2.27.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.0...v2.27.1
 [2.27.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.26.0...v2.27.0
diff --git a/package.json b/package.json
index 3ddaf6ea7f..0275b32437 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.27.2",
+  "version": "2.27.3",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 520e169abdef9f3e6648675995f2778465081aa8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 23:15:44 -0800
Subject: [PATCH 556/767] [Fix] `semver` should be a prod dep

Fixes #2668
---
 CHANGELOG.md | 4 ++++
 package.json | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c4f66a850..f58f1f9b6f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- `semver` should be a prod dep ([#2668])
+
 ## [2.27.3] - 2023-01-11
 
 ### Fixed
@@ -1371,6 +1374,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2668]: https://github.com/import-js/eslint-plugin-import/issues/2668
 [#2666]: https://github.com/import-js/eslint-plugin-import/issues/2666
 [#2665]: https://github.com/import-js/eslint-plugin-import/issues/2665
 [#2444]: https://github.com/import-js/eslint-plugin-import/issues/2444
diff --git a/package.json b/package.json
index 0275b32437..71aba4c2ab 100644
--- a/package.json
+++ b/package.json
@@ -92,7 +92,6 @@
     "redux": "^3.7.2",
     "rimraf": "^2.7.1",
     "safe-publish-latest": "^2.0.0",
-    "semver": "^6.3.0",
     "sinon": "^2.4.1",
     "typescript": "^2.8.1 || ~3.9.5 || ~4.5.2",
     "typescript-eslint-parser": "^15 || ^20 || ^22"
@@ -114,6 +113,7 @@
     "minimatch": "^3.1.2",
     "object.values": "^1.1.6",
     "resolve": "^1.22.1",
+    "semver": "^6.3.0",
     "tsconfig-paths": "^3.14.1"
   }
 }

From cda23feaf2083c78f97fdfd44d7277b55aee3f25 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 23:16:29 -0800
Subject: [PATCH 557/767] Bump to 2.27.4

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f58f1f9b6f..48bf738e0b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.27.4] - 2023-01-11
+
 ### Fixed
 - `semver` should be a prod dep ([#2668])
 
@@ -1495,7 +1497,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.3...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.4...HEAD
+[2.27.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.3...v2.27.4
 [2.27.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.2...v2.27.3
 [2.27.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.1...v2.27.2
 [2.27.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.0...v2.27.1
diff --git a/package.json b/package.json
index 71aba4c2ab..0ec56aafa6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.27.3",
+  "version": "2.27.4",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From af8fd26766912a47b213d6e6676195ab9383524e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Jan 2023 23:35:11 -0800
Subject: [PATCH 558/767] =?UTF-8?q?[eslint]=20configure=20`no-extraneous-d?=
 =?UTF-8?q?ependencies`=20rule=20properly,=20to=20prevent=20today=E2=80=99?=
 =?UTF-8?q?s=20bugs?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .eslintrc                  | 12 ++++++++++--
 src/ExportMap.js           |  2 +-
 src/rules/no-duplicates.js |  2 +-
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index a90ba1d4be..1c41cb71bd 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -76,7 +76,16 @@
         "eslint-plugin/require-meta-type": "error",
 
         // dog fooding
-        "import/no-extraneous-dependencies": "error",
+        "import/no-extraneous-dependencies": ["error", {
+            "devDependencies": [
+                "tests/**",
+                "resolvers/*/test/**",
+                "scripts/**"
+            ],
+            "optionalDependencies": false,
+            "peerDependencies": true,
+            "bundledDependencies": false,
+        }],
         "import/unambiguous": "off",
     },
 
@@ -106,7 +115,6 @@
         {
             "files": "resolvers/webpack/**",
             "rules": {
-                "import/no-extraneous-dependencies": 1,
                 "no-console": 1,
             },
             "env": {
diff --git a/src/ExportMap.js b/src/ExportMap.js
index d95fdb7a75..7b8c883143 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -558,7 +558,7 @@ ExportMap.parse = function (path, content, context) {
     try {
       if (tsConfigInfo.tsConfigPath !== undefined) {
         // Projects not using TypeScript won't have `typescript` installed.
-        if (!ts) { ts = require('typescript'); }
+        if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
   
         const configFile = ts.readConfigFile(tsConfigInfo.tsConfigPath, ts.sys.readFile);
         return ts.parseJsonConfigFileContent(
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 93ec36a8eb..e2df4afdb4 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -4,7 +4,7 @@ import semver from 'semver';
 
 let typescriptPkg;
 try {
-  typescriptPkg = require('typescript/package.json');
+  typescriptPkg = require('typescript/package.json'); // eslint-disable-line import/no-extraneous-dependencies
 } catch (e) { /**/ }
 
 function checkImports(imported, context) {

From 0778b0390ec18b9fdc1acfd45d10bf1b614d82ff Mon Sep 17 00:00:00 2001
From: Pearce <pearce@sigmacomputing.com>
Date: Fri, 13 Jan 2023 12:49:34 -0800
Subject: [PATCH 559/767] [Fix] `order`: Fix group ranks order when
 alphabetizing

Fixes #2671
---
 CHANGELOG.md             |  4 ++++
 src/rules/order.js       |  9 ++++++---
 tests/src/rules/order.js | 43 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 48bf738e0b..907ceb0596 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- [`order]`: Fix group ranks order when alphabetizing ([#2674], thanks [@Pearce-Ropion])
+
 ## [2.27.4] - 2023-01-11
 
 ### Fixed
@@ -1376,6 +1379,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2674]: https://github.com/import-js/eslint-plugin-import/issues/2674
 [#2668]: https://github.com/import-js/eslint-plugin-import/issues/2668
 [#2666]: https://github.com/import-js/eslint-plugin-import/issues/2666
 [#2665]: https://github.com/import-js/eslint-plugin-import/issues/2665
diff --git a/src/rules/order.js b/src/rules/order.js
index dc9da64f22..bdead9d40c 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -334,10 +334,13 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
     return acc;
   }, {});
 
-  const groupRanks = Object.keys(groupedByRanks);
-
   const sorterFn = getSorter(alphabetizeOptions);
 
+  // sort group keys so that they can be iterated on in order
+  const groupRanks = Object.keys(groupedByRanks).sort(function (a, b) {
+    return a - b;
+  });
+
   // sort imports locally within their group
   groupRanks.forEach(function (groupRank) {
     groupedByRanks[groupRank].sort(sorterFn);
@@ -345,7 +348,7 @@ function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
 
   // assign globally unique rank to each import
   let newRank = 0;
-  const alphabetizedRanks = groupRanks.sort().reduce(function (acc, groupRank) {
+  const alphabetizedRanks = groupRanks.reduce(function (acc, groupRank) {
     groupedByRanks[groupRank].forEach(function (importedItem) {
       acc[`${importedItem.value}|${importedItem.node.importKind}`] = parseInt(groupRank, 10) + newRank;
       newRank += 1;
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 07511ee4de..b7d86dd93f 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2280,6 +2280,8 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+
+    // pathGroups overflowing to previous/next groups
     test({
       code: `
         import path from 'path';
@@ -2349,6 +2351,47 @@ ruleTester.run('order', rule, {
       errors: Array.from({ length: 11 }, () => 'There should be at least one empty line between import groups'),
     }),
 
+    // rankings that overflow to double-digit ranks
+    test({
+      code: `
+        import external from 'external';
+        import a from '@namespace/a';
+        import b from '@namespace/b';
+        import { parent } from '../../parent';
+        import local from './local';
+        import './side-effect';`,
+      output: `
+        import external from 'external';
+
+        import a from '@namespace/a';
+        import b from '@namespace/b';
+
+        import { parent } from '../../parent';
+
+        import local from './local';
+        import './side-effect';`,
+      options: [
+        {
+          alphabetize: {
+            order: 'asc',
+            caseInsensitive: true,
+          },
+          groups: ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object'],
+          'newlines-between': 'always',
+          pathGroups: [
+            { pattern: '@namespace', group: 'external', position: 'after' },
+            { pattern: '@namespace/**', group: 'external', position: 'after' },
+          ],
+          pathGroupsExcludedImportTypes: ['@namespace'],
+        },
+      ],
+      errors: [
+        'There should be at least one empty line between import groups',
+        'There should be at least one empty line between import groups',
+        'There should be at least one empty line between import groups',
+      ],
+    }),
+
     // reorder fix cannot cross non import or require
     test(withoutAutofixOutput({
       code: `

From 3cb966edccbd6482db8503336dc855cd180793b8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 16 Jan 2023 10:25:01 -0800
Subject: [PATCH 560/767] [Deps] update `array.prototype.flatmap`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 0ec56aafa6..8dcf9a5b72 100644
--- a/package.json
+++ b/package.json
@@ -102,7 +102,7 @@
   "dependencies": {
     "array-includes": "^3.1.6",
     "array.prototype.flat": "^1.3.1",
-    "array.prototype.flatmap": "^1.3.0",
+    "array.prototype.flatmap": "^1.3.1",
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.7",

From ee6e1be7da260a30179339afe5fccba7acec6545 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 16 Jan 2023 10:33:15 -0800
Subject: [PATCH 561/767] [Refactor] minor performance refactors

---
 scripts/copyMetafiles.js                      |  6 ++--
 src/rules/export.js                           |  2 +-
 src/rules/no-namespace.js                     |  5 +--
 .../rules/consistent-type-specifier-style.js  | 32 +++++++++----------
 4 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/scripts/copyMetafiles.js b/scripts/copyMetafiles.js
index d14964f1c7..6140bd2dc9 100644
--- a/scripts/copyMetafiles.js
+++ b/scripts/copyMetafiles.js
@@ -8,11 +8,11 @@ const files = [
   '.nycrc',
 ];
 
-const directories = [
+const directories = [].concat(
   'memo-parser',
-  ...resolverDirectories,
+  resolverDirectories,
   'utils',
-];
+);
 
 for (const directory of directories) {
   for (const file of files) {
diff --git a/src/rules/export.js b/src/rules/export.js
index da0df1ee75..92583bdd8f 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -37,7 +37,6 @@ const tsTypePrefix = 'type:';
  */
 function isTypescriptFunctionOverloads(nodes) {
   const nodesArr = Array.from(nodes);
-  const types = new Set(nodesArr.map(node => node.parent.type));
 
   const idents = flatMap(nodesArr, (node) => (
     node.declaration && (
@@ -51,6 +50,7 @@ function isTypescriptFunctionOverloads(nodes) {
     return true;
   }
 
+  const types = new Set(nodesArr.map(node => node.parent.type));
   if (!types.has('TSDeclareFunction')) {
     return false;
   }
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index 4382007a59..a078137e65 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -144,10 +144,7 @@ function getVariableNamesInScope(scopeManager, node) {
     currentNode = currentNode.parent;
     scope = scopeManager.acquire(currentNode, true);
   }
-  return new Set([
-    ...scope.variables.map(variable => variable.name),
-    ...scope.upper.variables.map(variable => variable.name),
-  ]);
+  return new Set(scope.variables.concat(scope.upper.variables).map(variable => variable.name));
 }
 
 /**
diff --git a/tests/src/rules/consistent-type-specifier-style.js b/tests/src/rules/consistent-type-specifier-style.js
index 31a4c09ffe..440ef3aff5 100644
--- a/tests/src/rules/consistent-type-specifier-style.js
+++ b/tests/src/rules/consistent-type-specifier-style.js
@@ -367,14 +367,14 @@ context('TypeScript', () => {
     },
   });
   ruleTester.run('consistent-type-specifier-style', rule, {
-    valid: [
-      ...COMMON_TESTS.valid,
-      ...TS_ONLY.valid,
-    ],
-    invalid: [
-      ...COMMON_TESTS.invalid,
-      ...TS_ONLY.invalid,
-    ],
+    valid: [].concat(
+      COMMON_TESTS.valid,
+      TS_ONLY.valid,
+    ),
+    invalid: [].concat(
+      COMMON_TESTS.invalid,
+      TS_ONLY.invalid,
+    ),
   });
 });
 
@@ -391,13 +391,13 @@ context('Babel/Flow', () => {
     },
   });
   ruleTester.run('consistent-type-specifier-style', rule, {
-    valid: [
-      ...COMMON_TESTS.valid,
-      ...FLOW_ONLY.valid,
-    ],
-    invalid: [
-      ...COMMON_TESTS.invalid,
-      ...FLOW_ONLY.invalid,
-    ],
+    valid: [].concat(
+      COMMON_TESTS.valid,
+      FLOW_ONLY.valid,
+    ),
+    invalid: [].concat(
+      COMMON_TESTS.invalid,
+      FLOW_ONLY.invalid,
+    ),
   });
 });

From 5ff9e45d585c5aac396802288aa9a8d93b0a09c6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 16 Jan 2023 11:44:15 -0800
Subject: [PATCH 562/767] Bump to v2.27.5

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 907ceb0596..9d63f05558 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.27.5] - 2023-01-16
+
 ### Fixed
 - [`order]`: Fix group ranks order when alphabetizing ([#2674], thanks [@Pearce-Ropion])
 
@@ -1501,7 +1503,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.4...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...HEAD
+[2.27.5]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.4...v2.27.5
 [2.27.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.3...v2.27.4
 [2.27.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.2...v2.27.3
 [2.27.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.1...v2.27.2
diff --git a/package.json b/package.json
index 8dcf9a5b72..299cf52b0c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.27.4",
+  "version": "2.27.5",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From defcf082e03f71af900e7e7d8abfe9a07f660446 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 17 Jan 2023 10:42:46 -0800
Subject: [PATCH 563/767] [Tests] `order`: add a passing test

Closes #2662
---
 tests/src/rules/order.js | 86 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 82 insertions(+), 4 deletions(-)

diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index b7d86dd93f..291dae33b0 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1096,16 +1096,15 @@ ruleTester.run('order', rule, {
     // orderImportKind option that is not used
     test({
       code: `
-            import B from './B';
-            import b from './b';
-          `,
+        import B from './B';
+        import b from './b';
+      `,
       options: [
         {
           'alphabetize': { order: 'asc', orderImportKind: 'asc', 'caseInsensitive': true },
         },
       ],
     }),
-
   ],
   invalid: [
     // builtin before external module (require)
@@ -3275,5 +3274,84 @@ flowRuleTester.run('order', rule, {
         message: '`./local/sub` typeof import should occur before import of `./local/sub`',
       }],
     }),
+    test({
+      code: `
+        import { cfg } from 'path/path/path/src/Cfg';
+        import { l10n } from 'path/src/l10n';
+        import { helpers } from 'path/path/path/helpers';
+        import { tip } from 'path/path/tip';
+
+        import { controller } from '../../../../path/path/path/controller';
+        import { component } from '../../../../path/path/path/component';
+      `,
+      output: semver.satisfies(eslintPkg.version, '< 3') ? `
+        import { cfg } from 'path/path/path/src/Cfg';
+        import { tip } from 'path/path/tip';
+        import { l10n } from 'path/src/l10n';
+        import { helpers } from 'path/path/path/helpers';
+
+        import { component } from '../../../../path/path/path/component';
+        import { controller } from '../../../../path/path/path/controller';
+      ` : `
+        import { helpers } from 'path/path/path/helpers';
+        import { cfg } from 'path/path/path/src/Cfg';
+        import { l10n } from 'path/src/l10n';
+        import { tip } from 'path/path/tip';
+
+        import { component } from '../../../../path/path/path/component';
+        import { controller } from '../../../../path/path/path/controller';
+      `,
+      options: [
+        {
+          'groups': [
+            ['builtin', 'external'],
+            'internal',
+            ['sibling', 'parent'],
+            'object',
+            'type',
+          ],
+          'pathGroups': [
+            {
+              'pattern': 'react',
+              'group': 'builtin',
+              'position': 'before',
+              'patternOptions': {
+                'matchBase': true,
+              },
+            },
+            {
+              'pattern': '*.+(css|svg)',
+              'group': 'type',
+              'position': 'after',
+              'patternOptions': {
+                'matchBase': true,
+              },
+            },
+          ],
+          'pathGroupsExcludedImportTypes': ['react'],
+          'alphabetize': {
+            'order': 'asc',
+          },
+          'newlines-between': 'always',
+        },
+      ],
+      errors: [
+        {
+          message: '`path/path/path/helpers` import should occur before import of `path/path/path/src/Cfg`',
+          line: 4,
+          column: 9,
+        },
+        {
+          message: '`path/path/tip` import should occur before import of `path/src/l10n`',
+          line: 5,
+          column: 9,
+        },
+        {
+          message: '`../../../../path/path/path/component` import should occur before import of `../../../../path/path/path/controller`',
+          line: 8,
+          column: 9,
+        },
+      ],
+    }),
   ],
 });

From 766af5ff6c2e97cbe2a2a211729f7c129da3005d Mon Sep 17 00:00:00 2001
From: Mike Simmonds <mike@simmo.me>
Date: Wed, 18 Jan 2023 22:29:38 +0000
Subject: [PATCH 564/767] [Docs] `no-duplicates`: fix example schema

---
 CHANGELOG.md                | 5 +++++
 docs/rules/no-duplicates.md | 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d63f05558..894aa97b30 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Changed
+- [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
+
 ## [2.27.5] - 2023-01-16
 
 ### Fixed
@@ -1381,6 +1384,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2684]: https://github.com/import-js/eslint-plugin-import/issues/2684
 [#2674]: https://github.com/import-js/eslint-plugin-import/issues/2674
 [#2668]: https://github.com/import-js/eslint-plugin-import/issues/2668
 [#2666]: https://github.com/import-js/eslint-plugin-import/issues/2666
@@ -1800,6 +1804,7 @@ for info on changes for earlier releases.
 [@sheepsteak]: https://github.com/sheepsteak
 [@silviogutierrez]: https://github.com/silviogutierrez
 [@SimenB]: https://github.com/SimenB
+[@simmo]: https://github.com/simmo
 [@sindresorhus]: https://github.com/sindresorhus
 [@singles]: https://github.com/singles
 [@skozin]: https://github.com/skozin
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index 553fbbcc34..5f3cfbd426 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -79,14 +79,14 @@ Config:
 
 <!--tabs-->
 
-❌ Invalid `["error", "prefer-inline"]`
+❌ Invalid `["error", {"prefer-inline": true}]`
 
 ```js
 import { AValue, type AType } from './mama-mia'
 import type { BType } from './mama-mia'
 ```
 
-✅ Valid with `["error", "prefer-inline"]`
+✅ Valid with `["error", {"prefer-inline": true}]`
 
 ```js
 import { AValue, type AType, type BType } from './mama-mia'

From 87a609689777203fe94a0b702fa92d387a52a3f4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 27 Jan 2023 08:59:52 -0800
Subject: [PATCH 565/767] Revert "[Tests] update nvm in travis"

This reverts commit 8b0fb989ae08161499a478ab23fb10b68e3cd828.
---
 .travis.yml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index f57222a8ff..21a7070fb7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,7 +25,6 @@ matrix:
   fast_finish: true
 
 before_install:
-  - 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash && . $NVM_DIR/nvm.sh'
   - 'nvm install-latest-npm'
   - 'NPM_CONFIG_LEGACY_PEER_DEPS=true npm install'
   - 'npm run copy-metafiles'

From 50b3d23062e58b884d741b1e5b77d4feeea82747 Mon Sep 17 00:00:00 2001
From: Joe Portner <5295965+jportner@users.noreply.github.com>
Date: Fri, 21 Oct 2022 11:59:00 -0400
Subject: [PATCH 566/767] [Fix] `no-duplicates`: remove duplicate identifiers
 in duplicate imports

---
 CHANGELOG.md                     |  5 +++++
 src/rules/no-duplicates.js       | 31 +++++++++++++++++++++++--------
 tests/src/rules/no-duplicates.js | 31 +++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 894aa97b30..8186d87856 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- [`no-duplicates`]: remove duplicate identifiers in duplicate imports ([#2577], thanks [@joe-matsec])
+
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
 
@@ -1389,6 +1392,7 @@ for info on changes for earlier releases.
 [#2668]: https://github.com/import-js/eslint-plugin-import/issues/2668
 [#2666]: https://github.com/import-js/eslint-plugin-import/issues/2666
 [#2665]: https://github.com/import-js/eslint-plugin-import/issues/2665
+[#2577]: https://github.com/import-js/eslint-plugin-import/issues/2577
 [#2444]: https://github.com/import-js/eslint-plugin-import/issues/2444
 [#2412]: https://github.com/import-js/eslint-plugin-import/issues/2412
 [#2392]: https://github.com/import-js/eslint-plugin-import/issues/2392
@@ -1703,6 +1707,7 @@ for info on changes for earlier releases.
 [@jimbolla]: https://github.com/jimbolla
 [@jkimbo]: https://github.com/jkimbo
 [@joaovieira]: https://github.com/joaovieira
+[@joe-matsec]: https://github.com/joe-matsec
 [@johndevedu]: https://github.com/johndevedu
 [@johnthagen]: https://github.com/johnthagen
 [@jonboiser]: https://github.com/jonboiser
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index e2df4afdb4..15515e6757 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -79,8 +79,7 @@ function getFix(first, rest, sourceCode, context) {
 
       return {
         importNode: node,
-        text: sourceCode.text.slice(openBrace.range[1], closeBrace.range[0]),
-        hasTrailingComma: isPunctuator(sourceCode.getTokenBefore(closeBrace), ','),
+        identifiers: sourceCode.text.slice(openBrace.range[1], closeBrace.range[0]).split(','), // Split the text into separate identifiers (retaining any whitespace before or after)
         isEmpty: !hasSpecifiers(node),
       };
     })
@@ -111,9 +110,15 @@ function getFix(first, rest, sourceCode, context) {
       closeBrace != null &&
       isPunctuator(sourceCode.getTokenBefore(closeBrace), ',');
     const firstIsEmpty = !hasSpecifiers(first);
+    const firstExistingIdentifiers = firstIsEmpty
+      ? new Set()
+      : new Set(sourceCode.text.slice(openBrace.range[1], closeBrace.range[0])
+        .split(',')
+        .map((x) => x.trim()),
+      );
 
     const [specifiersText] = specifiers.reduce(
-      ([result, needsComma], specifier) => {
+      ([result, needsComma, existingIdentifiers], specifier) => {
         const isTypeSpecifier = specifier.importNode.importKind === 'type';
 
         const preferInline = context.options[0] && context.options[0]['prefer-inline'];
@@ -122,15 +127,25 @@ function getFix(first, rest, sourceCode, context) {
           throw new Error('Your version of TypeScript does not support inline type imports.');
         }
 
-        const insertText = `${preferInline && isTypeSpecifier ? 'type ' : ''}${specifier.text}`;
+        // Add *only* the new identifiers that don't already exist, and track any new identifiers so we don't add them again in the next loop
+        const [specifierText, updatedExistingIdentifiers] = specifier.identifiers.reduce(([text, set], cur) => {
+          const trimmed = cur.trim(); // Trim whitespace before/after to compare to our set of existing identifiers
+          const curWithType = trimmed.length > 0 && preferInline && isTypeSpecifier ? `type ${cur}` : cur;
+          if (existingIdentifiers.has(trimmed)) {
+            return [text, set];
+          }
+          return [text.length > 0 ? `${text},${curWithType}` : curWithType, set.add(trimmed)];
+        }, ['', existingIdentifiers]);
+
         return [
-          needsComma && !specifier.isEmpty
-            ? `${result},${insertText}`
-            : `${result}${insertText}`,
+          needsComma && !specifier.isEmpty && specifierText.length > 0
+            ? `${result},${specifierText}`
+            : `${result}${specifierText}`,
           specifier.isEmpty ? needsComma : true,
+          updatedExistingIdentifiers,
         ];
       },
-      ['', !firstHasTrailingComma && !firstIsEmpty],
+      ['', !firstHasTrailingComma && !firstIsEmpty, firstExistingIdentifiers],
     );
 
     const fixes = [];
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index f8a27a743b..ac76c3070a 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -5,6 +5,7 @@ import jsxConfig from '../../../config/react';
 import { RuleTester } from 'eslint';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
+import flatMap from 'array.prototype.flatmap';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-duplicates');
@@ -130,6 +131,36 @@ ruleTester.run('no-duplicates', rule, {
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
 
+    // These test cases use duplicate import identifiers, which causes a fatal parsing error using ESPREE (default) and TS_OLD.
+    ...flatMap([parsers.BABEL_OLD, parsers.TS_NEW], parser => {
+      if (!parser) return []; // TS_NEW is not always available
+      return [
+        // #2347: duplicate identifiers should be removed
+        test({
+          code: "import {a} from './foo'; import { a } from './foo'",
+          output: "import {a} from './foo'; ",
+          errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
+          parser,
+        }),
+
+        // #2347: duplicate identifiers should be removed
+        test({
+          code: "import {a,b} from './foo'; import { b, c } from './foo'; import {b,c,d} from './foo'",
+          output: "import {a,b, c ,d} from './foo';  ",
+          errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
+          parser,
+        }),
+
+        // #2347: duplicate identifiers should be removed, but not if they are adjacent to comments
+        test({
+          code: "import {a} from './foo'; import { a/*,b*/ } from './foo'",
+          output: "import {a, a/*,b*/ } from './foo'; ",
+          errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
+          parser,
+        }),
+      ];
+    }),
+
     test({
       code: "import {x} from './foo'; import {} from './foo'; import {/*c*/} from './foo'; import {y} from './foo'",
       output: "import {x/*c*/,y} from './foo';   ",

From 808d504bffe29286a885475a424562969e9d4879 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 7 Feb 2023 10:21:05 -0800
Subject: [PATCH 567/767] [Fix] TypeScript config: fix resolver extension
 settings

---
 CHANGELOG.md         | 1 +
 config/typescript.js | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8186d87856..1b1999bb26 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - [`no-duplicates`]: remove duplicate identifiers in duplicate imports ([#2577], thanks [@joe-matsec])
+- TypeScript config: fix resolver extension settings (thanks [@gajus])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
diff --git a/config/typescript.js b/config/typescript.js
index ed03fb3f6c..59c3c42dae 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -16,7 +16,7 @@ module.exports = {
       '@typescript-eslint/parser': ['.ts', '.tsx'],
     },
     'import/resolver': {
-      'node': {
+      'typescript': {
         'extensions': allExtensions,
       },
     },

From d5fc8b670dc8e6903dbb7b0894452f60c03089f5 Mon Sep 17 00:00:00 2001
From: Devin Rhode <devinrhode2@gmail.com>
Date: Tue, 31 Jan 2023 10:12:37 -0600
Subject: [PATCH 568/767] [Docs] `group-exports`: fix syntax highlighting

These snippets didn't have any syntax highlighting:
First chunk: https://share.cleanshot.com/spXGCRRGJkpBsLGLPk7k
Second chunk: https://share.cleanshot.com/vhRsmDnxCd7PZfFfLLhh

I searched codebase for any other ```flow js code blocks,
but there were only these two from this file:
https://share.cleanshot.com/xY7W9TJTXPrJ8ngtf6Kr
---
 CHANGELOG.md                | 3 +++
 docs/rules/group-exports.md | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b1999bb26..c16d2c9ffa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
+- [Docs] [`group-exports`]: fix syntax highlighting ([#2699], thanks [@devinrhode2])
 
 ## [2.27.5] - 2023-01-16
 
@@ -1064,6 +1065,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2699]: https://github.com/import-js/eslint-plugin-import/pull/2699
 [#2664]: https://github.com/import-js/eslint-plugin-import/pull/2664
 [#2613]: https://github.com/import-js/eslint-plugin-import/pull/2613
 [#2608]: https://github.com/import-js/eslint-plugin-import/pull/2608
@@ -1654,6 +1656,7 @@ for info on changes for earlier releases.
 [@darkartur]: https://github.com/darkartur
 [@davidbonnet]: https://github.com/davidbonnet
 [@dbrewer5]: https://github.com/dbrewer5
+[@devinrhode2]: https://github.com/devinrhode2
 [@devongovett]: https://github.com/devongovett
 [@dmnd]: https://github.com/dmnd
 [@duncanbeevers]: https://github.com/duncanbeevers
diff --git a/docs/rules/group-exports.md b/docs/rules/group-exports.md
index c5a23cd218..67e76de2fe 100644
--- a/docs/rules/group-exports.md
+++ b/docs/rules/group-exports.md
@@ -62,7 +62,7 @@ test.another = true
 module.exports = test
 ```
 
-```flow js
+```ts
 const first = true;
 type firstType = boolean
 
@@ -105,7 +105,7 @@ module.exports.first = true
 module.exports.second = true
 ```
 
-```flow js
+```ts
 type firstType = boolean
 type secondType = any
 

From 8f05399f3b13ea224b0dd5b6f137dc3ba5928574 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 12 Feb 2023 14:17:53 -0800
Subject: [PATCH 569/767] [Dev Deps] update `@angular-eslint/template-parser`,
 `chai`, `eslint-doc-generator`, `glob`

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 299cf52b0c..d543ec5a83 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
   },
   "homepage": "https://github.com/import-js/eslint-plugin-import",
   "devDependencies": {
-    "@angular-eslint/template-parser": "^13.2.1",
+    "@angular-eslint/template-parser": "^13.5.0",
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
     "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3 || ^5.10.0",
@@ -68,11 +68,11 @@
     "babel-preset-flow": "^6.23.0",
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
-    "chai": "^4.3.6",
+    "chai": "^4.3.7",
     "cross-env": "^4.0.0",
     "escope": "^3.6.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8",
-    "eslint-doc-generator": "^1.0.0",
+    "eslint-doc-generator": "^1.4.3",
     "eslint-import-resolver-node": "file:./resolvers/node",
     "eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
@@ -82,7 +82,7 @@
     "eslint-plugin-import": "2.x",
     "eslint-plugin-json": "^2.1.2",
     "fs-copy-file-sync": "^1.1.1",
-    "glob": "^7.2.0",
+    "glob": "^7.2.3",
     "in-publish": "^2.0.1",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",

From 5680a1f8d41cd19f9c60d999a6fadf10994a0a64 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 25 Feb 2023 10:57:20 -0800
Subject: [PATCH 570/767] [Deps] update `tsconfig-paths`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index d543ec5a83..3733e2d76f 100644
--- a/package.json
+++ b/package.json
@@ -114,6 +114,6 @@
     "object.values": "^1.1.6",
     "resolve": "^1.22.1",
     "semver": "^6.3.0",
-    "tsconfig-paths": "^3.14.1"
+    "tsconfig-paths": "^3.14.2"
   }
 }

From 6f12316ee7faa879fb046e04c8be8352f013a6f2 Mon Sep 17 00:00:00 2001
From: Brad Zacher <brad.zacher@gmail.com>
Date: Thu, 6 Apr 2023 16:31:23 +0930
Subject: [PATCH 571/767] [Fix] `consistent-type-specifier-style`: fix
 accidental removal of comma in certain cases

---
 CHANGELOG.md                                  |  2 ++
 src/rules/consistent-type-specifier-style.js  |  6 ++---
 .../rules/consistent-type-specifier-style.js  | 27 +++++++++++++++++++
 3 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c16d2c9ffa..1866819b09 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [`no-duplicates`]: remove duplicate identifiers in duplicate imports ([#2577], thanks [@joe-matsec])
 - TypeScript config: fix resolver extension settings (thanks [@gajus])
+- [`consistent-type-specifier-style`]: fix accidental removal of comma in certain cases ([#2754], thanks [@bradzacher])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
@@ -1065,6 +1066,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2754]: https://github.com/import-js/eslint-plugin-import/pull/2754
 [#2699]: https://github.com/import-js/eslint-plugin-import/pull/2699
 [#2664]: https://github.com/import-js/eslint-plugin-import/pull/2664
 [#2613]: https://github.com/import-js/eslint-plugin-import/pull/2613
diff --git a/src/rules/consistent-type-specifier-style.js b/src/rules/consistent-type-specifier-style.js
index 869eea91ff..bb8fdf8498 100644
--- a/src/rules/consistent-type-specifier-style.js
+++ b/src/rules/consistent-type-specifier-style.js
@@ -7,9 +7,9 @@ function isComma(token) {
 function removeSpecifiers(fixes, fixer, sourceCode, specifiers) {
   for (const specifier of specifiers) {
     // remove the trailing comma
-    const comma = sourceCode.getTokenAfter(specifier, isComma);
-    if (comma) {
-      fixes.push(fixer.remove(comma));
+    const token = sourceCode.getTokenAfter(specifier);
+    if (token && isComma(token)) {
+      fixes.push(fixer.remove(token));
     }
     fixes.push(fixer.remove(specifier));
   }
diff --git a/tests/src/rules/consistent-type-specifier-style.js b/tests/src/rules/consistent-type-specifier-style.js
index 440ef3aff5..7799238c32 100644
--- a/tests/src/rules/consistent-type-specifier-style.js
+++ b/tests/src/rules/consistent-type-specifier-style.js
@@ -168,6 +168,33 @@ const COMMON_TESTS = {
         type: 'ImportSpecifier',
       }],
     },
+    // https://github.com/import-js/eslint-plugin-import/issues/2753
+    {
+      code: `\
+import { Component, type ComponentProps } from "package-1";
+import {
+  Component1,
+  Component2,
+  Component3,
+  Component4,
+  Component5,
+} from "package-2";`,
+      output: `\
+import { Component  } from "package-1";
+import type {ComponentProps} from "package-1";
+import {
+  Component1,
+  Component2,
+  Component3,
+  Component4,
+  Component5,
+} from "package-2";`,
+      options: ['prefer-top-level'],
+      errors: [{
+        message: 'Prefer using a top-level type-only import instead of inline type specifiers.',
+        type: 'ImportSpecifier',
+      }],
+    },
 
     //
     // prefer-inline

From 6be042b559aecc50f3a5313f20023a2cc4879541 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 7 Apr 2023 22:22:40 -0700
Subject: [PATCH 572/767] [Tests] `no-extraneous-dependencies`: add passing
 test

Closes #2718
---
 tests/src/rules/no-extraneous-dependencies.js | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index c1018a9149..8815f63cd8 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -475,5 +475,14 @@ typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', r
         message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
       }],
     }),
+    test({
+      code: `import type { Foo } from 'not-a-dependency'`,
+      options: [{ includeTypes: true }],
+      filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      parser: parsers.BABEL_OLD,
+      errors: [{
+        message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
+      }],
+    }),
   ],
 });

From d2b10aec006d04680c8b36fbd4e4e325376a73c0 Mon Sep 17 00:00:00 2001
From: xM8WVqaG <44505331+xM8WVqaG@users.noreply.github.com>
Date: Sat, 25 Mar 2023 14:49:48 +0000
Subject: [PATCH 573/767] [Docs] `extensions`: reference node ESM behavior

This behavior largely didn't change despite the functionality becoming more widely adopted. Even though the document assumes CJS, It's probably worth including at least a footnote about the resolver behaving differently for ESM.

See: https://github.com/import-js/eslint-plugin-import/issues/2043
---
 CHANGELOG.md             | 3 +++
 docs/rules/extensions.md | 4 +++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1866819b09..d10ceef814 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
 - [Docs] [`group-exports`]: fix syntax highlighting ([#2699], thanks [@devinrhode2])
+- [Docs] [`extensions`]: reference node ESM behavior ([#2748], thanks [@xM8WVqaG])
 
 ## [2.27.5] - 2023-01-16
 
@@ -1067,6 +1068,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2754]: https://github.com/import-js/eslint-plugin-import/pull/2754
+[#2748]: https://github.com/import-js/eslint-plugin-import/pull/2748
 [#2699]: https://github.com/import-js/eslint-plugin-import/pull/2699
 [#2664]: https://github.com/import-js/eslint-plugin-import/pull/2664
 [#2613]: https://github.com/import-js/eslint-plugin-import/pull/2613
@@ -1853,6 +1855,7 @@ for info on changes for earlier releases.
 [@wKich]: https://github.com/wKich
 [@wschurman]: https://github.com/wschurman
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
+[@xM8WVqaG]: https://github.com/xM8WVqaG
 [@xpl]: https://github.com/xpl
 [@yordis]: https://github.com/yordis
 [@zloirock]: https://github.com/zloirock
diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md
index 9e78b8c70f..df4f341287 100644
--- a/docs/rules/extensions.md
+++ b/docs/rules/extensions.md
@@ -2,7 +2,7 @@
 
 <!-- end auto-generated rule header -->
 
-Some file resolve algorithms allow you to omit the file extension within the import source path. For example the `node` resolver can resolve `./foo/bar` to the absolute path `/User/someone/foo/bar.js` because the `.js` extension is resolved automatically by default. Depending on the resolver you can configure more extensions to get resolved automatically.
+Some file resolve algorithms allow you to omit the file extension within the import source path. For example the `node` resolver (which does not yet support ESM/`import`) can resolve `./foo/bar` to the absolute path `/User/someone/foo/bar.js` because the `.js` extension is resolved automatically by default in CJS. Depending on the resolver you can configure more extensions to get resolved automatically.
 
 In order to provide a consistent use of file extensions across your code base, this rule can enforce or disallow the use of certain file extensions.
 
@@ -170,3 +170,5 @@ import foo from '@/foo';
 ## When Not To Use It
 
 If you are not concerned about a consistent usage of file extension.
+
+In the future, when this rule supports native node ESM resolution, and the plugin is configured to use native rather than transpiled ESM (a config option that is not yet available) - setting this to `always` will have no effect.

From 6cb9616d3fcc07b98b9efe3256b457f9d44a11cf Mon Sep 17 00:00:00 2001
From: Lukas Eipert <git@leipert.io>
Date: Sat, 8 Apr 2023 15:18:37 +0200
Subject: [PATCH 574/767] [utils] [perf] Performance of fullResolve

While looking at a larger code base https://gitlab.com/gitlab-org/gitlab,
I've came to realize that `fullResolve` takes a lot of CPU cycles,
particularly the `hashObject` calls inside it.

I applied the following patch locally to see how often this is called and
how many unique hashes were produced:

```diff
diff --git a/utils/resolve.js b/utils/resolve.js
index 4a35c6a..3c28324 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -83,13 +83,28 @@ function relative(modulePath, sourceFile, settings) {
   return fullResolve(modulePath, sourceFile, settings).path;
 }

+let prevSettings = null;
+let nonEqualSettings = 0;
+let totalCalls = 0;
+let uniqueHashes = new Set();
 function fullResolve(modulePath, sourceFile, settings) {
   // check if this is a bonus core module
   const coreSet = new Set(settings['import/core-modules']);
   if (coreSet.has(modulePath)) return { found: true, path: null };

   const sourceDir = path.dirname(sourceFile);
-  const cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath;
+
+  totalCalls+=1;
+  const hash = hashObject(settings).digest('hex');
+
+  if(prevSettings !== settings){
+    uniqueHashes.add(hash);
+    prevSettings = settings;
+    nonEqualSettings+=1;
+    console.log(`fullResolve | Total calls:${totalCalls} | Non-Equal settings:${nonEqualSettings} | Unique hashes:${uniqueHashes.size} | dir:${sourceDir}`)
+  }
+
+  const cacheKey = sourceDir + hash + modulePath;

   const cacheSettings = ModuleCache.getSettings(settings);
```

For our code base, `fullResolve` is called more than 570 thousand times.
The simple in-equality `!==` code path is taken 1090 times.
Actually only _four_ unique hashes are produced, meaning we only have
four unique settings across our code base.

I assume that a full object equality comparison might not be needed,
and a simple object comparison with `!==` already would reduce the amount
of `hashObject` calls by 570x. This is what is implemented in this commit.

Time spend in `fullResolve` was reduced by ~38%:
- Before: 17% (19.10s) of our total execution time
- After: 11% (11.86s) of our total execution time

The effect might even be more pronounced on machines that are slower when
calculating `sha256` hashes or that have less memory, as the `hashObject`
method tends to create loads of small strings which need to be garbage
collected.
---
 utils/CHANGELOG.md |  5 +++++
 utils/resolve.js   | 10 +++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 72fa611a14..7d2057dec2 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Fixed
+- Improve performance of `fullResolve` for large projects ([#2755], thanks [@leipert])
+
 ## v2.7.4 - 2022-08-11
 
 ### Fixed
@@ -123,6 +126,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2755]: https://github.com/import-js/eslint-plugin-import/pull/2755
 [#2523]: https://github.com/import-js/eslint-plugin-import/pull/2523
 [#2431]: https://github.com/import-js/eslint-plugin-import/pull/2431
 [#2350]: https://github.com/import-js/eslint-plugin-import/issues/2350
@@ -160,6 +164,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@iamnapo]: https://github.com/iamnapo
 [@JounQin]: https://github.com/JounQin
 [@kaiyoma]: https://github.com/kaiyoma
+[@leipert]: https://github.com/leipert
 [@manuth]: https://github.com/manuth
 [@maxkomarychev]: https://github.com/maxkomarychev
 [@mgwalker]: https://github.com/mgwalker
diff --git a/utils/resolve.js b/utils/resolve.js
index 4a35c6a472..9d9dfa8439 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -83,13 +83,21 @@ function relative(modulePath, sourceFile, settings) {
   return fullResolve(modulePath, sourceFile, settings).path;
 }
 
+let prevSettings = null;
+let memoizedHash = '';
 function fullResolve(modulePath, sourceFile, settings) {
   // check if this is a bonus core module
   const coreSet = new Set(settings['import/core-modules']);
   if (coreSet.has(modulePath)) return { found: true, path: null };
 
   const sourceDir = path.dirname(sourceFile);
-  const cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath;
+
+  if (prevSettings !== settings) {
+    memoizedHash = hashObject(settings).digest('hex');
+    prevSettings = settings;
+  }
+
+  const cacheKey = sourceDir + memoizedHash + modulePath;
 
   const cacheSettings = ModuleCache.getSettings(settings);
 

From 3a22c3b05fa22c5c0e9db639007d79ff730678e8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 11 Apr 2023 16:00:25 -0700
Subject: [PATCH 575/767] Revert "[Fix] TypeScript config: fix resolver
 extension settings"

This reverts commit 808d504bffe29286a885475a424562969e9d4879, per https://github.com/import-js/eslint-plugin-import/commit/808d504bffe29286a885475a424562969e9d4879#commitcomment-107093802
---
 CHANGELOG.md         | 1 -
 config/typescript.js | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d10ceef814..01ab3f0819 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,6 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - [`no-duplicates`]: remove duplicate identifiers in duplicate imports ([#2577], thanks [@joe-matsec])
-- TypeScript config: fix resolver extension settings (thanks [@gajus])
 - [`consistent-type-specifier-style`]: fix accidental removal of comma in certain cases ([#2754], thanks [@bradzacher])
 
 ### Changed
diff --git a/config/typescript.js b/config/typescript.js
index 59c3c42dae..ed03fb3f6c 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -16,7 +16,7 @@ module.exports = {
       '@typescript-eslint/parser': ['.ts', '.tsx'],
     },
     'import/resolver': {
-      'typescript': {
+      'node': {
         'extensions': allExtensions,
       },
     },

From dc596a29bb3fe705396acc64f38d891b2ce52669 Mon Sep 17 00:00:00 2001
From: Daniel Martens <danielmartens@protonmail.ch>
Date: Fri, 10 Feb 2023 20:57:33 +0100
Subject: [PATCH 576/767] [utils] [new] `parse`: support flat config

---
 tests/src/core/parse.js              | 59 ++++++++++++++++++++++++++++
 tests/src/rules/no-unused-modules.js | 22 +++++++++++
 utils/parse.js                       | 38 ++++++++++++------
 3 files changed, 108 insertions(+), 11 deletions(-)

diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index 407070aa2f..4ab8370ed2 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -69,4 +69,63 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
     expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, parserOptions })).not.to.throw(Error);
     expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
   });
+
+  it('throws on invalid languageOptions', function () {
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: null, languageOptions: null })).to.throw(Error);
+  });
+
+  it('throws on non-object languageOptions.parser', function () {
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: null, languageOptions: { parser: 'espree' } })).to.throw(Error);
+  });
+
+  it('throws on null languageOptions.parser', function () {
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: null, languageOptions: { parser: null } })).to.throw(Error);
+  });
+
+  it('throws on empty languageOptions.parser', function () {
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: null, languageOptions: { parser: {} } })).to.throw(Error);
+  });
+
+  it('throws on non-function languageOptions.parser.parse', function () {
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: null, languageOptions: { parser: { parse: 'espree' } } })).to.throw(Error);
+  });
+
+  it('throws on non-function languageOptions.parser.parse', function () {
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: null, languageOptions: { parser: { parseForESLint: 'espree' } } })).to.throw(Error);
+  });
+
+  it('requires only one of the parse methods', function () {
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: null, languageOptions: { parser: { parseForESLint: () => ({ ast: {} }) } } })).not.to.throw(Error);
+  });
+
+  it('uses parse from languageOptions.parser', function () {
+    const parseSpy = sinon.spy();
+    expect(parse.bind(null, path, content, { settings: {}, languageOptions: { parser: { parse: parseSpy } } })).not.to.throw(Error);
+    expect(parseSpy.callCount, 'passed parser to be called once').to.equal(1);
+  });
+
+  it('uses parseForESLint from languageOptions.parser', function () {
+    const parseSpy = sinon.spy(() => ({ ast: {} }));
+    expect(parse.bind(null, path, content, { settings: {}, languageOptions: { parser: { parseForESLint: parseSpy } } })).not.to.throw(Error);
+    expect(parseSpy.callCount, 'passed parser to be called once').to.equal(1);
+  });
+
+  it('prefers parsers specified in the settings over languageOptions.parser', () => {
+    const parseSpy = sinon.spy();
+    parseStubParser.parse = parseSpy;
+    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, languageOptions: { parser: { parse() {} } } })).not.to.throw(Error);
+    expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
+  });
+
+  it('ignores parser options from language options set to null', () => {
+    const parseSpy = sinon.spy();
+    parseStubParser.parse = parseSpy;
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: 'espree', languageOptions: { parserOptions: null }, parserOptions: { sourceType: 'module', ecmaVersion: 2015, ecmaFeatures: { jsx: true } } })).not.to.throw(Error);
+  });
+
+  it('prefers languageOptions.parserOptions over parserOptions', () => {
+    const parseSpy = sinon.spy();
+    parseStubParser.parse = parseSpy;
+    expect(parse.bind(null, path, content, { settings: {}, parserPath: 'espree', languageOptions: { parserOptions: { sourceType: 'module', ecmaVersion: 2015, ecmaFeatures: { jsx: true } } }, parserOptions: { sourceType: 'script' } })).not.to.throw(Error);
+  });
 });
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index de169c65da..87714b599b 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -7,6 +7,11 @@ import fs from 'fs';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
+let FlatRuleTester;
+try {
+  ({ FlatRuleTester } = require('eslint/use-at-your-own-risk'));
+} catch (e) { /**/ }
+
 // TODO: figure out why these tests fail in eslint 4 and 5
 const isESLint4TODO = semver.satisfies(eslintPkg.version, '^4 || ^5');
 
@@ -1371,3 +1376,20 @@ describe('parser ignores prefixes like BOM and hashbang', () => {
     invalid: [],
   });
 });
+
+describe('supports flat eslint', { skip: !FlatRuleTester }, () => {
+  const flatRuleTester = new FlatRuleTester();
+  flatRuleTester.run('no-unused-modules', rule, {
+    valid: [{
+      options: unusedExportsOptions,
+      code: 'import { o2 } from "./file-o";export default () => 12',
+      filename: testFilePath('./no-unused-modules/file-a.js'),
+    }],
+    invalid: [{
+      options: unusedExportsOptions,
+      code: 'export default () => 13',
+      filename: testFilePath('./no-unused-modules/file-f.js'),
+      errors: [error(`exported declaration 'default' not used within other modules`)],
+    }],
+  });
+});
diff --git a/utils/parse.js b/utils/parse.js
index ac728ec5b2..dd0746aaa7 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -23,10 +23,10 @@ function keysFromParser(parserPath, parserInstance, parsedResult) {
   if (parsedResult && parsedResult.visitorKeys) {
     return parsedResult.visitorKeys;
   }
-  if (/.*espree.*/.test(parserPath)) {
+  if (typeof parserPath === 'string' && /.*espree.*/.test(parserPath)) {
     return parserInstance.VisitorKeys;
   }
-  if (/.*babel-eslint.*/.test(parserPath)) {
+  if (typeof parserPath === 'string' && /.*babel-eslint.*/.test(parserPath)) {
     return getBabelEslintVisitorKeys(parserPath);
   }
   return null;
@@ -51,13 +51,13 @@ function transformHashbang(text) {
 }
 
 exports.default = function parse(path, content, context) {
-
   if (context == null) throw new Error('need context to parse properly');
 
-  let parserOptions = context.parserOptions;
-  const parserPath = getParserPath(path, context);
+  // ESLint in "flat" mode only sets context.languageOptions.parserOptions
+  let parserOptions = (context.languageOptions && context.languageOptions.parserOptions) || context.parserOptions;
+  const parserOrPath = getParser(path, context);
 
-  if (!parserPath) throw new Error('parserPath is required!');
+  if (!parserOrPath) throw new Error('parserPath or languageOptions.parser is required!');
 
   // hack: espree blows up with frozen options
   parserOptions = Object.assign({}, parserOptions);
@@ -84,7 +84,7 @@ exports.default = function parse(path, content, context) {
   delete parserOptions.projects;
 
   // require the parser relative to the main module (i.e., ESLint)
-  const parser = moduleRequire(parserPath);
+  const parser = typeof parserOrPath === 'string' ? moduleRequire(parserOrPath) : parserOrPath;
 
   // replicate bom strip and hashbang transform of ESLint
   // https://github.com/eslint/eslint/blob/b93af98b3c417225a027cabc964c38e779adb945/lib/linter/linter.js#L779
@@ -95,7 +95,7 @@ exports.default = function parse(path, content, context) {
     try {
       const parserRaw = parser.parseForESLint(content, parserOptions);
       ast = parserRaw.ast;
-      return makeParseReturn(ast, keysFromParser(parserPath, parser, parserRaw));
+      return makeParseReturn(ast, keysFromParser(parserOrPath, parser, parserRaw));
     } catch (e) {
       console.warn();
       console.warn('Error while parsing ' + parserOptions.filePath);
@@ -104,18 +104,34 @@ exports.default = function parse(path, content, context) {
     if (!ast || typeof ast !== 'object') {
       console.warn(
         '`parseForESLint` from parser `' +
-          parserPath +
+          (typeof parserOrPath === 'string' ? parserOrPath : '`context.languageOptions.parser`') + // Can only be invalid for custom parser per imports/parser
           '` is invalid and will just be ignored'
       );
     } else {
-      return makeParseReturn(ast, keysFromParser(parserPath, parser, undefined));
+      return makeParseReturn(ast, keysFromParser(parserOrPath, parser, undefined));
     }
   }
 
   const ast = parser.parse(content, parserOptions);
-  return makeParseReturn(ast, keysFromParser(parserPath, parser, undefined));
+  return makeParseReturn(ast, keysFromParser(parserOrPath, parser, undefined));
 };
 
+function getParser(path, context) {
+  const parserPath = getParserPath(path, context);
+  if (parserPath) {
+    return parserPath;
+  }
+  const isFlat = context.languageOptions
+    && context.languageOptions.parser
+    && typeof context.languageOptions.parser !== 'string'
+    && (
+      typeof context.languageOptions.parser.parse === 'function'
+      || typeof context.languageOptions.parser.parseForESLint === 'function'
+    );
+
+  return isFlat ? context.languageOptions.parser : null;
+}
+
 function getParserPath(path, context) {
   const parsers = context.settings['import/parsers'];
   if (parsers != null) {

From 0ae35c0efc02422f577bc0336ce9cef14b8339a0 Mon Sep 17 00:00:00 2001
From: Lukas Eipert <git@leipert.io>
Date: Wed, 12 Apr 2023 14:33:48 +0200
Subject: [PATCH 577/767] [perf] `ExportMap`: Improve ExportMap.for performance
 on larger codebases

While looking at a larger code base https://gitlab.com/gitlab-org/gitlab,
`ExportMap.for` seems to take a significant amount of time. More than
half of it is spend on calculating hashes with `hashObject`.

Digging a little deeper, it seems like we are calling it around 500
thousand times. Each iteration calculates the hash of a context object.
This context object is created inside of the `childContext` function and
consists of four parts:
- `settings` -> an Object itself
- `parserOptions` -> an Object itself
- `parserPath` -> a String
- `path` -> a String.

Interestingly `settings`, `parserOptions` and `parserPath` rarely do
change for us, so calculating their hashes on every iteration seems
unnecessary. `hashObject` recursively calculates the hashes of each
key / value pair.

So instead of doing:

```js
cacheKey = hashObject({settings, parserOptions, parserPath, path})
```
We could also do:
```js
cacheKey = parserPath +
  hashObject(parserOptions) +
  hashObject(settings) +
  path
```

This would be just as stable as before, although resulting in longer
cache keys. `parserPath` and `path` would not need to be hashed,
because they are strings and a single character change in them would
result in a different cache key.

Furthermore we can memoize the hashes of `parserOptions` and
`settings`, in case they didn't change compared. The equality is
checked with a simple `JSON.stringify`.

We move this `cacheKey` calculation to `childContext`, adding the
cache key to the `context` object. This way, we can fall back to the
old calculation inside of `ExportMap.for`, as it is a public
interface which consumers might be using.

In our code base the results speak for itself:
- 51.59s spent in `ExportMap.for`, 0ms spent in `childContext`.
    - 16.89s is spent in node:crypto/hash `update` (overall)
- 41.02s spent in `ExportMap.for, 1.91s spent in `childContext`.
    - Almost no time spent in `hashObject`, actually all calls in
      our flame graph come from other code paths
    - 7.86s is spent in node:crypto/hash `update` (overall)

So on this machine, and project, we are cutting the execution time
of `ExportMap.for` in half. On machines, which are hashing slower,
the effect might be more pronounced. Similarly machines with less
memory, as the `hashObject` function creates a lot of tiny strings.

One side-effect here could be, that the memoization is in-efficient
if the `settings` or `parserOptions` change often. (I cannot think
of such a scenario, but I am not that versed in the use cases of
this plugin.) But even then, the overhead should mainly be the
`JSON.stringify`.
---
 CHANGELOG.md     |  3 +++
 src/ExportMap.js | 21 +++++++++++++++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 01ab3f0819..bbfaa0fb98 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [`no-duplicates`]: remove duplicate identifiers in duplicate imports ([#2577], thanks [@joe-matsec])
 - [`consistent-type-specifier-style`]: fix accidental removal of comma in certain cases ([#2754], thanks [@bradzacher])
+- [Perf] `ExportMap`: Improve `ExportMap.for` performance on larger codebases ([#2756], thanks [@leipert])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
@@ -1066,6 +1067,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2756]: https://github.com/import-js/eslint-plugin-import/pull/2756
 [#2754]: https://github.com/import-js/eslint-plugin-import/pull/2754
 [#2748]: https://github.com/import-js/eslint-plugin-import/pull/2748
 [#2699]: https://github.com/import-js/eslint-plugin-import/pull/2699
@@ -1737,6 +1739,7 @@ for info on changes for earlier releases.
 [@kylemh]: https://github.com/kylemh
 [@laysent]: https://github.com/laysent
 [@le0nik]: https://github.com/le0nik
+[@leipert]: https://github.com/leipert
 [@lemonmade]: https://github.com/lemonmade
 [@lencioni]: https://github.com/lencioni
 [@leonardodino]: https://github.com/leonardodino
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 7b8c883143..d31375c83d 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -305,7 +305,7 @@ ExportMap.get = function (source, context) {
 ExportMap.for = function (context) {
   const { path } = context;
 
-  const cacheKey = hashObject(context).digest('hex');
+  const cacheKey = context.cacheKey || hashObject(context).digest('hex');
   let exportMap = exportCache.get(cacheKey);
 
   // return cached ignore
@@ -559,7 +559,7 @@ ExportMap.parse = function (path, content, context) {
       if (tsConfigInfo.tsConfigPath !== undefined) {
         // Projects not using TypeScript won't have `typescript` installed.
         if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
-  
+
         const configFile = ts.readConfigFile(tsConfigInfo.tsConfigPath, ts.sys.readFile);
         return ts.parseJsonConfigFileContent(
           configFile.config,
@@ -781,12 +781,29 @@ export function recursivePatternCapture(pattern, callback) {
   }
 }
 
+let parserOptionsHash = '';
+let prevParserOptions = '';
+let settingsHash = '';
+let prevSettings = '';
 /**
  * don't hold full context object in memory, just grab what we need.
+ * also calculate a cacheKey, where parts of the cacheKey hash are memoized
  */
 function childContext(path, context) {
   const { settings, parserOptions, parserPath } = context;
+
+  if (JSON.stringify(settings) !== prevSettings) {
+    settingsHash = hashObject({ settings }).digest('hex');
+    prevSettings = JSON.stringify(settings);
+  }
+
+  if (JSON.stringify(parserOptions) !== prevParserOptions) {
+    parserOptionsHash = hashObject({ parserOptions }).digest('hex');
+    prevParserOptions = JSON.stringify(parserOptions);
+  }
+
   return {
+    cacheKey: String(parserPath) + parserOptionsHash + settingsHash + String(path),
     settings,
     parserOptions,
     parserPath,

From 97995673e02c3523559a4ae0792e1792d23064ec Mon Sep 17 00:00:00 2001
From: Andreas Deuschlinger <andreas.deuschlinger@gmail.com>
Date: Tue, 14 Mar 2023 22:50:50 +0100
Subject: [PATCH 578/767] [Fix] `no-extraneous-dependencies`/TypeScript: do not
 error when importing inline type from dev dependencies

---
 CHANGELOG.md                                  |  3 ++
 docs/rules/no-extraneous-dependencies.md      |  1 +
 src/rules/no-extraneous-dependencies.js       |  7 ++++-
 tests/src/rules/no-extraneous-dependencies.js | 30 +++++++++++++++++--
 4 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bbfaa0fb98..fe7f6771b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-duplicates`]: remove duplicate identifiers in duplicate imports ([#2577], thanks [@joe-matsec])
 - [`consistent-type-specifier-style`]: fix accidental removal of comma in certain cases ([#2754], thanks [@bradzacher])
 - [Perf] `ExportMap`: Improve `ExportMap.for` performance on larger codebases ([#2756], thanks [@leipert])
+- [`no-extraneous-dependencies`]/TypeScript: do not error when importing inline type from dev dependencies ([#1820], thanks [@andyogo])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
@@ -1070,6 +1071,7 @@ for info on changes for earlier releases.
 [#2756]: https://github.com/import-js/eslint-plugin-import/pull/2756
 [#2754]: https://github.com/import-js/eslint-plugin-import/pull/2754
 [#2748]: https://github.com/import-js/eslint-plugin-import/pull/2748
+[#2735]: https://github.com/import-js/eslint-plugin-import/pull/2735
 [#2699]: https://github.com/import-js/eslint-plugin-import/pull/2699
 [#2664]: https://github.com/import-js/eslint-plugin-import/pull/2664
 [#2613]: https://github.com/import-js/eslint-plugin-import/pull/2613
@@ -1625,6 +1627,7 @@ for info on changes for earlier releases.
 [@alexgorbatchev]: https://github.com/alexgorbatchev
 [@andreubotella]: https://github.com/andreubotella
 [@AndrewLeedham]: https://github.com/AndrewLeedham
+[@andyogo]: https://github.com/andyogo
 [@aravindet]: https://github.com/aravindet
 [@arvigeus]: https://github.com/arvigeus
 [@asapach]: https://github.com/asapach
diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index 68cd4b154f..660875d1da 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -12,6 +12,7 @@ Modules have to be installed for this rule to work.
 This rule supports the following options:
 
 `devDependencies`: If set to `false`, then the rule will show an error when `devDependencies` are imported. Defaults to `true`.
+Type imports are ignored by default.
 
 `optionalDependencies`: If set to `false`, then the rule will show an error when `optionalDependencies` are imported. Defaults to `true`.
 
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index d6437c2fd1..a149ca6599 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -178,7 +178,12 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types unless option is enabled
   if (
     !depsOptions.verifyTypeImports &&
-    (node.importKind === 'type' || node.importKind === 'typeof')
+    (node.importKind === 'type' || node.importKind === 'typeof' ||
+    (
+      Array.isArray(node.specifiers) &&
+      node.specifiers.length &&
+      node.specifiers.every((specifier) => specifier.importKind === 'type' || specifier.importKind === 'typeof'))
+    )
   ) {
     return;
   }
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 8815f63cd8..84aa8bb35d 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -438,7 +438,7 @@ describe('TypeScript', () => {
 
           test(Object.assign({
             code: 'import type T from "a";',
-            options: [{ 
+            options: [{
               packageDir: packageDirWithTypescriptDevDependencies,
               devDependencies: false,
               includeTypes: true,
@@ -464,6 +464,16 @@ typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', r
       filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
       parser: parsers.BABEL_OLD,
     }),
+    test({
+      code: 'import { type MyType } from "not-a-dependency";',
+      filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      parser: parsers.BABEL_OLD,
+    }),
+    test({
+      code: 'import { type MyType, type OtherType } from "not-a-dependency";',
+      filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      parser: parsers.BABEL_OLD,
+    }),
   ],
   invalid: [
     test({
@@ -476,7 +486,7 @@ typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', r
       }],
     }),
     test({
-      code: `import type { Foo } from 'not-a-dependency'`,
+      code: `import type { Foo } from 'not-a-dependency';`,
       options: [{ includeTypes: true }],
       filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
       parser: parsers.BABEL_OLD,
@@ -484,5 +494,21 @@ typescriptRuleTester.run('no-extraneous-dependencies typescript type imports', r
         message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
       }],
     }),
+    test({
+      code: 'import Foo, { type MyType } from "not-a-dependency";',
+      filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      parser: parsers.BABEL_OLD,
+      errors: [{
+        message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
+      }],
+    }),
+    test({
+      code: 'import { type MyType, Foo } from "not-a-dependency";',
+      filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'),
+      parser: parsers.BABEL_OLD,
+      errors: [{
+        message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
+      }],
+    }),
   ],
 });

From 8c155baaca39dc78c5a3a63ff1bdd53b58f343e0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 Apr 2023 16:20:26 -0700
Subject: [PATCH 579/767] [eslint] tighten up rules

---
 .eslintrc                                     |  95 ++++++-
 config/typescript.js                          |   4 +-
 memo-parser/index.js                          |   4 +-
 resolvers/node/index.js                       |   9 +-
 resolvers/node/test/packageMains.js           |   1 -
 resolvers/node/test/paths.js                  |   2 -
 resolvers/webpack/index.js                    |  20 +-
 .../config-extensions/webpack.config.babel.js |   4 +-
 resolvers/webpack/test/extensions.js          |   1 -
 resolvers/webpack/test/fallback.js            |   1 -
 resolvers/webpack/test/loaders.js             |   1 -
 resolvers/webpack/test/packageMains.js        |   1 -
 resolvers/webpack/test/root.js                |   1 -
 scripts/testAll.js                            |   4 +-
 src/ExportMap.js                              | 254 +++++++++---------
 src/core/importType.js                        |  18 +-
 src/core/packagePath.js                       |   1 -
 src/core/staticRequire.js                     |  14 +-
 src/index.js                                  |  28 +-
 src/rules/consistent-type-specifier-style.js  |  36 +--
 src/rules/default.js                          |  10 +-
 src/rules/dynamic-import-chunkname.js         |   3 +-
 src/rules/export.js                           |  40 +--
 src/rules/exports-last.js                     |   6 +-
 src/rules/extensions.js                       |  18 +-
 src/rules/first.js                            |  35 +--
 src/rules/group-exports.js                    |  10 +-
 src/rules/imports-first.js                    |   7 +-
 src/rules/max-dependencies.js                 |  32 ++-
 src/rules/named.js                            |   8 +-
 src/rules/namespace.js                        |  68 ++---
 src/rules/newline-after-import.js             |  35 +--
 src/rules/no-absolute-path.js                 |   6 +-
 src/rules/no-amd.js                           |  13 +-
 src/rules/no-anonymous-default-export.js      |   6 +-
 src/rules/no-commonjs.js                      |  46 ++--
 src/rules/no-cycle.js                         |  44 +--
 src/rules/no-default-export.js                |   2 +-
 src/rules/no-deprecated.js                    |  75 +++---
 src/rules/no-duplicates.js                    |  65 +++--
 src/rules/no-dynamic-require.js               |  20 +-
 src/rules/no-empty-named-blocks.js            |  21 +-
 src/rules/no-extraneous-dependencies.js       |  94 +++----
 src/rules/no-import-module-exports.js         |  21 +-
 src/rules/no-internal-modules.js              |  34 +--
 src/rules/no-mutable-exports.js               |   4 +-
 src/rules/no-named-as-default-member.js       | 105 ++++----
 src/rules/no-named-as-default.js              |  18 +-
 src/rules/no-named-default.js                 |   2 +-
 src/rules/no-named-export.js                  |   2 +-
 src/rules/no-namespace.js                     |  23 +-
 src/rules/no-nodejs-modules.js                |   2 +-
 src/rules/no-relative-packages.js             |   2 +-
 src/rules/no-relative-parent-imports.js       |   7 +-
 src/rules/no-restricted-paths.js              |  20 +-
 src/rules/no-unassigned-import.js             |  37 +--
 src/rules/no-unused-modules.js                | 117 ++++----
 src/rules/no-useless-path-segments.js         |   4 +-
 src/rules/no-webpack-loader-syntax.js         |   4 +-
 src/rules/order.js                            | 101 ++++---
 src/rules/prefer-default-export.js            |  24 +-
 tests/src/cli.js                              |  14 +-
 tests/src/core/getExports.js                  |  55 ++--
 tests/src/core/hash.js                        |   2 +-
 tests/src/core/parse.js                       |  16 +-
 tests/src/core/resolve.js                     | 207 ++++++++------
 tests/src/package.js                          |   6 +-
 tests/src/rules/dynamic-import-chunkname.js   |   2 +-
 tests/src/rules/export.js                     |   2 -
 tests/src/rules/exports-last.js               |   2 +-
 tests/src/rules/extensions.js                 |  25 +-
 tests/src/rules/first.js                      |   2 +-
 tests/src/rules/named.js                      |  16 +-
 tests/src/rules/namespace.js                  |  69 ++---
 tests/src/rules/newline-after-import.js       |  50 ++--
 tests/src/rules/no-commonjs.js                |  16 +-
 tests/src/rules/no-cycle.js                   |   4 +-
 tests/src/rules/no-deprecated.js              |  13 +-
 tests/src/rules/no-duplicates.js              |  24 +-
 tests/src/rules/no-dynamic-require.js         |  14 +-
 tests/src/rules/no-empty-named-blocks.js      |   3 +-
 tests/src/rules/no-extraneous-dependencies.js |  26 +-
 tests/src/rules/no-import-module-exports.js   |   3 +-
 tests/src/rules/no-named-as-default-member.js |  25 +-
 tests/src/rules/no-nodejs-modules.js          |   4 +-
 tests/src/rules/no-relative-parent-imports.js |   2 +-
 tests/src/rules/no-restricted-paths.js        |   5 +-
 tests/src/rules/no-unassigned-import.js       |  30 +--
 tests/src/rules/no-unresolved.js              |  23 +-
 tests/src/rules/no-unused-modules.js          |   7 +-
 tests/src/rules/no-webpack-loader-syntax.js   |   8 +-
 tests/src/rules/order.js                      | 182 ++++++-------
 tests/src/rules/prefer-default-export.js      |   6 +-
 tests/src/utils.js                            |  12 +-
 utils/ModuleCache.js                          |   7 +-
 utils/declaredScope.js                        |   5 +-
 utils/hash.js                                 |  11 +-
 utils/ignore.js                               |   7 +-
 utils/module-require.js                       |   1 +
 utils/moduleVisitor.js                        |  88 +++---
 utils/parse.js                                |  16 +-
 utils/pkgUp.js                                |   9 +-
 utils/readPkgUp.js                            |   9 +-
 utils/resolve.js                              |  53 ++--
 utils/unambiguous.js                          |   3 +-
 utils/visit.js                                |   1 +
 106 files changed, 1405 insertions(+), 1370 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 1c41cb71bd..709a474484 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -12,12 +12,18 @@
     "env": {
         "node": true,
         "es6": true,
+        "es2017": true,
     },
     "parserOptions": {
         "sourceType": "module",
         "ecmaVersion": 2020,
     },
     "rules": {
+        "arrow-body-style": [2, "as-needed"],
+        "arrow-parens": [2, "always"],
+        "arrow-spacing": [2, { "before": true, "after": true }],
+        "block-spacing": [2, "always"],
+        "brace-style": [2, "1tbs", { "allowSingleLine": true }],
         "comma-dangle": ["error", {
             "arrays": "always-multiline",
             "objects": "always-multiline",
@@ -25,12 +31,47 @@
             "exports": "always-multiline",
             "functions": "always-multiline",
         }],
+        "comma-spacing": [2, { "before": false, "after": true }],
         "comma-style": [2, "last"],
-        "curly": [2, "multi-line"],
+        "computed-property-spacing": [2, "never"],
+        "curly": [2, "all"],
+        "default-case": [2, { "commentPattern": "(?:)" }],
+        "default-case-last": [2],
+        "default-param-last": [2],
+        "dot-location": [2, "property"],
+        "dot-notation": [2, { "allowKeywords": true, "allowPattern": "throws" }],
         "eol-last": [2, "always"],
         "eqeqeq": [2, "allow-null"],
-        "func-call-spacing": 2,
-        "indent": [2, 2],
+        "for-direction": [2],
+        "function-call-argument-newline": [2, "consistent"],
+        "func-call-spacing": [2, "never"],
+        "implicit-arrow-linebreak": [2, "beside"],
+        "indent": [2, 2, {
+            "SwitchCase": 1,
+            "VariableDeclarator": 1,
+            "outerIIFEBody": 1,
+            "FunctionDeclaration": {
+                "parameters": 1,
+                "body": 1
+            },
+            "FunctionExpression": {
+                "parameters": 1,
+                "body": 1
+            },
+            "CallExpression": {
+                "arguments": 1
+            },
+            "ArrayExpression": 1,
+            "ObjectExpression": 1,
+            "ImportDeclaration": 1,
+            "flatTernaryExpressions": false,
+        }],
+        "jsx-quotes": [2, "prefer-double"],
+        "key-spacing": [2, {
+            "beforeColon": false,
+            "afterColon": true,
+            "mode": "strict",
+        }],
         "keyword-spacing": ["error", {
           "before": true,
           "after": true,
@@ -40,27 +81,68 @@
             "case": { "after": true }
           }
         }],
+        "linebreak-style": [2, "unix"],
+        "lines-around-directive": [2, {
+            "before": "always",
+            "after": "always",
+        }],
         "max-len": 0,
+        "new-parens": 2,
+        "no-array-constructor": 2,
+        "no-compare-neg-zero": 2,
         "no-cond-assign": [2, "always"],
+        "no-extra-parens": 2,
+        "no-multiple-empty-lines": [2, { "max": 1, "maxEOF": 1, "maxBOF": 0 }],
         "no-return-assign": [2, "always"],
+        "no-trailing-spaces": 2,
         "no-var": 2,
         "object-curly-spacing": [2, "always"],
         "object-shorthand": ["error", "always", {
             "ignoreConstructors": false,
-            "avoidQuotes": true,
+            "avoidQuotes": false,
+            "avoidExplicitReturnArrows": true,
         }],
         "one-var": [2, "never"],
+        "operator-linebreak": [2, "none", {
+            "overrides": {
+              "?": "before",
+              ":": "before",
+              "&&": "before",
+              "||": "before",
+            },
+        }],
         "prefer-const": 2,
+        "prefer-object-spread": 2,
+        "prefer-rest-params": 2,
+        "prefer-template": 2,
+        "quote-props": [2, "as-needed", { "keywords": false }],
         "quotes": [2, "single", {
             "allowTemplateLiterals": true,
             "avoidEscape": true,
         }],
+        "rest-spread-spacing": [2, "never"],
         "semi": [2, "always"],
+        "semi-spacing": [2, { "before": false, "after": true }],
+        "semi-style": [2, "last"],
+        "space-before-blocks": [2, { "functions": "always", "keywords": "always", "classes": "always" }],
         "space-before-function-paren": ["error", {
             "anonymous": "always",
             "named": "never",
             "asyncArrow": "always",
         }],
+        "space-in-parens": [2, "never"],
+        "space-infix-ops": [2],
+        "space-unary-ops": [2, { "words": true, "nonwords": false }],
+        "switch-colon-spacing": [2, { "after": true, "before": false }],
+        "template-curly-spacing": [2, "never"],
+        "template-tag-spacing": [2, "never"],
+        "unicode-bom": [2, "never"],
+        "use-isnan": [2, { "enforceForSwitchCase": true }],
+        "valid-typeof": [2],
+        "wrap-iife": [2, "outside", { "functionPrototypeMethods": true }],
+        "wrap-regex": [2],
+        "yield-star-spacing": [2, { "before": false, "after": true }],
+        "yoda": [2, "never", { "exceptRange": true, "onlyEquality": false }],
 
         "eslint-plugin/consistent-output": [
             "error",
@@ -116,6 +198,9 @@
             "files": "resolvers/webpack/**",
             "rules": {
                 "no-console": 1,
+                "prefer-template": 0,
+                "prefer-object-spread": 0,
+                "prefer-rest-params": 0,
             },
             "env": {
                 "es6": true,
@@ -143,6 +228,8 @@
                     "exports": "always-multiline",
                     "functions": "never"
                 }],
+                "prefer-object-spread": "off",
+                "prefer-template": "off",
                 "no-console": 1,
             },
         },
diff --git a/config/typescript.js b/config/typescript.js
index ed03fb3f6c..9fd789dbf7 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -16,8 +16,8 @@ module.exports = {
       '@typescript-eslint/parser': ['.ts', '.tsx'],
     },
     'import/resolver': {
-      'node': {
-        'extensions': allExtensions,
+      node: {
+        extensions: allExtensions,
       },
     },
   },
diff --git a/memo-parser/index.js b/memo-parser/index.js
index de558ffa3e..7868b7e953 100644
--- a/memo-parser/index.js
+++ b/memo-parser/index.js
@@ -17,7 +17,7 @@ const parserOptions = {
 };
 
 exports.parse = function parse(content, options) {
-  options = Object.assign({}, options, parserOptions);
+  options = { ...options, ...parserOptions };
 
   if (!options.filePath) {
     throw new Error('no file path provided!');
@@ -30,7 +30,7 @@ exports.parse = function parse(content, options) {
   const key = keyHash.digest('hex');
 
   let ast = cache.get(key);
-  if (ast != null) return ast;
+  if (ast != null) { return ast; }
 
   const realParser = moduleRequire(options.parser);
 
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index ac478ef029..d382bca43d 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -29,17 +29,14 @@ exports.resolve = function (source, file, config) {
 };
 
 function opts(file, config, packageFilter) {
-  return Object.assign({
-    // more closely matches Node (#333)
+  return { // more closely matches Node (#333)
     // plus 'mjs' for native modules! (#939)
     extensions: ['.mjs', '.js', '.json', '.node'],
-  },
-  config,
-  {
+    ...config,
     // path.resolve will handle paths relative to CWD
     basedir: path.dirname(path.resolve(file)),
     packageFilter,
-  });
+  };
 }
 
 function identity(x) { return x; }
diff --git a/resolvers/node/test/packageMains.js b/resolvers/node/test/packageMains.js
index caac6221ca..170b10e1a1 100644
--- a/resolvers/node/test/packageMains.js
+++ b/resolvers/node/test/packageMains.js
@@ -8,7 +8,6 @@ const resolver = require('../');
 
 const file = path.join(__dirname, 'package-mains', 'dummy.js');
 
-
 describe('packageMains', function () {
   it('captures module', function () {
     expect(resolver.resolve('./module', file)).property('path')
diff --git a/resolvers/node/test/paths.js b/resolvers/node/test/paths.js
index 1c42b46167..e6ffdafcd9 100644
--- a/resolvers/node/test/paths.js
+++ b/resolvers/node/test/paths.js
@@ -11,7 +11,6 @@ describe('paths', function () {
   });
 });
 
-
 describe('core', function () {
   it('returns found, but null path, for core Node modules', function () {
     const resolved = node.resolve('fs', './test/file.js');
@@ -20,7 +19,6 @@ describe('core', function () {
   });
 });
 
-
 describe('default options', function () {
 
   it('finds .json files', function () {
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index b569d53224..8eb2db5ad6 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -75,7 +75,7 @@ exports.resolve = function (source, file, settings) {
     if (!configPath || !path.isAbsolute(configPath)) {
       // if not, find ancestral package.json and use its directory as base for the path
       packageDir = findRoot(path.resolve(file));
-      if (!packageDir) throw new Error('package not found above ' + file);
+      if (!packageDir) { throw new Error('package not found above ' + file); }
     }
 
     configPath = findConfigPath(configPath, packageDir);
@@ -108,7 +108,7 @@ exports.resolve = function (source, file, settings) {
   }
 
   if (Array.isArray(webpackConfig)) {
-    webpackConfig = webpackConfig.map(cfg => {
+    webpackConfig = webpackConfig.map((cfg) => {
       if (typeof cfg === 'function') {
         return cfg(env, argv);
       }
@@ -284,16 +284,15 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
     new ResultSymlinkPlugin(),
   );
 
-
   const resolvePlugins = [];
 
   // support webpack.ResolverPlugin
   if (plugins) {
     plugins.forEach(function (plugin) {
       if (
-        plugin.constructor &&
-        plugin.constructor.name === 'ResolverPlugin' &&
-        Array.isArray(plugin.plugins)
+        plugin.constructor
+        && plugin.constructor.name === 'ResolverPlugin'
+        && Array.isArray(plugin.plugins)
       ) {
         resolvePlugins.push.apply(resolvePlugins, plugin.plugins);
       }
@@ -324,10 +323,10 @@ function makeRootPlugin(ModulesInRootPlugin, name, root) {
 /* eslint-enable */
 
 function findExternal(source, externals, context, resolveSync) {
-  if (!externals) return false;
+  if (!externals) { return false; }
 
   // string match
-  if (typeof externals === 'string') return (source === externals);
+  if (typeof externals === 'string') { return source === externals; }
 
   // array: recurse
   if (Array.isArray(externals)) {
@@ -384,8 +383,8 @@ function findExternal(source, externals, context, resolveSync) {
 
   // else, vanilla object
   for (const key in externals) {
-    if (!has(externals, key)) continue;
-    if (source === key) return true;
+    if (!has(externals, key)) { continue; }
+    if (source === key) { return true; }
   }
   return false;
 }
@@ -396,7 +395,6 @@ function findConfigPath(configPath, packageDir) {
   });
   let extension;
 
-
   if (configPath) {
     // extensions is not reused below, so safe to mutate it here.
     extensions.reverse();
diff --git a/resolvers/webpack/test/config-extensions/webpack.config.babel.js b/resolvers/webpack/test/config-extensions/webpack.config.babel.js
index a63434f9bb..c8b3cd5780 100644
--- a/resolvers/webpack/test/config-extensions/webpack.config.babel.js
+++ b/resolvers/webpack/test/config-extensions/webpack.config.babel.js
@@ -3,7 +3,7 @@ import path from 'path';
 export default {
   resolve: {
     alias: {
-      'foo': path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'),
+      foo: path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'),
     },
     modules: [
       path.join(__dirname, 'src'),
@@ -17,7 +17,7 @@ export default {
   },
 
   externals: [
-    { 'jquery': 'jQuery' },
+    { jquery: 'jQuery' },
     'bootstrap',
   ],
 };
diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js
index c028f5c913..096df77281 100644
--- a/resolvers/webpack/test/extensions.js
+++ b/resolvers/webpack/test/extensions.js
@@ -6,7 +6,6 @@ const path = require('path');
 
 const resolve = require('../index').resolve;
 
-
 const file = path.join(__dirname, 'files', 'dummy.js');
 const extensions = path.join(__dirname, 'custom-extensions', 'dummy.js');
 
diff --git a/resolvers/webpack/test/fallback.js b/resolvers/webpack/test/fallback.js
index 87c15eecd7..b164209e14 100644
--- a/resolvers/webpack/test/fallback.js
+++ b/resolvers/webpack/test/fallback.js
@@ -6,7 +6,6 @@ const path = require('path');
 
 const resolve = require('../index').resolve;
 
-
 const file = path.join(__dirname, 'files', 'src', 'dummy.js');
 
 describe('fallback', function () {
diff --git a/resolvers/webpack/test/loaders.js b/resolvers/webpack/test/loaders.js
index 6b5604592d..e250894a54 100644
--- a/resolvers/webpack/test/loaders.js
+++ b/resolvers/webpack/test/loaders.js
@@ -6,7 +6,6 @@ const path = require('path');
 
 const resolve = require('../index').resolve;
 
-
 const file = path.join(__dirname, 'files', 'dummy.js');
 
 describe('inline loader syntax', function () {
diff --git a/resolvers/webpack/test/packageMains.js b/resolvers/webpack/test/packageMains.js
index fef3dde073..d3ddad9dab 100644
--- a/resolvers/webpack/test/packageMains.js
+++ b/resolvers/webpack/test/packageMains.js
@@ -8,7 +8,6 @@ const resolver = require('../');
 
 const file = path.join(__dirname, 'package-mains', 'dummy.js');
 
-
 describe('packageMains', function () {
 
   it('captures module', function () {
diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js
index 154dbeef95..194bb8fc88 100644
--- a/resolvers/webpack/test/root.js
+++ b/resolvers/webpack/test/root.js
@@ -6,7 +6,6 @@ const path = require('path');
 
 const resolve = require('../index').resolve;
 
-
 const file = path.join(__dirname, 'files', 'src', 'dummy.js');
 const webpackDir = path.join(__dirname, 'different-package-location');
 
diff --git a/scripts/testAll.js b/scripts/testAll.js
index fc30b1ac7d..0e4a12c68a 100644
--- a/scripts/testAll.js
+++ b/scripts/testAll.js
@@ -10,11 +10,11 @@ const spawnOptions = {
 spawnSync(
   npmPath,
   ['test'],
-  Object.assign({ cwd: __dirname }, spawnOptions));
+  { cwd: __dirname, ...spawnOptions });
 
 for (const resolverDir of resolverDirectories) {
   spawnSync(
     npmPath,
     ['test'],
-    Object.assign({ cwd: resolverDir }, spawnOptions));
+    { cwd: resolverDir, ...spawnOptions });
 }
diff --git a/src/ExportMap.js b/src/ExportMap.js
index d31375c83d..cd5bad56c3 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -53,10 +53,10 @@ export default class ExportMap {
 
   get size() {
     let size = this.namespace.size + this.reexports.size;
-    this.dependencies.forEach(dep => {
+    this.dependencies.forEach((dep) => {
       const d = dep();
       // CJS / ignored dependencies won't exist (#717)
-      if (d == null) return;
+      if (d == null) { return; }
       size += d.size;
     });
     return size;
@@ -70,8 +70,8 @@ export default class ExportMap {
    * @return {Boolean} true if `name` is exported by this module.
    */
   has(name) {
-    if (this.namespace.has(name)) return true;
-    if (this.reexports.has(name)) return true;
+    if (this.namespace.has(name)) { return true; }
+    if (this.reexports.has(name)) { return true; }
 
     // default exports must be explicitly re-exported (#328)
     if (name !== 'default') {
@@ -79,9 +79,9 @@ export default class ExportMap {
         const innerMap = dep();
 
         // todo: report as unresolved?
-        if (!innerMap) continue;
+        if (!innerMap) { continue; }
 
-        if (innerMap.has(name)) return true;
+        if (innerMap.has(name)) { return true; }
       }
     }
 
@@ -94,14 +94,14 @@ export default class ExportMap {
    * @return {{ found: boolean, path: ExportMap[] }}
    */
   hasDeep(name) {
-    if (this.namespace.has(name)) return { found: true, path: [this] };
+    if (this.namespace.has(name)) { return { found: true, path: [this] }; }
 
     if (this.reexports.has(name)) {
       const reexports = this.reexports.get(name);
       const imported = reexports.getImport();
 
       // if import is ignored, return explicit 'null'
-      if (imported == null) return { found: true, path: [this] };
+      if (imported == null) { return { found: true, path: [this] }; }
 
       // safeguard against cycles, only if name matches
       if (imported.path === this.path && reexports.local === name) {
@@ -114,17 +114,16 @@ export default class ExportMap {
       return deep;
     }
 
-
     // default exports must be explicitly re-exported (#328)
     if (name !== 'default') {
       for (const dep of this.dependencies) {
         const innerMap = dep();
-        if (innerMap == null) return { found: true, path: [this] };
+        if (innerMap == null) { return { found: true, path: [this] }; }
         // todo: report as unresolved?
-        if (!innerMap) continue;
+        if (!innerMap) { continue; }
 
         // safeguard against cycles
-        if (innerMap.path === this.path) continue;
+        if (innerMap.path === this.path) { continue; }
 
         const innerValue = innerMap.hasDeep(name);
         if (innerValue.found) {
@@ -138,17 +137,17 @@ export default class ExportMap {
   }
 
   get(name) {
-    if (this.namespace.has(name)) return this.namespace.get(name);
+    if (this.namespace.has(name)) { return this.namespace.get(name); }
 
     if (this.reexports.has(name)) {
       const reexports = this.reexports.get(name);
       const imported = reexports.getImport();
 
       // if import is ignored, return explicit 'null'
-      if (imported == null) return null;
+      if (imported == null) { return null; }
 
       // safeguard against cycles, only if name matches
-      if (imported.path === this.path && reexports.local === name) return undefined;
+      if (imported.path === this.path && reexports.local === name) { return undefined; }
 
       return imported.get(reexports.local);
     }
@@ -158,13 +157,13 @@ export default class ExportMap {
       for (const dep of this.dependencies) {
         const innerMap = dep();
         // todo: report as unresolved?
-        if (!innerMap) continue;
+        if (!innerMap) { continue; }
 
         // safeguard against cycles
-        if (innerMap.path === this.path) continue;
+        if (innerMap.path === this.path) { continue; }
 
         const innerValue = innerMap.get(name);
-        if (innerValue !== undefined) return innerValue;
+        if (innerValue !== undefined) { return innerValue; }
       }
     }
 
@@ -172,8 +171,7 @@ export default class ExportMap {
   }
 
   forEach(callback, thisArg) {
-    this.namespace.forEach((v, n) =>
-      callback.call(thisArg, v, n, this));
+    this.namespace.forEach((v, n) => { callback.call(thisArg, v, n, this); });
 
     this.reexports.forEach((reexports, name) => {
       const reexported = reexports.getImport();
@@ -181,25 +179,28 @@ export default class ExportMap {
       callback.call(thisArg, reexported && reexported.get(reexports.local), name, this);
     });
 
-    this.dependencies.forEach(dep => {
+    this.dependencies.forEach((dep) => {
       const d = dep();
       // CJS / ignored dependencies won't exist (#717)
-      if (d == null) return;
+      if (d == null) { return; }
 
-      d.forEach((v, n) =>
-        n !== 'default' && callback.call(thisArg, v, n, this));
+      d.forEach((v, n) => {
+        if (n !== 'default') {
+          callback.call(thisArg, v, n, this);
+        }
+      });
     });
   }
 
   // todo: keys, values, entries?
 
   reportErrors(context, declaration) {
+    const msg = this.errors
+      .map((e) => `${e.message} (${e.lineNumber}:${e.column})`)
+      .join(', ');
     context.report({
       node: declaration.source,
-      message: `Parse errors in imported module '${declaration.source.value}': ` +
-                  `${this.errors
-                    .map(e => `${e.message} (${e.lineNumber}:${e.column})`)
-                    .join(', ')}`,
+      message: `Parse errors in imported module '${declaration.source.value}': ${msg}`,
     });
   }
 }
@@ -211,7 +212,7 @@ function captureDoc(source, docStyleParsers, ...nodes) {
   const metadata = {};
 
   // 'some' short-circuits on first 'true'
-  nodes.some(n => {
+  nodes.some((n) => {
     try {
 
       let leadingComments;
@@ -223,7 +224,7 @@ function captureDoc(source, docStyleParsers, ...nodes) {
         leadingComments = source.getCommentsBefore(n);
       }
 
-      if (!leadingComments || leadingComments.length === 0) return false;
+      if (!leadingComments || leadingComments.length === 0) { return false; }
 
       for (const name in docStyleParsers) {
         const doc = docStyleParsers[name](leadingComments);
@@ -255,9 +256,9 @@ function captureJsDoc(comments) {
   let doc;
 
   // capture XSDoc
-  comments.forEach(comment => {
+  comments.forEach((comment) => {
     // skip non-block comments
-    if (comment.type !== 'Block') return;
+    if (comment.type !== 'Block') { return; }
     try {
       doc = doctrine.parse(comment.value, { unwrap: true });
     } catch (err) {
@@ -276,7 +277,7 @@ function captureTomDoc(comments) {
   const lines = [];
   for (let i = 0; i < comments.length; i++) {
     const comment = comments[i];
-    if (comment.value.match(/^\s*$/)) break;
+    if (comment.value.match(/^\s*$/)) { break; }
     lines.push(comment.value.trim());
   }
 
@@ -297,7 +298,7 @@ const supportedImportTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespace
 
 ExportMap.get = function (source, context) {
   const path = resolve(source, context);
-  if (path == null) return null;
+  if (path == null) { return null; }
 
   return ExportMap.for(childContext(path, context));
 };
@@ -309,7 +310,7 @@ ExportMap.for = function (context) {
   let exportMap = exportCache.get(cacheKey);
 
   // return cached ignore
-  if (exportMap === null) return null;
+  if (exportMap === null) { return null; }
 
   const stats = fs.statSync(path);
   if (exportMap != null) {
@@ -358,7 +359,6 @@ ExportMap.for = function (context) {
   return exportMap;
 };
 
-
 ExportMap.parse = function (path, content, context) {
   const m = new ExportMap(path);
   const isEsModuleInteropTrue = isEsModuleInterop();
@@ -416,21 +416,21 @@ ExportMap.parse = function (path, content, context) {
   });
 
   const unambiguouslyESM = unambiguous.isModule(ast);
-  if (!unambiguouslyESM && !hasDynamicImports) return null;
+  if (!unambiguouslyESM && !hasDynamicImports) { return null; }
 
-  const docstyle = (context.settings && context.settings['import/docstyle']) || ['jsdoc'];
+  const docstyle = context.settings && context.settings['import/docstyle'] || ['jsdoc'];
   const docStyleParsers = {};
-  docstyle.forEach(style => {
+  docstyle.forEach((style) => {
     docStyleParsers[style] = availableDocStyleParsers[style];
   });
 
   // attempt to collect module doc
   if (ast.comments) {
-    ast.comments.some(c => {
-      if (c.type !== 'Block') return false;
+    ast.comments.some((c) => {
+      if (c.type !== 'Block') { return false; }
       try {
         const doc = doctrine.parse(c.value, { unwrap: true });
-        if (doc.tags.some(t => t.title === 'module')) {
+        if (doc.tags.some((t) => t.title === 'module')) {
           m.doc = doc;
           return true;
         }
@@ -447,12 +447,12 @@ ExportMap.parse = function (path, content, context) {
 
   function resolveImport(value) {
     const rp = remotePath(value);
-    if (rp == null) return null;
+    if (rp == null) { return null; }
     return ExportMap.for(childContext(rp, context));
   }
 
   function getNamespace(identifier) {
-    if (!namespaces.has(identifier.name)) return;
+    if (!namespaces.has(identifier.name)) { return; }
 
     return function () {
       return resolveImport(namespaces.get(identifier.name));
@@ -474,27 +474,27 @@ ExportMap.parse = function (path, content, context) {
     let local;
 
     switch (s.type) {
-    case 'ExportDefaultSpecifier':
-      if (!nsource) return;
-      local = 'default';
-      break;
-    case 'ExportNamespaceSpecifier':
-      m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
-        get() { return resolveImport(nsource); },
-      }));
-      return;
-    case 'ExportAllDeclaration':
-      m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.source.value));
-      return;
-    case 'ExportSpecifier':
-      if (!n.source) {
-        m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.local));
+      case 'ExportDefaultSpecifier':
+        if (!nsource) { return; }
+        local = 'default';
+        break;
+      case 'ExportNamespaceSpecifier':
+        m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
+          get() { return resolveImport(nsource); },
+        }));
         return;
-      }
+      case 'ExportAllDeclaration':
+        m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.source.value));
+        return;
+      case 'ExportSpecifier':
+        if (!n.source) {
+          m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.local));
+          return;
+        }
       // else falls through
-    default:
-      local = s.local.name;
-      break;
+      default:
+        local = s.local.name;
+        break;
     }
 
     // todo: JSDoc
@@ -508,7 +508,7 @@ ExportMap.parse = function (path, content, context) {
     // shouldn't be considered to be just importing types
     let specifiersOnlyImportingTypes = n.specifiers.length > 0;
     const importedSpecifiers = new Set();
-    n.specifiers.forEach(specifier => {
+    n.specifiers.forEach((specifier) => {
       if (specifier.type === 'ImportSpecifier') {
         importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
       } else if (supportedImportTypes.has(specifier.type)) {
@@ -523,10 +523,10 @@ ExportMap.parse = function (path, content, context) {
   }
 
   function captureDependency({ source }, isOnlyImportingTypes, importedSpecifiers = new Set()) {
-    if (source == null) return null;
+    if (source == null) { return null; }
 
     const p = remotePath(source.value);
-    if (p == null) return null;
+    if (p == null) { return null; }
 
     const declarationMetadata = {
       // capturing actual node reference holds full AST in memory!
@@ -550,9 +550,7 @@ ExportMap.parse = function (path, content, context) {
 
   function readTsConfig(context) {
     const tsConfigInfo = tsConfigLoader({
-      cwd:
-        (context.parserOptions && context.parserOptions.tsconfigRootDir) ||
-        process.cwd(),
+      cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
       getEnv: (key) => process.env[key],
     });
     try {
@@ -599,7 +597,7 @@ ExportMap.parse = function (path, content, context) {
 
     if (n.type === 'ExportAllDeclaration') {
       const getter = captureDependency(n, n.exportKind === 'type');
-      if (getter) m.dependencies.add(getter);
+      if (getter) { m.dependencies.add(getter); }
       if (n.exported) {
         processSpecifier(n, n.exported, m);
       }
@@ -610,7 +608,7 @@ ExportMap.parse = function (path, content, context) {
     if (n.type === 'ImportDeclaration') {
       captureDependencyWithSpecifiers(n);
 
-      const ns = n.specifiers.find(s => s.type === 'ImportNamespaceSpecifier');
+      const ns = n.specifiers.find((s) => s.type === 'ImportNamespaceSpecifier');
       if (ns) {
         namespaces.set(ns.local.name, n.source.value);
       }
@@ -623,24 +621,28 @@ ExportMap.parse = function (path, content, context) {
       // capture declaration
       if (n.declaration != null) {
         switch (n.declaration.type) {
-        case 'FunctionDeclaration':
-        case 'ClassDeclaration':
-        case 'TypeAlias': // flowtype with babel-eslint parser
-        case 'InterfaceDeclaration':
-        case 'DeclareFunction':
-        case 'TSDeclareFunction':
-        case 'TSEnumDeclaration':
-        case 'TSTypeAliasDeclaration':
-        case 'TSInterfaceDeclaration':
-        case 'TSAbstractClassDeclaration':
-        case 'TSModuleDeclaration':
-          m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n));
-          break;
-        case 'VariableDeclaration':
-          n.declaration.declarations.forEach((d) =>
-            recursivePatternCapture(d.id,
-              id => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n))));
-          break;
+          case 'FunctionDeclaration':
+          case 'ClassDeclaration':
+          case 'TypeAlias': // flowtype with babel-eslint parser
+          case 'InterfaceDeclaration':
+          case 'DeclareFunction':
+          case 'TSDeclareFunction':
+          case 'TSEnumDeclaration':
+          case 'TSTypeAliasDeclaration':
+          case 'TSInterfaceDeclaration':
+          case 'TSAbstractClassDeclaration':
+          case 'TSModuleDeclaration':
+            m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n));
+            break;
+          case 'VariableDeclaration':
+            n.declaration.declarations.forEach((d) => {
+              recursivePatternCapture(
+                d.id,
+                (id) => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n)),
+              );
+            });
+            break;
+          default:
         }
       }
 
@@ -656,7 +658,7 @@ ExportMap.parse = function (path, content, context) {
     if (includes(exports, n.type)) {
       const exportedName = n.type === 'TSNamespaceExportDeclaration'
         ? (n.id || n.name).name
-        : (n.expression && n.expression.name || (n.expression.id && n.expression.id.name) || null);
+        : n.expression && n.expression.name || n.expression.id && n.expression.id.name || null;
       const declTypes = [
         'VariableDeclaration',
         'ClassDeclaration',
@@ -668,7 +670,7 @@ ExportMap.parse = function (path, content, context) {
         'TSModuleDeclaration',
       ];
       const exportedDecls = ast.body.filter(({ type, id, declarations }) => includes(declTypes, type) && (
-        (id && id.name === exportedName) || (declarations && declarations.find((d) => d.id.name === exportedName))
+        id && id.name === exportedName || declarations && declarations.find((d) => d.id.name === exportedName)
       ));
       if (exportedDecls.length === 0) {
         // Export is not referencing any local declaration, must be re-exporting
@@ -689,18 +691,17 @@ ExportMap.parse = function (path, content, context) {
             decl.body.body.forEach((moduleBlockNode) => {
               // Export-assignment exports all members in the namespace,
               // explicitly exported or not.
-              const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ?
-                moduleBlockNode.declaration :
-                moduleBlockNode;
+              const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration'
+                ? moduleBlockNode.declaration
+                : moduleBlockNode;
 
               if (!namespaceDecl) {
                 // TypeScript can check this for us; we needn't
               } else if (namespaceDecl.type === 'VariableDeclaration') {
-                namespaceDecl.declarations.forEach((d) =>
-                  recursivePatternCapture(d.id, (id) => m.namespace.set(
-                    id.name,
-                    captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode),
-                  )),
+                namespaceDecl.declarations.forEach((d) => recursivePatternCapture(d.id, (id) => m.namespace.set(
+                  id.name,
+                  captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode),
+                )),
                 );
               } else {
                 m.namespace.set(
@@ -740,7 +741,6 @@ function thunkFor(p, context) {
   return () => ExportMap.for(childContext(p, context));
 }
 
-
 /**
  * Traverse a pattern/identifier node, calling 'callback'
  * for each leaf identifier.
@@ -750,34 +750,35 @@ function thunkFor(p, context) {
  */
 export function recursivePatternCapture(pattern, callback) {
   switch (pattern.type) {
-  case 'Identifier': // base case
-    callback(pattern);
-    break;
-
-  case 'ObjectPattern':
-    pattern.properties.forEach(p => {
-      if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
-        callback(p.argument);
-        return;
-      }
-      recursivePatternCapture(p.value, callback);
-    });
-    break;
+    case 'Identifier': // base case
+      callback(pattern);
+      break;
 
-  case 'ArrayPattern':
-    pattern.elements.forEach((element) => {
-      if (element == null) return;
-      if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
-        callback(element.argument);
-        return;
-      }
-      recursivePatternCapture(element, callback);
-    });
-    break;
+    case 'ObjectPattern':
+      pattern.properties.forEach((p) => {
+        if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
+          callback(p.argument);
+          return;
+        }
+        recursivePatternCapture(p.value, callback);
+      });
+      break;
 
-  case 'AssignmentPattern':
-    callback(pattern.left);
-    break;
+    case 'ArrayPattern':
+      pattern.elements.forEach((element) => {
+        if (element == null) { return; }
+        if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
+          callback(element.argument);
+          return;
+        }
+        recursivePatternCapture(element, callback);
+      });
+      break;
+
+    case 'AssignmentPattern':
+      callback(pattern.left);
+      break;
+    default:
   }
 }
 
@@ -811,7 +812,6 @@ function childContext(path, context) {
   };
 }
 
-
 /**
  * sometimes legacy support isn't _that_ hard... right?
  */
diff --git a/src/core/importType.js b/src/core/importType.js
index ebdb306bc9..6a37d1bb14 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -14,7 +14,7 @@ function baseModule(name) {
 }
 
 function isInternalRegexMatch(name, settings) {
-  const internalScope = (settings && settings['import/internal-regex']);
+  const internalScope = settings && settings['import/internal-regex'];
   return internalScope && new RegExp(internalScope).test(name);
 }
 
@@ -24,21 +24,21 @@ export function isAbsolute(name) {
 
 // path is defined only when a resolver resolves to a non-standard path
 export function isBuiltIn(name, settings, path) {
-  if (path || !name) return false;
+  if (path || !name) { return false; }
   const base = baseModule(name);
-  const extras = (settings && settings['import/core-modules']) || [];
+  const extras = settings && settings['import/core-modules'] || [];
   return isCoreModule(base) || extras.indexOf(base) > -1;
 }
 
 export function isExternalModule(name, path, context) {
-  if (arguments.length < 3) {                                                                                                                                                                              
+  if (arguments.length < 3) {
     throw new TypeError('isExternalModule: name, path, and context are all required');
   }
   return (isModule(name) || isScoped(name)) && typeTest(name, context, path) === 'external';
 }
 
 export function isExternalModuleMain(name, path, context) {
-  if (arguments.length < 3) {                                                                                                                                                                              
+  if (arguments.length < 3) {
     throw new TypeError('isExternalModule: name, path, and context are all required');
   }
   return isModuleMain(name) && typeTest(name, context, path) === 'external';
@@ -65,7 +65,7 @@ export function isScopedMain(name) {
 }
 
 function isRelativeToParent(name) {
-  return /^\.\.$|^\.\.[\\/]/.test(name);
+  return (/^\.\.$|^\.\.[\\/]/).test(name);
 }
 
 const indexFiles = ['.', './', './index', './index.js'];
@@ -74,7 +74,7 @@ function isIndex(name) {
 }
 
 function isRelativeToSibling(name) {
-  return /^\.[\\/]/.test(name);
+  return (/^\.[\\/]/).test(name);
 }
 
 function isExternalPath(path, context) {
@@ -89,7 +89,7 @@ function isExternalPath(path, context) {
     return true;
   }
 
-  const folders = (settings && settings['import/external-module-folders']) || ['node_modules'];
+  const folders = settings && settings['import/external-module-folders'] || ['node_modules'];
   return folders.some((folder) => {
     const folderPath = nodeResolve(packagePath, folder);
     const relativePath = relative(folderPath, path);
@@ -109,7 +109,7 @@ function isExternalLookingName(name) {
   return isModule(name) || isScoped(name);
 }
 
-function typeTest(name, context, path ) {
+function typeTest(name, context, path) {
   const { settings } = context;
   if (isInternalRegexMatch(name, settings)) { return 'internal'; }
   if (isAbsolute(name, settings, path)) { return 'absolute'; }
diff --git a/src/core/packagePath.js b/src/core/packagePath.js
index 2b5a2d41ef..1a7a28f4b4 100644
--- a/src/core/packagePath.js
+++ b/src/core/packagePath.js
@@ -2,7 +2,6 @@ import { dirname } from 'path';
 import pkgUp from 'eslint-module-utils/pkgUp';
 import readPkgUp from 'eslint-module-utils/readPkgUp';
 
-
 export function getContextPackagePath(context) {
   return getFilePackagePath(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
 }
diff --git a/src/core/staticRequire.js b/src/core/staticRequire.js
index 502d39317d..88b5000c89 100644
--- a/src/core/staticRequire.js
+++ b/src/core/staticRequire.js
@@ -1,10 +1,10 @@
 // todo: merge with module visitor
 export default function isStaticRequire(node) {
-  return node &&
-    node.callee &&
-    node.callee.type === 'Identifier' &&
-    node.callee.name === 'require' &&
-    node.arguments.length === 1 &&
-    node.arguments[0].type === 'Literal' &&
-    typeof node.arguments[0].value === 'string';
+  return node
+    && node.callee
+    && node.callee.type === 'Identifier'
+    && node.callee.name === 'require'
+    && node.arguments.length === 1
+    && node.arguments[0].type === 'Literal'
+    && typeof node.arguments[0].value === 'string';
 }
diff --git a/src/index.js b/src/index.js
index 15f98d96f2..feafba9003 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,12 +1,12 @@
 export const rules = {
   'no-unresolved': require('./rules/no-unresolved'),
-  'named': require('./rules/named'),
-  'default': require('./rules/default'),
-  'namespace': require('./rules/namespace'),
+  named: require('./rules/named'),
+  default: require('./rules/default'),
+  namespace: require('./rules/namespace'),
   'no-namespace': require('./rules/no-namespace'),
-  'export': require('./rules/export'),
+  export: require('./rules/export'),
   'no-mutable-exports': require('./rules/no-mutable-exports'),
-  'extensions': require('./rules/extensions'),
+  extensions: require('./rules/extensions'),
   'no-restricted-paths': require('./rules/no-restricted-paths'),
   'no-internal-modules': require('./rules/no-internal-modules'),
   'group-exports': require('./rules/group-exports'),
@@ -25,19 +25,19 @@ export const rules = {
   'no-commonjs': require('./rules/no-commonjs'),
   'no-amd': require('./rules/no-amd'),
   'no-duplicates': require('./rules/no-duplicates'),
-  'first': require('./rules/first'),
+  first: require('./rules/first'),
   'max-dependencies': require('./rules/max-dependencies'),
   'no-extraneous-dependencies': require('./rules/no-extraneous-dependencies'),
   'no-absolute-path': require('./rules/no-absolute-path'),
   'no-nodejs-modules': require('./rules/no-nodejs-modules'),
   'no-webpack-loader-syntax': require('./rules/no-webpack-loader-syntax'),
-  'order': require('./rules/order'),
+  order: require('./rules/order'),
   'newline-after-import': require('./rules/newline-after-import'),
   'prefer-default-export': require('./rules/prefer-default-export'),
   'no-default-export': require('./rules/no-default-export'),
   'no-named-export': require('./rules/no-named-export'),
   'no-dynamic-require': require('./rules/no-dynamic-require'),
-  'unambiguous': require('./rules/unambiguous'),
+  unambiguous: require('./rules/unambiguous'),
   'no-unassigned-import': require('./rules/no-unassigned-import'),
   'no-useless-path-segments': require('./rules/no-useless-path-segments'),
   'dynamic-import-chunkname': require('./rules/dynamic-import-chunkname'),
@@ -55,17 +55,17 @@ export const rules = {
 };
 
 export const configs = {
-  'recommended': require('../config/recommended'),
+  recommended: require('../config/recommended'),
 
-  'errors': require('../config/errors'),
-  'warnings': require('../config/warnings'),
+  errors: require('../config/errors'),
+  warnings: require('../config/warnings'),
 
   // shhhh... work in progress "secret" rules
   'stage-0': require('../config/stage-0'),
 
   // useful stuff for folks using various environments
-  'react': require('../config/react'),
+  react: require('../config/react'),
   'react-native': require('../config/react-native'),
-  'electron': require('../config/electron'),
-  'typescript': require('../config/typescript'),
+  electron: require('../config/electron'),
+  typescript: require('../config/typescript'),
 };
diff --git a/src/rules/consistent-type-specifier-style.js b/src/rules/consistent-type-specifier-style.js
index bb8fdf8498..9119976b19 100644
--- a/src/rules/consistent-type-specifier-style.js
+++ b/src/rules/consistent-type-specifier-style.js
@@ -26,7 +26,7 @@ function getImportText(
     return '';
   }
 
-  const names = specifiers.map(s => {
+  const names = specifiers.map((s) => {
     if (s.imported.name === s.local.name) {
       return s.imported.name;
     }
@@ -67,12 +67,14 @@ module.exports = {
 
           if (
             // no specifiers (import type {} from '') have no specifiers to mark as inline
-            node.specifiers.length === 0 ||
-            (node.specifiers.length === 1 &&
-              // default imports are both "inline" and "top-level"
-              (node.specifiers[0].type === 'ImportDefaultSpecifier' ||
-                // namespace imports are both "inline" and "top-level"
-                node.specifiers[0].type === 'ImportNamespaceSpecifier'))
+            node.specifiers.length === 0
+            || node.specifiers.length === 1
+            // default imports are both "inline" and "top-level"
+            && (
+              node.specifiers[0].type === 'ImportDefaultSpecifier'
+              // namespace imports are both "inline" and "top-level"
+              || node.specifiers[0].type === 'ImportNamespaceSpecifier'
+            )
           ) {
             return;
           }
@@ -101,15 +103,17 @@ module.exports = {
       ImportDeclaration(node) {
         if (
           // already top-level is valid
-          node.importKind === 'type' ||
-          node.importKind === 'typeof' ||
+          node.importKind === 'type'
+          || node.importKind === 'typeof'
           // no specifiers (import {} from '') cannot have inline - so is valid
-          node.specifiers.length === 0 ||
-          (node.specifiers.length === 1 &&
-            // default imports are both "inline" and "top-level"
-            (node.specifiers[0].type === 'ImportDefaultSpecifier' ||
-              // namespace imports are both "inline" and "top-level"
-              node.specifiers[0].type === 'ImportNamespaceSpecifier'))
+          || node.specifiers.length === 0
+          || node.specifiers.length === 1
+          // default imports are both "inline" and "top-level"
+          && (
+            node.specifiers[0].type === 'ImportDefaultSpecifier'
+            // namespace imports are both "inline" and "top-level"
+            || node.specifiers[0].type === 'ImportNamespaceSpecifier'
+          )
         ) {
           return;
         }
@@ -195,7 +199,7 @@ module.exports = {
                   const comma = sourceCode.getTokenAfter(defaultSpecifier, isComma);
                   const closingBrace = sourceCode.getTokenAfter(
                     node.specifiers[node.specifiers.length - 1],
-                    token => token.type === 'Punctuator' && token.value === '}',
+                    (token) => token.type === 'Punctuator' && token.value === '}',
                   );
                   fixes.push(fixer.removeRange([
                     comma.range[0],
diff --git a/src/rules/default.js b/src/rules/default.js
index 6ca918ef66..f6b786020d 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -17,12 +17,12 @@ module.exports = {
     function checkDefault(specifierType, node) {
 
       const defaultSpecifier = node.specifiers.find(
-        specifier => specifier.type === specifierType,
+        (specifier) => specifier.type === specifierType,
       );
 
-      if (!defaultSpecifier) return;
+      if (!defaultSpecifier) { return; }
       const imports = Exports.get(node.source.value, context);
-      if (imports == null) return;
+      if (imports == null) { return; }
 
       if (imports.errors.length) {
         imports.reportErrors(context, node);
@@ -35,8 +35,8 @@ module.exports = {
     }
 
     return {
-      'ImportDeclaration': checkDefault.bind(null, 'ImportDefaultSpecifier'),
-      'ExportNamedDeclaration': checkDefault.bind(null, 'ExportDefaultSpecifier'),
+      ImportDeclaration: checkDefault.bind(null, 'ImportDefaultSpecifier'),
+      ExportNamedDeclaration: checkDefault.bind(null, 'ExportDefaultSpecifier'),
     };
   },
 };
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 87a8523dad..96ceff2e16 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -72,8 +72,7 @@ module.exports = {
         try {
           // just like webpack itself does
           vm.runInNewContext(`(function() {return {${comment.value}}})()`);
-        }
-        catch (error) {
+        } catch (error) {
           context.report({
             node,
             message: `dynamic imports require a "webpack" comment with valid syntax`,
diff --git a/src/rules/export.js b/src/rules/export.js
index 92583bdd8f..c540f1e3c9 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -38,19 +38,20 @@ const tsTypePrefix = 'type:';
 function isTypescriptFunctionOverloads(nodes) {
   const nodesArr = Array.from(nodes);
 
-  const idents = flatMap(nodesArr, (node) => (
-    node.declaration && (
+  const idents = flatMap(
+    nodesArr,
+    (node) => node.declaration && (
       node.declaration.type === 'TSDeclareFunction' // eslint 6+
       || node.declaration.type === 'TSEmptyBodyFunctionDeclaration' // eslint 4-5
     )
       ? node.declaration.id.name
-      : []
-  ));
+      : [],
+  );
   if (new Set(idents).size !== idents.length) {
     return true;
   }
 
-  const types = new Set(nodesArr.map(node => node.parent.type));
+  const types = new Set(nodesArr.map((node) => node.parent.type));
   if (!types.has('TSDeclareFunction')) {
     return false;
   }
@@ -73,17 +74,17 @@ function isTypescriptFunctionOverloads(nodes) {
  * @returns {boolean}
  */
 function isTypescriptNamespaceMerging(nodes) {
-  const types = new Set(Array.from(nodes, node => node.parent.type));
+  const types = new Set(Array.from(nodes, (node) => node.parent.type));
   const noNamespaceNodes = Array.from(nodes).filter((node) => node.parent.type !== 'TSModuleDeclaration');
 
   return types.has('TSModuleDeclaration')
     && (
       types.size === 1
       // Merging with functions
-      || (types.size === 2 && (types.has('FunctionDeclaration') || types.has('TSDeclareFunction')))
-      || (types.size === 3 && types.has('FunctionDeclaration') && types.has('TSDeclareFunction'))
+      || types.size === 2 && (types.has('FunctionDeclaration') || types.has('TSDeclareFunction'))
+      || types.size === 3 && types.has('FunctionDeclaration') && types.has('TSDeclareFunction')
       // Merging with classes or enums
-      || (types.size === 2 && (types.has('ClassDeclaration') || types.has('TSEnumDeclaration')) && noNamespaceNodes.length === 1)
+      || types.size === 2 && (types.has('ClassDeclaration') || types.has('TSEnumDeclaration')) && noNamespaceNodes.length === 1
     );
 }
 
@@ -99,7 +100,7 @@ function isTypescriptNamespaceMerging(nodes) {
  * @returns {boolean}
  */
 function shouldSkipTypescriptNamespace(node, nodes) {
-  const types = new Set(Array.from(nodes, node => node.parent.type));
+  const types = new Set(Array.from(nodes, (node) => node.parent.type));
 
   return !isTypescriptNamespaceMerging(nodes)
     && node.parent.type === 'TSModuleDeclaration'
@@ -166,7 +167,7 @@ module.exports = {
       },
 
       ExportNamedDeclaration(node) {
-        if (node.declaration == null) return;
+        if (node.declaration == null) { return; }
 
         const parent = getParent(node);
         // support for old TypeScript versions
@@ -185,20 +186,19 @@ module.exports = {
 
         if (node.declaration.declarations != null) {
           for (const declaration of node.declaration.declarations) {
-            recursivePatternCapture(declaration.id, v =>
-              addNamed(v.name, v, parent, isTypeVariableDecl));
+            recursivePatternCapture(declaration.id, (v) => { addNamed(v.name, v, parent, isTypeVariableDecl); });
           }
         }
       },
 
       ExportAllDeclaration(node) {
-        if (node.source == null) return; // not sure if this is ever true
+        if (node.source == null) { return; } // not sure if this is ever true
 
         // `export * as X from 'path'` does not conflict
-        if (node.exported && node.exported.name) return;
+        if (node.exported && node.exported.name) { return; }
 
         const remoteExports = ExportMap.get(node.source.value, context);
-        if (remoteExports == null) return;
+        if (remoteExports == null) { return; }
 
         if (remoteExports.errors.length) {
           remoteExports.reportErrors(context, node);
@@ -223,15 +223,15 @@ module.exports = {
         }
       },
 
-      'Program:exit': function () {
+      'Program:exit'() {
         for (const [, named] of namespace) {
           for (const [name, nodes] of named) {
-            if (nodes.size <= 1) continue;
+            if (nodes.size <= 1) { continue; }
 
-            if (isTypescriptFunctionOverloads(nodes) || isTypescriptNamespaceMerging(nodes)) continue;
+            if (isTypescriptFunctionOverloads(nodes) || isTypescriptNamespaceMerging(nodes)) { continue; }
 
             for (const node of nodes) {
-              if (shouldSkipTypescriptNamespace(node, nodes)) continue;
+              if (shouldSkipTypescriptNamespace(node, nodes)) { continue; }
 
               if (name === 'default') {
                 context.report(node, 'Multiple default exports.');
diff --git a/src/rules/exports-last.js b/src/rules/exports-last.js
index ed77758d20..c4ed97e22f 100644
--- a/src/rules/exports-last.js
+++ b/src/rules/exports-last.js
@@ -1,9 +1,9 @@
 import docsUrl from '../docsUrl';
 
 function isNonExportStatement({ type }) {
-  return type !== 'ExportDefaultDeclaration' &&
-    type !== 'ExportNamedDeclaration' &&
-    type !== 'ExportAllDeclaration';
+  return type !== 'ExportDefaultDeclaration'
+    && type !== 'ExportNamedDeclaration'
+    && type !== 'ExportAllDeclaration';
 }
 
 module.exports = {
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 7d026c787f..50debc6c8c 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -13,8 +13,8 @@ const patternProperties = {
 const properties = {
   type: 'object',
   properties: {
-    'pattern': patternProperties,
-    'ignorePackages': { type: 'boolean' },
+    pattern: patternProperties,
+    ignorePackages: { type: 'boolean' },
   },
 };
 
@@ -26,7 +26,7 @@ function buildProperties(context) {
     ignorePackages: false,
   };
 
-  context.options.forEach(obj => {
+  context.options.forEach((obj) => {
 
     // If this is a string, set defaultConfig to its value
     if (typeof obj === 'string') {
@@ -132,25 +132,25 @@ module.exports = {
     function isExternalRootModule(file) {
       const slashCount = file.split('/').length - 1;
 
-      if (slashCount === 0)  return true;
-      if (isScoped(file) && slashCount <= 1) return true;
+      if (slashCount === 0)  { return true; }
+      if (isScoped(file) && slashCount <= 1) { return true; }
       return false;
     }
 
     function checkFileExtension(source, node) {
       // bail if the declaration doesn't have a source, e.g. "export { foo };", or if it's only partially typed like in an editor
-      if (!source || !source.value) return;
+      if (!source || !source.value) { return; }
 
       const importPathWithQueryString = source.value;
 
       // don't enforce anything on builtins
-      if (isBuiltIn(importPathWithQueryString, context.settings)) return;
+      if (isBuiltIn(importPathWithQueryString, context.settings)) { return; }
 
       const importPath = importPathWithQueryString.replace(/\?(.*)$/, '');
 
       // don't enforce in root external packages as they may have names with `.js`.
       // Like `import Decimal from decimal.js`)
-      if (isExternalRootModule(importPath)) return;
+      if (isExternalRootModule(importPath)) { return; }
 
       const resolvedPath = resolve(importPath, context);
 
@@ -167,7 +167,7 @@ module.exports = {
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
         // ignore type-only imports and exports
-        if (node.importKind === 'type' || node.exportKind === 'type') return;
+        if (node.importKind === 'type' || node.exportKind === 'type') { return; }
         const extensionRequired = isUseOfExtensionRequired(extension, isPackage);
         const extensionForbidden = isUseOfExtensionForbidden(extension);
         if (extensionRequired && !extensionForbidden) {
diff --git a/src/rules/first.js b/src/rules/first.js
index ebead6cf27..f8cc273a31 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -25,13 +25,13 @@ module.exports = {
 
   create(context) {
     function isPossibleDirective(node) {
-      return node.type === 'ExpressionStatement' &&
-        node.expression.type === 'Literal' &&
-        typeof node.expression.value === 'string';
+      return node.type === 'ExpressionStatement'
+        && node.expression.type === 'Literal'
+        && typeof node.expression.value === 'string';
     }
 
     return {
-      'Program': function (n) {
+      Program(n) {
         const body = n.body;
         if (!body) {
           return;
@@ -56,7 +56,7 @@ module.exports = {
 
           if (node.type === 'ImportDeclaration' || node.type === 'TSImportEqualsDeclaration') {
             if (absoluteFirst) {
-              if (/^\./.test(getImportValue(node))) {
+              if ((/^\./).test(getImportValue(node))) {
                 anyRelative = true;
               } else if (anyRelative) {
                 context.report({
@@ -67,7 +67,7 @@ module.exports = {
             }
             if (nonImportCount > 0) {
               for (const variable of context.getDeclaredVariables(node)) {
-                if (!shouldSort) break;
+                if (!shouldSort) { break; }
                 const references = variable.references;
                 if (references.length) {
                   for (const reference of references) {
@@ -90,7 +90,7 @@ module.exports = {
             nonImportCount++;
           }
         });
-        if (!errorInfos.length) return;
+        if (!errorInfos.length) { return; }
         errorInfos.forEach(function (errorInfo, index) {
           const node = errorInfo.node;
           const infos = {
@@ -112,26 +112,27 @@ module.exports = {
                 const nodeSourceCode = String.prototype.slice.apply(
                   originSourceCode, _errorInfo.range,
                 );
-                if (/\S/.test(nodeSourceCode[0])) {
-                  return '\n' + nodeSourceCode;
+                if ((/\S/).test(nodeSourceCode[0])) {
+                  return `\n${nodeSourceCode}`;
                 }
                 return nodeSourceCode;
               }).join('');
               let insertFixer = null;
               let replaceSourceCode = '';
               if (!lastLegalImp) {
-                insertSourceCode =
-                    insertSourceCode.trim() + insertSourceCode.match(/^(\s+)/)[0];
+                insertSourceCode = insertSourceCode.trim() + insertSourceCode.match(/^(\s+)/)[0];
               }
-              insertFixer = lastLegalImp ?
-                fixer.insertTextAfter(lastLegalImp, insertSourceCode) :
-                fixer.insertTextBefore(body[0], insertSourceCode);
+              insertFixer = lastLegalImp
+                ? fixer.insertTextAfter(lastLegalImp, insertSourceCode)
+                : fixer.insertTextBefore(body[0], insertSourceCode);
+
               const fixers = [insertFixer].concat(removeFixers);
-              fixers.forEach(function (computedFixer, i) {
-                replaceSourceCode += (originSourceCode.slice(
+              fixers.forEach((computedFixer, i) => {
+                replaceSourceCode += originSourceCode.slice(
                   fixers[i - 1] ? fixers[i - 1].range[1] : 0, computedFixer.range[0],
-                ) + computedFixer.text);
+                ) + computedFixer.text;
               });
+
               return fixer.replaceTextRange(range, replaceSourceCode);
             };
           }
diff --git a/src/rules/group-exports.js b/src/rules/group-exports.js
index 63af9d9141..7978130d34 100644
--- a/src/rules/group-exports.js
+++ b/src/rules/group-exports.js
@@ -98,7 +98,7 @@ function create(context) {
     'Program:exit': function onExit() {
       // Report multiple `export` declarations (ES2015 modules)
       if (nodes.modules.set.size > 1) {
-        nodes.modules.set.forEach(node => {
+        nodes.modules.set.forEach((node) => {
           context.report({
             node,
             message: errors[node.type],
@@ -108,7 +108,7 @@ function create(context) {
 
       // Report multiple `aggregated exports` from the same module (ES2015 modules)
       flat(values(nodes.modules.sources)
-        .filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1))
+        .filter((nodesWithSource) => Array.isArray(nodesWithSource) && nodesWithSource.length > 1))
         .forEach((node) => {
           context.report({
             node,
@@ -118,7 +118,7 @@ function create(context) {
 
       // Report multiple `export type` declarations (FLOW ES2015 modules)
       if (nodes.types.set.size > 1) {
-        nodes.types.set.forEach(node => {
+        nodes.types.set.forEach((node) => {
           context.report({
             node,
             message: errors[node.type],
@@ -128,7 +128,7 @@ function create(context) {
 
       // Report multiple `aggregated type exports` from the same module (FLOW ES2015 modules)
       flat(values(nodes.types.sources)
-        .filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1))
+        .filter((nodesWithSource) => Array.isArray(nodesWithSource) && nodesWithSource.length > 1))
         .forEach((node) => {
           context.report({
             node,
@@ -138,7 +138,7 @@ function create(context) {
 
       // Report multiple `module.exports` assignments (CommonJS)
       if (nodes.commonjs.set.size > 1) {
-        nodes.commonjs.set.forEach(node => {
+        nodes.commonjs.set.forEach((node) => {
           context.report({
             node,
             message: errors[node.type],
diff --git a/src/rules/imports-first.js b/src/rules/imports-first.js
index 07bb4633de..966367e99f 100644
--- a/src/rules/imports-first.js
+++ b/src/rules/imports-first.js
@@ -2,13 +2,14 @@ import docsUrl from '../docsUrl';
 
 const first = require('./first');
 
-const newMeta = Object.assign({}, first.meta, {
+const newMeta = {
+  ...first.meta,
   deprecated: true,
   docs: {
     category: 'Style guide',
     description: 'Replaced by `import/first`.',
     url: docsUrl('imports-first', '7b25c1cb95ee18acc1531002fd343e1e6031f9ed'),
   },
-});
+};
 
-module.exports = Object.assign({}, first, { meta: newMeta });
+module.exports = { ...first, meta: newMeta };
diff --git a/src/rules/max-dependencies.js b/src/rules/max-dependencies.js
index 95f34176f5..488e906182 100644
--- a/src/rules/max-dependencies.js
+++ b/src/rules/max-dependencies.js
@@ -24,17 +24,17 @@ module.exports = {
 
     schema: [
       {
-        'type': 'object',
-        'properties': {
-          'max': { 'type': 'number' },
-          'ignoreTypeImports': { 'type': 'boolean' },
+        type: 'object',
+        properties: {
+          max: { type: 'number' },
+          ignoreTypeImports: { type: 'boolean' },
         },
-        'additionalProperties': false,
+        additionalProperties: false,
       },
     ],
   },
 
-  create: context => {
+  create(context) {
     const {
       ignoreTypeImports = DEFAULT_IGNORE_TYPE_IMPORTS,
     } = context.options[0] || {};
@@ -42,15 +42,19 @@ module.exports = {
     const dependencies = new Set(); // keep track of dependencies
     let lastNode; // keep track of the last node to report on
 
-    return Object.assign({
-      'Program:exit': function () {
+    return {
+      'Program:exit'() {
         countDependencies(dependencies, lastNode, context);
       },
-    }, moduleVisitor((source, { importKind }) => {
-      if (importKind !== TYPE_IMPORT || !ignoreTypeImports) {
-        dependencies.add(source.value);
-      }
-      lastNode = source;
-    }, { commonjs: true }));
+      ...moduleVisitor(
+        (source, { importKind }) => {
+          if (importKind !== TYPE_IMPORT || !ignoreTypeImports) {
+            dependencies.add(source.value);
+          }
+          lastNode = source;
+        },
+        { commonjs: true },
+      ),
+    };
   },
 };
diff --git a/src/rules/named.js b/src/rules/named.js
index 050f835056..e7fe4e4dce 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -67,12 +67,12 @@ module.exports = {
         if (!deepLookup.found) {
           if (deepLookup.path.length > 1) {
             const deepPath = deepLookup.path
-              .map(i => path.relative(path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename()), i.path))
+              .map((i) => path.relative(path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename()), i.path))
               .join(' -> ');
 
             context.report(im[key], `${name} not found via ${deepPath}`);
           } else {
-            context.report(im[key], name + ' not found in \'' + node.source.value + '\'');
+            context.report(im[key], `${name} not found in '${node.source.value}'`);
           }
         }
       });
@@ -121,12 +121,12 @@ module.exports = {
         if (!deepLookup.found) {
           if (deepLookup.path.length > 1) {
             const deepPath = deepLookup.path
-              .map(i => path.relative(path.dirname(context.getFilename()), i.path))
+              .map((i) => path.relative(path.dirname(context.getFilename()), i.path))
               .join(' -> ');
 
             context.report(im.key, `${im.key.name} not found via ${deepPath}`);
           } else {
-            context.report(im.key, im.key.name + ' not found in \'' + source.value + '\'');
+            context.report(im.key, `${im.key.name} not found in '${source.value}'`);
           }
         }
       });
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 3b6019da8d..77a3ea9077 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -4,12 +4,12 @@ import importDeclaration from '../importDeclaration';
 import docsUrl from '../docsUrl';
 
 function processBodyStatement(context, namespaces, declaration) {
-  if (declaration.type !== 'ImportDeclaration') return;
+  if (declaration.type !== 'ImportDeclaration') { return; }
 
-  if (declaration.specifiers.length === 0) return;
+  if (declaration.specifiers.length === 0) { return; }
 
   const imports = Exports.get(declaration.source.value, context);
-  if (imports == null) return null;
+  if (imports == null) { return null; }
 
   if (imports.errors.length > 0) {
     imports.reportErrors(context, declaration);
@@ -18,25 +18,26 @@ function processBodyStatement(context, namespaces, declaration) {
 
   declaration.specifiers.forEach((specifier) => {
     switch (specifier.type) {
-    case 'ImportNamespaceSpecifier':
-      if (!imports.size) {
-        context.report(
-          specifier,
-          `No exported names found in module '${declaration.source.value}'.`,
+      case 'ImportNamespaceSpecifier':
+        if (!imports.size) {
+          context.report(
+            specifier,
+            `No exported names found in module '${declaration.source.value}'.`,
+          );
+        }
+        namespaces.set(specifier.local.name, imports);
+        break;
+      case 'ImportDefaultSpecifier':
+      case 'ImportSpecifier': {
+        const meta = imports.get(
+        // default to 'default' for default https://i.imgur.com/nj6qAWy.jpg
+          specifier.imported ? specifier.imported.name || specifier.imported.value : 'default',
         );
+        if (!meta || !meta.namespace) { break; }
+        namespaces.set(specifier.local.name, meta.namespace);
+        break;
       }
-      namespaces.set(specifier.local.name, imports);
-      break;
-    case 'ImportDefaultSpecifier':
-    case 'ImportSpecifier': {
-      const meta = imports.get(
-        // default to 'default' for default https://i.imgur.com/nj6qAWy.jpg
-        specifier.imported ? (specifier.imported.name || specifier.imported.value) : 'default',
-      );
-      if (!meta || !meta.namespace) { break; }
-      namespaces.set(specifier.local.name, meta.namespace);
-      break;
-    }
+      default:
     }
   });
 }
@@ -66,7 +67,6 @@ module.exports = {
   },
 
   create: function namespaceRule(context) {
-
     // read options
     const {
       allowComputed = false,
@@ -81,7 +81,7 @@ module.exports = {
     return {
       // pick up all imports at body entry time, to properly respect hoisting
       Program({ body }) {
-        body.forEach(x => processBodyStatement(context, namespaces, x));
+        body.forEach((x) => { processBodyStatement(context, namespaces, x); });
       },
 
       // same as above, but does not add names to local map
@@ -89,7 +89,7 @@ module.exports = {
         const declaration = importDeclaration(context);
 
         const imports = Exports.get(declaration.source.value, context);
-        if (imports == null) return null;
+        if (imports == null) { return null; }
 
         if (imports.errors.length) {
           imports.reportErrors(context, declaration);
@@ -107,9 +107,9 @@ module.exports = {
       // todo: check for possible redefinition
 
       MemberExpression(dereference) {
-        if (dereference.object.type !== 'Identifier') return;
-        if (!namespaces.has(dereference.object.name)) return;
-        if (declaredScope(context, dereference.object.name) !== 'module') return;
+        if (dereference.object.type !== 'Identifier') { return; }
+        if (!namespaces.has(dereference.object.name)) { return; }
+        if (declaredScope(context, dereference.object.name) !== 'module') { return; }
 
         if (dereference.parent.type === 'AssignmentExpression' && dereference.parent.left === dereference) {
           context.report(
@@ -142,7 +142,7 @@ module.exports = {
           }
 
           const exported = namespace.get(dereference.property.name);
-          if (exported == null) return;
+          if (exported == null) { return; }
 
           // stash and pop
           namepath.push(dereference.property.name);
@@ -152,18 +152,18 @@ module.exports = {
       },
 
       VariableDeclarator({ id, init }) {
-        if (init == null) return;
-        if (init.type !== 'Identifier') return;
-        if (!namespaces.has(init.name)) return;
+        if (init == null) { return; }
+        if (init.type !== 'Identifier') { return; }
+        if (!namespaces.has(init.name)) { return; }
 
         // check for redefinition in intermediate scopes
-        if (declaredScope(context, init.name) !== 'module') return;
+        if (declaredScope(context, init.name) !== 'module') { return; }
 
         // DFS traverse child namespaces
         function testKey(pattern, namespace, path = [init.name]) {
-          if (!(namespace instanceof Exports)) return;
+          if (!(namespace instanceof Exports)) { return; }
 
-          if (pattern.type !== 'ObjectPattern') return;
+          if (pattern.type !== 'ObjectPattern') { return; }
 
           for (const property of pattern.properties) {
             if (
@@ -204,7 +204,7 @@ module.exports = {
       },
 
       JSXMemberExpression({ object, property }) {
-        if (!namespaces.has(object.name)) return;
+        if (!namespaces.has(object.name)) { return; }
         const namespace = namespaces.get(object.name);
         if (!namespace.has(property.name)) {
           context.report({
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 36678bfc4e..c63bb21b24 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -63,22 +63,22 @@ module.exports = {
     fixable: 'whitespace',
     schema: [
       {
-        'type': 'object',
-        'properties': {
-          'count': {
-            'type': 'integer',
-            'minimum': 1,
+        type: 'object',
+        properties: {
+          count: {
+            type: 'integer',
+            minimum: 1,
           },
-          'considerComments': { 'type': 'boolean' },
+          considerComments: { type: 'boolean' },
         },
-        'additionalProperties': false,
+        additionalProperties: false,
       },
     ],
   },
   create(context) {
     let level = 0;
     const requireCalls = [];
-    const options = Object.assign({ count: 1, considerComments: false }, context.options[0]);
+    const options = { count: 1, considerComments: false, ...context.options[0] };
 
     function checkForNewLine(node, nextNode, type) {
       if (isExportDefaultClass(nextNode) || isExportNameClass(nextNode)) {
@@ -107,7 +107,7 @@ module.exports = {
             column,
           },
           message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} after ${type} statement not followed by another ${type}.`,
-          fix: fixer => fixer.insertTextAfter(
+          fix: (fixer) => fixer.insertTextAfter(
             node,
             '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference),
           ),
@@ -132,7 +132,7 @@ module.exports = {
             column,
           },
           message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} after import statement not followed by another import.`,
-          fix: fixer => fixer.insertTextAfter(
+          fix: (fixer) => fixer.insertTextAfter(
             node,
             '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference),
           ),
@@ -155,10 +155,9 @@ module.exports = {
       let nextComment;
 
       if (typeof parent.comments !== 'undefined' && options.considerComments) {
-        nextComment = parent.comments.find(o => o.loc.start.line === endLine + 1);
+        nextComment = parent.comments.find((o) => o.loc.start.line === endLine + 1);
       }
 
-
       // skip "export import"s
       if (node.type === 'TSImportEqualsDeclaration' && node.isExport) {
         return;
@@ -179,12 +178,12 @@ module.exports = {
           requireCalls.push(node);
         }
       },
-      'Program:exit': function () {
+      'Program:exit'() {
         log('exit processing for', context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
         const scopeBody = getScopeBody(context.getScope());
         log('got scope:', scopeBody);
 
-        requireCalls.forEach(function (node, index) {
+        requireCalls.forEach((node, index) => {
           const nodePosition = findNodeIndexInScopeBody(scopeBody, node);
           log('node position in scope:', nodePosition);
 
@@ -196,8 +195,12 @@ module.exports = {
             return;
           }
 
-          if (nextStatement &&
-             (!nextRequireCall || !containsNodeOrEqual(nextStatement, nextRequireCall))) {
+          if (
+            nextStatement && (
+              !nextRequireCall
+              || !containsNodeOrEqual(nextStatement, nextRequireCall)
+            )
+          ) {
 
             checkForNewLine(statementWithRequireCall, nextStatement, 'require');
           }
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index 19dae6b6fb..a5498ec765 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -21,12 +21,12 @@ module.exports = {
         context.report({
           node: source,
           message: 'Do not import modules using an absolute path',
-          fix: fixer => {
+          fix(fixer) {
             const resolvedContext = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
             // node.js and web imports work with posix style paths ("/")
             let relativePath = path.posix.relative(path.dirname(resolvedContext), source.value);
             if (!relativePath.startsWith('.')) {
-              relativePath = './' + relativePath;
+              relativePath = `./${relativePath}`;
             }
             return fixer.replaceText(source, JSON.stringify(relativePath));
           },
@@ -34,7 +34,7 @@ module.exports = {
       }
     }
 
-    const options = Object.assign({ esmodule: true, commonjs: true }, context.options[0]);
+    const options = { esmodule: true, commonjs: true, ...context.options[0] };
     return moduleVisitor(reportIfAbsolute, options);
   },
 };
diff --git a/src/rules/no-amd.js b/src/rules/no-amd.js
index 90359cd5fd..5edfe3e698 100644
--- a/src/rules/no-amd.js
+++ b/src/rules/no-amd.js
@@ -22,18 +22,17 @@ module.exports = {
 
   create(context) {
     return {
-      'CallExpression': function (node) {
-        if (context.getScope().type !== 'module') return;
+      CallExpression(node) {
+        if (context.getScope().type !== 'module') { return; }
 
-        if (node.callee.type !== 'Identifier') return;
-        if (node.callee.name !== 'require' &&
-            node.callee.name !== 'define') return;
+        if (node.callee.type !== 'Identifier') { return; }
+        if (node.callee.name !== 'require' && node.callee.name !== 'define') { return; }
 
         // todo: capture define((require, module, exports) => {}) form?
-        if (node.arguments.length !== 2) return;
+        if (node.arguments.length !== 2) { return; }
 
         const modules = node.arguments[0];
-        if (modules.type !== 'ArrayExpression') return;
+        if (modules.type !== 'ArrayExpression') { return; }
 
         // todo: check second arg type? (identifier or callback)
 
diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js
index d9edcc2b36..80950d550e 100644
--- a/src/rules/no-anonymous-default-export.js
+++ b/src/rules/no-anonymous-default-export.js
@@ -88,16 +88,16 @@ module.exports = {
       {
         type: 'object',
         properties: schemaProperties,
-        'additionalProperties': false,
+        additionalProperties: false,
       },
     ],
   },
 
   create(context) {
-    const options = Object.assign({}, defaults, context.options[0]);
+    const options = { ...defaults, ...context.options[0] };
 
     return {
-      'ExportDefaultDeclaration': (node) => {
+      ExportDefaultDeclaration(node) {
         const def = defs[node.declaration.type];
 
         // Recognized node type and allowed by configuration,
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index 7a35fc8a08..dde509222b 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -16,9 +16,9 @@ function normalizeLegacyOptions(options) {
 }
 
 function allowPrimitive(node, options) {
-  if (!options.allowPrimitiveModules) return false;
-  if (node.parent.type !== 'AssignmentExpression') return false;
-  return (node.parent.right.type !== 'ObjectExpression');
+  if (!options.allowPrimitiveModules) { return false; }
+  if (node.parent.type !== 'AssignmentExpression') { return false; }
+  return node.parent.right.type !== 'ObjectExpression';
 }
 
 function allowRequire(node, options) {
@@ -40,14 +40,16 @@ function isConditional(node) {
     || node.type === 'TryStatement'
     || node.type === 'LogicalExpression'
     || node.type === 'ConditionalExpression'
-  ) return true;
-  if (node.parent) return isConditional(node.parent);
+  ) {
+    return true;
+  }
+  if (node.parent) { return isConditional(node.parent); }
   return false;
 }
 
 function isLiteralString(node) {
-  return (node.type === 'Literal' && typeof node.value === 'string') ||
-    (node.type === 'TemplateLiteral' && node.expressions.length === 0);
+  return node.type === 'Literal' && typeof node.value === 'string'
+    || node.type === 'TemplateLiteral' && node.expressions.length === 0;
 }
 
 //------------------------------------------------------------------------------
@@ -58,9 +60,9 @@ const schemaString = { enum: ['allow-primitive-modules'] };
 const schemaObject = {
   type: 'object',
   properties: {
-    allowPrimitiveModules: { 'type': 'boolean' },
-    allowRequire: { 'type': 'boolean' },
-    allowConditionalRequire: { 'type': 'boolean' },
+    allowPrimitiveModules: { type: 'boolean' },
+    allowRequire: { type: 'boolean' },
+    allowConditionalRequire: { type: 'boolean' },
   },
   additionalProperties: false,
 };
@@ -95,11 +97,11 @@ module.exports = {
 
     return {
 
-      'MemberExpression': function (node) {
+      MemberExpression(node) {
 
         // module.exports
         if (node.object.name === 'module' && node.property.name === 'exports') {
-          if (allowPrimitive(node, options)) return;
+          if (allowPrimitive(node, options)) { return; }
           context.report({ node, message: EXPORT_MESSAGE });
         }
 
@@ -107,25 +109,25 @@ module.exports = {
         if (node.object.name === 'exports') {
           const isInScope = context.getScope()
             .variables
-            .some(variable => variable.name === 'exports');
-          if (! isInScope) {
+            .some((variable) => variable.name === 'exports');
+          if (!isInScope) {
             context.report({ node, message: EXPORT_MESSAGE });
           }
         }
 
       },
-      'CallExpression': function (call) {
-        if (!validateScope(context.getScope())) return;
+      CallExpression(call) {
+        if (!validateScope(context.getScope())) { return; }
 
-        if (call.callee.type !== 'Identifier') return;
-        if (call.callee.name !== 'require') return;
+        if (call.callee.type !== 'Identifier') { return; }
+        if (call.callee.name !== 'require') { return; }
 
-        if (call.arguments.length !== 1) return;
-        if (!isLiteralString(call.arguments[0])) return;
+        if (call.arguments.length !== 1) { return; }
+        if (!isLiteralString(call.arguments[0])) { return; }
 
-        if (allowRequire(call, options)) return;
+        if (allowRequire(call, options)) { return; }
 
-        if (allowConditionalRequire(call, options) && isConditional(call.parent)) return;
+        if (allowConditionalRequire(call, options) && isConditional(call.parent)) { return; }
 
         // keeping it simple: all 1-string-arg `require` calls are reported
         context.report({
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index e12a81cea6..5b9d8c0709 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -48,7 +48,7 @@ module.exports = {
 
   create(context) {
     const myPath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
-    if (myPath === '<text>') return {}; // can't cycle-check a non-file
+    if (myPath === '<text>') { return {}; } // can't cycle-check a non-file
 
     const options = context.options[0] || {};
     const maxDepth = typeof options.maxDepth === 'number' ? options.maxDepth : Infinity;
@@ -62,20 +62,23 @@ module.exports = {
       if (ignoreModule(sourceNode.value)) {
         return; // ignore external modules
       }
-      if (options.allowUnsafeDynamicCyclicDependency && (
-        // Ignore `import()`
-        importer.type === 'ImportExpression' ||
-        // `require()` calls are always checked (if possible)
-        (importer.type === 'CallExpression' && importer.callee.name !== 'require'))) {
+      if (
+        options.allowUnsafeDynamicCyclicDependency && (
+          // Ignore `import()`
+          importer.type === 'ImportExpression'
+          // `require()` calls are always checked (if possible)
+          || importer.type === 'CallExpression' && importer.callee.name !== 'require'
+        )
+      ) {
         return; // cycle via dynamic import allowed by config
       }
 
       if (
         importer.type === 'ImportDeclaration' && (
           // import type { Foo } (TS and Flow)
-          importer.importKind === 'type' ||
+          importer.importKind === 'type'
           // import { type Foo } (Flow)
-          importer.specifiers.every(({ importKind }) => importKind === 'type')
+          || importer.specifiers.every(({ importKind }) => importKind === 'type')
         )
       ) {
         return; // ignore type imports
@@ -91,25 +94,24 @@ module.exports = {
         return;  // no-self-import territory
       }
 
-      const untraversed = [{ mget: () => imported, route:[] }];
+      const untraversed = [{ mget: () => imported, route: [] }];
       function detectCycle({ mget, route }) {
         const m = mget();
-        if (m == null) return;
-        if (traversed.has(m.path)) return;
+        if (m == null) { return; }
+        if (traversed.has(m.path)) { return; }
         traversed.add(m.path);
 
         for (const [path, { getter, declarations }] of m.imports) {
-          if (traversed.has(path)) continue;
-          const toTraverse = [...declarations].filter(({ source, isOnlyImportingTypes }) =>
-            !ignoreModule(source.value) &&
+          if (traversed.has(path)) { continue; }
+          const toTraverse = [...declarations].filter(({ source, isOnlyImportingTypes }) => !ignoreModule(source.value)
             // Ignore only type imports
-            !isOnlyImportingTypes,
+            && !isOnlyImportingTypes,
           );
 
           /*
           If cyclic dependency is allowed via dynamic import, skip checking if any module is imported dynamically
           */
-          if (options.allowUnsafeDynamicCyclicDependency && toTraverse.some(d => d.dynamic)) return;
+          if (options.allowUnsafeDynamicCyclicDependency && toTraverse.some((d) => d.dynamic)) { return; }
 
           /*
           Only report as a cycle if there are any import declarations that are considered by
@@ -121,7 +123,7 @@ module.exports = {
           b.ts:
           import type { Bar } from './a'
           */
-          if (path === myPath && toTraverse.length > 0) return true;
+          if (path === myPath && toTraverse.length > 0) { return true; }
           if (route.length + 1 < maxDepth) {
             for (const { source } of toTraverse) {
               untraversed.push({ mget: getter, route: route.concat(source) });
@@ -133,9 +135,9 @@ module.exports = {
       while (untraversed.length > 0) {
         const next = untraversed.shift(); // bfs!
         if (detectCycle(next)) {
-          const message = (next.route.length > 0
+          const message = next.route.length > 0
             ? `Dependency cycle via ${routeString(next.route)}`
-            : 'Dependency cycle detected.');
+            : 'Dependency cycle detected.';
           context.report(importer, message);
           return;
         }
@@ -143,7 +145,7 @@ module.exports = {
     }
 
     return Object.assign(moduleVisitor(checkSourceValue, context.options[0]), {
-      'Program:exit': () => {
+      'Program:exit'() {
         traversed.clear();
       },
     });
@@ -151,5 +153,5 @@ module.exports = {
 };
 
 function routeString(route) {
-  return route.map(s => `${s.value}:${s.loc.start.line}`).join('=>');
+  return route.map((s) => `${s.value}:${s.loc.start.line}`).join('=>');
 }
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index 5fc8c40e4c..6e5a537485 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -27,7 +27,7 @@ module.exports = {
       },
 
       ExportNamedDeclaration(node) {
-        node.specifiers.filter(specifier => (specifier.exported.name || specifier.exported.value) === 'default').forEach(specifier => {
+        node.specifiers.filter((specifier) => (specifier.exported.name || specifier.exported.value) === 'default').forEach((specifier) => {
           const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {};
           if (specifier.type === 'ExportDefaultSpecifier') {
             context.report({ node, message: preferNamed, loc });
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index 7a35a8e673..06eeff8ea7 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -3,13 +3,13 @@ import Exports from '../ExportMap';
 import docsUrl from '../docsUrl';
 
 function message(deprecation) {
-  return 'Deprecated' + (deprecation.description ? ': ' + deprecation.description : '.');
+  return `Deprecated${deprecation.description ? `: ${deprecation.description}` : '.'}`;
 }
 
 function getDeprecation(metadata) {
-  if (!metadata || !metadata.doc) return;
+  if (!metadata || !metadata.doc) { return; }
 
-  return metadata.doc.tags.find(t => t.title === 'deprecated');
+  return metadata.doc.tags.find((t) => t.title === 'deprecated');
 }
 
 module.exports = {
@@ -28,13 +28,13 @@ module.exports = {
     const namespaces = new Map();
 
     function checkSpecifiers(node) {
-      if (node.type !== 'ImportDeclaration') return;
-      if (node.source == null) return; // local export, ignore
+      if (node.type !== 'ImportDeclaration') { return; }
+      if (node.source == null) { return; } // local export, ignore
 
       const imports = Exports.get(node.source.value, context);
-      if (imports == null) return;
+      if (imports == null) { return; }
 
-      const moduleDeprecation = imports.doc && imports.doc.tags.find(t => t.title === 'deprecated');
+      const moduleDeprecation = imports.doc && imports.doc.tags.find((t) => t.title === 'deprecated');
       if (moduleDeprecation) {
         context.report({ node, message: message(moduleDeprecation) });
       }
@@ -48,35 +48,34 @@ module.exports = {
         let imported; let local;
         switch (im.type) {
 
+          case 'ImportNamespaceSpecifier': {
+            if (!imports.size) { return; }
+            namespaces.set(im.local.name, imports);
+            return;
+          }
 
-        case 'ImportNamespaceSpecifier':{
-          if (!imports.size) return;
-          namespaces.set(im.local.name, imports);
-          return;
-        }
-
-        case 'ImportDefaultSpecifier':
-          imported = 'default';
-          local = im.local.name;
-          break;
+          case 'ImportDefaultSpecifier':
+            imported = 'default';
+            local = im.local.name;
+            break;
 
-        case 'ImportSpecifier':
-          imported = im.imported.name;
-          local = im.local.name;
-          break;
+          case 'ImportSpecifier':
+            imported = im.imported.name;
+            local = im.local.name;
+            break;
 
-        default: return; // can't handle this one
+          default: return; // can't handle this one
         }
 
         // unknown thing can't be deprecated
         const exported = imports.get(imported);
-        if (exported == null) return;
+        if (exported == null) { return; }
 
         // capture import of deep namespace
-        if (exported.namespace) namespaces.set(local, exported.namespace);
+        if (exported.namespace) { namespaces.set(local, exported.namespace); }
 
         const deprecation = getDeprecation(imports.get(imported));
-        if (!deprecation) return;
+        if (!deprecation) { return; }
 
         context.report({ node: im, message: message(deprecation) });
 
@@ -86,44 +85,42 @@ module.exports = {
     }
 
     return {
-      'Program': ({ body }) => body.forEach(checkSpecifiers),
+      Program: ({ body }) => body.forEach(checkSpecifiers),
 
-      'Identifier': function (node) {
+      Identifier(node) {
         if (node.parent.type === 'MemberExpression' && node.parent.property === node) {
           return; // handled by MemberExpression
         }
 
         // ignore specifier identifiers
-        if (node.parent.type.slice(0, 6) === 'Import') return;
+        if (node.parent.type.slice(0, 6) === 'Import') { return; }
 
-        if (!deprecated.has(node.name)) return;
+        if (!deprecated.has(node.name)) { return; }
 
-        if (declaredScope(context, node.name) !== 'module') return;
+        if (declaredScope(context, node.name) !== 'module') { return; }
         context.report({
           node,
           message: message(deprecated.get(node.name)),
         });
       },
 
-      'MemberExpression': function (dereference) {
-        if (dereference.object.type !== 'Identifier') return;
-        if (!namespaces.has(dereference.object.name)) return;
+      MemberExpression(dereference) {
+        if (dereference.object.type !== 'Identifier') { return; }
+        if (!namespaces.has(dereference.object.name)) { return; }
 
-        if (declaredScope(context, dereference.object.name) !== 'module') return;
+        if (declaredScope(context, dereference.object.name) !== 'module') { return; }
 
         // go deep
         let namespace = namespaces.get(dereference.object.name);
         const namepath = [dereference.object.name];
         // while property is namespace and parent is member expression, keep validating
-        while (namespace instanceof Exports &&
-               dereference.type === 'MemberExpression') {
-
+        while (namespace instanceof Exports && dereference.type === 'MemberExpression') {
           // ignore computed parts for now
-          if (dereference.computed) return;
+          if (dereference.computed) { return; }
 
           const metadata = namespace.get(dereference.property.name);
 
-          if (!metadata) break;
+          if (!metadata) { break; }
           const deprecation = getDeprecation(metadata);
 
           if (deprecation) {
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 15515e6757..76bf187b2e 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -62,16 +62,16 @@ function getFix(first, rest, sourceCode, context) {
 
   // Leave it to the user to handle comments. Also skip `import * as ns from
   // './foo'` imports, since they cannot be merged into another import.
-  const restWithoutComments = rest.filter(node => !(
-    hasProblematicComments(node, sourceCode) ||
-    hasNamespace(node)
+  const restWithoutComments = rest.filter((node) => !(
+    hasProblematicComments(node, sourceCode)
+    || hasNamespace(node)
   ));
 
   const specifiers = restWithoutComments
-    .map(node => {
+    .map((node) => {
       const tokens = sourceCode.getTokens(node);
-      const openBrace = tokens.find(token => isPunctuator(token, '{'));
-      const closeBrace = tokens.find(token => isPunctuator(token, '}'));
+      const openBrace = tokens.find((token) => isPunctuator(token, '{'));
+      const closeBrace = tokens.find((token) => isPunctuator(token, '}'));
 
       if (openBrace == null || closeBrace == null) {
         return undefined;
@@ -85,10 +85,9 @@ function getFix(first, rest, sourceCode, context) {
     })
     .filter(Boolean);
 
-  const unnecessaryImports = restWithoutComments.filter(node =>
-    !hasSpecifiers(node) &&
-    !hasNamespace(node) &&
-    !specifiers.some(specifier => specifier.importNode === node),
+  const unnecessaryImports = restWithoutComments.filter((node) => !hasSpecifiers(node)
+    && !hasNamespace(node)
+    && !specifiers.some((specifier) => specifier.importNode === node),
   );
 
   const shouldAddDefault = getDefaultImportName(first) == null && defaultImportNames.size === 1;
@@ -99,16 +98,14 @@ function getFix(first, rest, sourceCode, context) {
     return undefined;
   }
 
-  return fixer => {
+  return (fixer) => {
     const tokens = sourceCode.getTokens(first);
-    const openBrace = tokens.find(token => isPunctuator(token, '{'));
-    const closeBrace = tokens.find(token => isPunctuator(token, '}'));
+    const openBrace = tokens.find((token) => isPunctuator(token, '{'));
+    const closeBrace = tokens.find((token) => isPunctuator(token, '}'));
     const firstToken = sourceCode.getFirstToken(first);
     const [defaultImportName] = defaultImportNames;
 
-    const firstHasTrailingComma =
-      closeBrace != null &&
-      isPunctuator(sourceCode.getTokenBefore(closeBrace), ',');
+    const firstHasTrailingComma = closeBrace != null && isPunctuator(sourceCode.getTokenBefore(closeBrace), ',');
     const firstIsEmpty = !hasSpecifiers(first);
     const firstExistingIdentifiers = firstIsEmpty
       ? new Set()
@@ -214,21 +211,21 @@ function isPunctuator(node, value) {
 // Get the name of the default import of `node`, if any.
 function getDefaultImportName(node) {
   const defaultSpecifier = node.specifiers
-    .find(specifier => specifier.type === 'ImportDefaultSpecifier');
+    .find((specifier) => specifier.type === 'ImportDefaultSpecifier');
   return defaultSpecifier != null ? defaultSpecifier.local.name : undefined;
 }
 
 // Checks whether `node` has a namespace import.
 function hasNamespace(node) {
   const specifiers = node.specifiers
-    .filter(specifier => specifier.type === 'ImportNamespaceSpecifier');
+    .filter((specifier) => specifier.type === 'ImportNamespaceSpecifier');
   return specifiers.length > 0;
 }
 
 // Checks whether `node` has any non-default specifiers.
 function hasSpecifiers(node) {
   const specifiers = node.specifiers
-    .filter(specifier => specifier.type === 'ImportSpecifier');
+    .filter((specifier) => specifier.type === 'ImportSpecifier');
   return specifiers.length > 0;
 }
 
@@ -236,9 +233,9 @@ function hasSpecifiers(node) {
 // duplicate imports, so skip imports with comments when autofixing.
 function hasProblematicComments(node, sourceCode) {
   return (
-    hasCommentBefore(node, sourceCode) ||
-    hasCommentAfter(node, sourceCode) ||
-    hasCommentInsideNonSpecifiers(node, sourceCode)
+    hasCommentBefore(node, sourceCode)
+    || hasCommentAfter(node, sourceCode)
+    || hasCommentInsideNonSpecifiers(node, sourceCode)
   );
 }
 
@@ -246,29 +243,29 @@ function hasProblematicComments(node, sourceCode) {
 // the same line as `node` (starts).
 function hasCommentBefore(node, sourceCode) {
   return sourceCode.getCommentsBefore(node)
-    .some(comment => comment.loc.end.line >= node.loc.start.line - 1);
+    .some((comment) => comment.loc.end.line >= node.loc.start.line - 1);
 }
 
 // Checks whether `node` has a comment (that starts) on the same line as `node`
 // (ends).
 function hasCommentAfter(node, sourceCode) {
   return sourceCode.getCommentsAfter(node)
-    .some(comment => comment.loc.start.line === node.loc.end.line);
+    .some((comment) => comment.loc.start.line === node.loc.end.line);
 }
 
 // Checks whether `node` has any comments _inside,_ except inside the `{...}`
 // part (if any).
 function hasCommentInsideNonSpecifiers(node, sourceCode) {
   const tokens = sourceCode.getTokens(node);
-  const openBraceIndex = tokens.findIndex(token => isPunctuator(token, '{'));
-  const closeBraceIndex = tokens.findIndex(token => isPunctuator(token, '}'));
+  const openBraceIndex = tokens.findIndex((token) => isPunctuator(token, '{'));
+  const closeBraceIndex = tokens.findIndex((token) => isPunctuator(token, '}'));
   // Slice away the first token, since we're no looking for comments _before_
   // `node` (only inside). If there's a `{...}` part, look for comments before
   // the `{`, but not before the `}` (hence the `+1`s).
   const someTokens = openBraceIndex >= 0 && closeBraceIndex >= 0
     ? tokens.slice(1, openBraceIndex + 1).concat(tokens.slice(closeBraceIndex + 1))
     : tokens.slice(1);
-  return someTokens.some(token => sourceCode.getCommentsBefore(token).length > 0);
+  return someTokens.some((token) => sourceCode.getCommentsBefore(token).length > 0);
 }
 
 module.exports = {
@@ -298,16 +295,16 @@ module.exports = {
 
   create(context) {
     // Prepare the resolver from options.
-    const considerQueryStringOption = context.options[0] &&
-      context.options[0]['considerQueryString'];
-    const defaultResolver = sourcePath => resolve(sourcePath, context) || sourcePath;
-    const resolver = considerQueryStringOption ? (sourcePath => {
+    const considerQueryStringOption = context.options[0]
+      && context.options[0].considerQueryString;
+    const defaultResolver = (sourcePath) => resolve(sourcePath, context) || sourcePath;
+    const resolver = considerQueryStringOption ? (sourcePath) => {
       const parts = sourcePath.match(/^([^?]*)\?(.*)$/);
       if (!parts) {
         return defaultResolver(sourcePath);
       }
-      return defaultResolver(parts[1]) + '?' + parts[2];
-    }) : defaultResolver;
+      return `${defaultResolver(parts[1])}?${parts[2]}`;
+    } : defaultResolver;
 
     const moduleMaps = new Map();
 
@@ -344,7 +341,7 @@ module.exports = {
         }
       },
 
-      'Program:exit': function () {
+      'Program:exit'() {
         for (const map of moduleMaps.values()) {
           checkImports(map.imported, context);
           checkImports(map.nsImported, context);
diff --git a/src/rules/no-dynamic-require.js b/src/rules/no-dynamic-require.js
index f334adec67..f8b369a70f 100644
--- a/src/rules/no-dynamic-require.js
+++ b/src/rules/no-dynamic-require.js
@@ -1,22 +1,22 @@
 import docsUrl from '../docsUrl';
 
 function isRequire(node) {
-  return node &&
-    node.callee &&
-    node.callee.type === 'Identifier' &&
-    node.callee.name === 'require' &&
-    node.arguments.length >= 1;
+  return node
+    && node.callee
+    && node.callee.type === 'Identifier'
+    && node.callee.name === 'require'
+    && node.arguments.length >= 1;
 }
 
 function isDynamicImport(node) {
-  return node &&
-    node.callee &&
-    node.callee.type === 'Import';
+  return node
+    && node.callee
+    && node.callee.type === 'Import';
 }
 
 function isStaticValue(arg) {
-  return arg.type === 'Literal' ||
-    (arg.type === 'TemplateLiteral' && arg.expressions.length === 0);
+  return arg.type === 'Literal'
+    || arg.type === 'TemplateLiteral' && arg.expressions.length === 0;
 }
 
 const dynamicImportErrorMessage = 'Calls to import() should use string literals';
diff --git a/src/rules/no-empty-named-blocks.js b/src/rules/no-empty-named-blocks.js
index 25567b08f8..3ec1501b8f 100644
--- a/src/rules/no-empty-named-blocks.js
+++ b/src/rules/no-empty-named-blocks.js
@@ -8,7 +8,7 @@ function getEmptyBlockRange(tokens, index) {
   const end = nextToken.range[1];
 
   // Remove block tokens and the previous comma
-  if (prevToken.value === ','|| prevToken.value === 'type' || prevToken.value === 'typeof') {
+  if (prevToken.value === ',' || prevToken.value === 'type' || prevToken.value === 'typeof') {
     start = prevToken.range[0];
   }
 
@@ -33,15 +33,13 @@ module.exports = {
 
     return {
       ImportDeclaration(node) {
-        if (!node.specifiers.some(x => x.type === 'ImportSpecifier')) {
+        if (!node.specifiers.some((x) => x.type === 'ImportSpecifier')) {
           importsWithoutNameds.push(node);
         }
       },
 
-      'Program:exit': function (program) {
-        const importsTokens = importsWithoutNameds.map((node) => {
-          return [node, program.tokens.filter(x => x.range[0] >= node.range[0] && x.range[1] <= node.range[1])];
-        });
+      'Program:exit'(program) {
+        const importsTokens = importsWithoutNameds.map((node) => [node, program.tokens.filter((x) => x.range[0] >= node.range[0] && x.range[1] <= node.range[1])]);
 
         importsTokens.forEach(([node, tokens]) => {
           tokens.forEach((token) => {
@@ -49,12 +47,11 @@ module.exports = {
             const nextToken = program.tokens[idx + 1];
 
             if (nextToken && token.value === '{' && nextToken.value === '}') {
-              const hasOtherIdentifiers = tokens.some((token) => (
-                token.type === 'Identifier'
+              const hasOtherIdentifiers = tokens.some((token) => token.type === 'Identifier'
                   && token.value !== 'from'
                   && token.value !== 'type'
-                  && token.value !== 'typeof'
-              ));
+                  && token.value !== 'typeof',
+              );
 
               // If it has no other identifiers it's the only thing in the import, so we can either remove the import
               // completely or transform it in a side-effects only import
@@ -76,8 +73,8 @@ module.exports = {
                         // Remove the empty block and the 'from' token, leaving the import only for its side
                         // effects, e.g. `import 'mod'`
                         const sourceCode = context.getSourceCode();
-                        const fromToken = program.tokens.find(t => t.value === 'from');
-                        const importToken = program.tokens.find(t => t.value === 'import');
+                        const fromToken = program.tokens.find((t) => t.value === 'from');
+                        const importToken = program.tokens.find((t) => t.value === 'import');
                         const hasSpaceAfterFrom = sourceCode.isSpaceBetween(fromToken, sourceCode.getTokenAfter(fromToken));
                         const hasSpaceAfterImport = sourceCode.isSpaceBetween(importToken, sourceCode.getTokenAfter(fromToken));
 
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index a149ca6599..0408e0866d 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -64,18 +64,18 @@ function getDependencies(context, packageDir) {
       if (!Array.isArray(packageDir)) {
         paths = [path.resolve(packageDir)];
       } else {
-        paths = packageDir.map(dir => path.resolve(dir));
+        paths = packageDir.map((dir) => path.resolve(dir));
       }
     }
 
     if (paths.length > 0) {
       // use rule config to find package.json
-      paths.forEach(dir => {
+      paths.forEach((dir) => {
         const packageJsonPath = path.join(dir, 'package.json');
         const _packageContent = getPackageDepFields(packageJsonPath, true);
-        Object.keys(packageContent).forEach(depsKey =>
-          Object.assign(packageContent[depsKey], _packageContent[depsKey]),
-        );
+        Object.keys(packageContent).forEach((depsKey) => {
+          Object.assign(packageContent[depsKey], _packageContent[depsKey]);
+        });
       });
     } else {
       const packageJsonPath = pkgUp({
@@ -110,7 +110,7 @@ function getDependencies(context, packageDir) {
     }
     if (e.name === 'JSONError' || e instanceof SyntaxError) {
       context.report({
-        message: 'The package.json file could not be parsed: ' + e.message,
+        message: `The package.json file could not be parsed: ${e.message}`,
         loc: { line: 0, column: 0 },
       });
     }
@@ -120,8 +120,7 @@ function getDependencies(context, packageDir) {
 }
 
 function missingErrorMessage(packageName) {
-  return `'${packageName}' should be listed in the project's dependencies. ` +
-    `Run 'npm i -S ${packageName}' to add it`;
+  return `'${packageName}' should be listed in the project's dependencies. Run 'npm i -S ${packageName}' to add it`;
 }
 
 function devDepErrorMessage(packageName) {
@@ -129,8 +128,7 @@ function devDepErrorMessage(packageName) {
 }
 
 function optDepErrorMessage(packageName) {
-  return `'${packageName}' should be listed in the project's dependencies, ` +
-    `not optionalDependencies.`;
+  return `'${packageName}' should be listed in the project's dependencies, not optionalDependencies.`;
 }
 
 function getModuleOriginalName(name) {
@@ -162,27 +160,24 @@ function checkDependencyDeclaration(deps, packageName, declarationStatus) {
     }
   });
 
-  return packageHierarchy.reduce((result, ancestorName) => {
-    return {
-      isInDeps: result.isInDeps || deps.dependencies[ancestorName] !== undefined,
-      isInDevDeps: result.isInDevDeps || deps.devDependencies[ancestorName] !== undefined,
-      isInOptDeps: result.isInOptDeps || deps.optionalDependencies[ancestorName] !== undefined,
-      isInPeerDeps: result.isInPeerDeps || deps.peerDependencies[ancestorName] !== undefined,
-      isInBundledDeps:
+  return packageHierarchy.reduce((result, ancestorName) => ({
+    isInDeps: result.isInDeps || deps.dependencies[ancestorName] !== undefined,
+    isInDevDeps: result.isInDevDeps || deps.devDependencies[ancestorName] !== undefined,
+    isInOptDeps: result.isInOptDeps || deps.optionalDependencies[ancestorName] !== undefined,
+    isInPeerDeps: result.isInPeerDeps || deps.peerDependencies[ancestorName] !== undefined,
+    isInBundledDeps:
         result.isInBundledDeps || deps.bundledDependencies.indexOf(ancestorName) !== -1,
-    };
-  }, newDeclarationStatus);
+  }), newDeclarationStatus);
 }
 
 function reportIfMissing(context, deps, depsOptions, node, name) {
   // Do not report when importing types unless option is enabled
   if (
-    !depsOptions.verifyTypeImports &&
-    (node.importKind === 'type' || node.importKind === 'typeof' ||
-    (
-      Array.isArray(node.specifiers) &&
-      node.specifiers.length &&
-      node.specifiers.every((specifier) => specifier.importKind === 'type' || specifier.importKind === 'typeof'))
+    !depsOptions.verifyTypeImports
+    && (
+      node.importKind === 'type'
+      || node.importKind === 'typeof'
+      || Array.isArray(node.specifiers) && node.specifiers.length && node.specifiers.every((specifier) => specifier.importKind === 'type' || specifier.importKind === 'typeof')
     )
   ) {
     return;
@@ -204,11 +199,11 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
   let declarationStatus = checkDependencyDeclaration(deps, importPackageName);
 
   if (
-    declarationStatus.isInDeps ||
-    (depsOptions.allowDevDeps && declarationStatus.isInDevDeps) ||
-    (depsOptions.allowPeerDeps && declarationStatus.isInPeerDeps) ||
-    (depsOptions.allowOptDeps && declarationStatus.isInOptDeps) ||
-    (depsOptions.allowBundledDeps && declarationStatus.isInBundledDeps)
+    declarationStatus.isInDeps
+    || depsOptions.allowDevDeps && declarationStatus.isInDevDeps
+    || depsOptions.allowPeerDeps && declarationStatus.isInPeerDeps
+    || depsOptions.allowOptDeps && declarationStatus.isInOptDeps
+    || depsOptions.allowBundledDeps && declarationStatus.isInBundledDeps
   ) {
     return;
   }
@@ -220,11 +215,11 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
     declarationStatus = checkDependencyDeclaration(deps, realPackageName, declarationStatus);
 
     if (
-      declarationStatus.isInDeps ||
-      (depsOptions.allowDevDeps && declarationStatus.isInDevDeps) ||
-      (depsOptions.allowPeerDeps && declarationStatus.isInPeerDeps) ||
-      (depsOptions.allowOptDeps && declarationStatus.isInOptDeps) ||
-      (depsOptions.allowBundledDeps && declarationStatus.isInBundledDeps)
+      declarationStatus.isInDeps
+      || depsOptions.allowDevDeps && declarationStatus.isInDevDeps
+      || depsOptions.allowPeerDeps && declarationStatus.isInPeerDeps
+      || depsOptions.allowOptDeps && declarationStatus.isInOptDeps
+      || depsOptions.allowBundledDeps && declarationStatus.isInBundledDeps
     ) {
       return;
     }
@@ -249,10 +244,9 @@ function testConfig(config, filename) {
     return config;
   }
   // Array of globs.
-  return config.some(c => (
-    minimatch(filename, c) ||
-    minimatch(filename, path.join(process.cwd(), c))
-  ));
+  return config.some((c) => minimatch(filename, c)
+    || minimatch(filename, path.join(process.cwd(), c)),
+  );
 }
 
 module.exports = {
@@ -266,17 +260,17 @@ module.exports = {
 
     schema: [
       {
-        'type': 'object',
-        'properties': {
-          'devDependencies': { 'type': ['boolean', 'array'] },
-          'optionalDependencies': { 'type': ['boolean', 'array'] },
-          'peerDependencies': { 'type': ['boolean', 'array'] },
-          'bundledDependencies': { 'type': ['boolean', 'array'] },
-          'packageDir': { 'type': ['string', 'array'] },
-          'includeInternal': { 'type': ['boolean'] },
-          'includeTypes': { 'type': ['boolean'] },
+        type: 'object',
+        properties: {
+          devDependencies: { type: ['boolean', 'array'] },
+          optionalDependencies: { type: ['boolean', 'array'] },
+          peerDependencies: { type: ['boolean', 'array'] },
+          bundledDependencies: { type: ['boolean', 'array'] },
+          packageDir: { type: ['string', 'array'] },
+          includeInternal: { type: ['boolean'] },
+          includeTypes: { type: ['boolean'] },
         },
-        'additionalProperties': false,
+        additionalProperties: false,
       },
     ],
   },
@@ -300,7 +294,7 @@ module.exports = {
     }, { commonjs: true });
   },
 
-  'Program:exit': () => {
+  'Program:exit'() {
     depFieldCache.clear();
   },
 };
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index 5a91acd07d..bc4605c39d 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -16,12 +16,12 @@ function getEntryPoint(context) {
 function findScope(context, identifier) {
   const { scopeManager } = context.getSourceCode();
 
-  return scopeManager && scopeManager.scopes.slice().reverse().find((scope) => scope.variables.some(variable => variable.identifiers.some((node) => node.name === identifier)));
+  return scopeManager && scopeManager.scopes.slice().reverse().find((scope) => scope.variables.some((variable) => variable.identifiers.some((node) => node.name === identifier)));
 }
 
 function findDefinition(objectScope, identifier) {
-  const variable = objectScope.variables.find(variable => variable.name === identifier);
-  return variable.defs.find(def => def.name.name === identifier);
+  const variable = objectScope.variables.find((variable) => variable.name === identifier);
+  return variable.defs.find((def) => def.name.name === identifier);
 }
 
 module.exports = {
@@ -35,11 +35,11 @@ module.exports = {
     fixable: 'code',
     schema: [
       {
-        'type': 'object',
-        'properties': {
-          'exceptions': { 'type': 'array' },
+        type: 'object',
+        properties: {
+          exceptions: { type: 'array' },
         },
-        'additionalProperties': false,
+        additionalProperties: false,
       },
     ],
   },
@@ -58,14 +58,13 @@ module.exports = {
       const variableDefinition = objectScope && findDefinition(objectScope, node.object.name);
       const isImportBinding = variableDefinition && variableDefinition.type === 'ImportBinding';
       const hasCJSExportReference = hasKeywords && (!objectScope || objectScope.type === 'module');
-      const isException = !!options.exceptions && options.exceptions.some(glob => minimatch(fileName, glob));
+      const isException = !!options.exceptions && options.exceptions.some((glob) => minimatch(fileName, glob));
 
       if (isIdentifier && hasCJSExportReference && !isEntryPoint && !isException && !isImportBinding) {
-        importDeclarations.forEach(importDeclaration => {
+        importDeclarations.forEach((importDeclaration) => {
           context.report({
             node: importDeclaration,
-            message: `Cannot use import declarations in modules that export using ` +
-              `CommonJS (module.exports = 'foo' or exports.bar = 'hi')`,
+            message: `Cannot use import declarations in modules that export using CommonJS (module.exports = 'foo' or exports.bar = 'hi')`,
           });
         });
         alreadyReported = true;
diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index 2416c1ce3f..687193f5c5 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -48,8 +48,8 @@ module.exports = {
 
   create: function noReachingInside(context) {
     const options = context.options[0] || {};
-    const allowRegexps = (options.allow || []).map(p => minimatch.makeRe(p));
-    const forbidRegexps = (options.forbid || []).map(p => minimatch.makeRe(p));
+    const allowRegexps = (options.allow || []).map((p) => minimatch.makeRe(p));
+    const forbidRegexps = (options.forbid || []).map((p) => minimatch.makeRe(p));
 
     // minimatch patterns are expected to use / path separators, like import
     // statements, so normalize paths to use the same
@@ -73,29 +73,29 @@ module.exports = {
 
     // test if reaching to this destination is allowed
     function reachingAllowed(importPath) {
-      return allowRegexps.some(re => re.test(importPath));
+      return allowRegexps.some((re) => re.test(importPath));
     }
 
     // test if reaching to this destination is forbidden
     function reachingForbidden(importPath) {
-      return forbidRegexps.some(re => re.test(importPath));
+      return forbidRegexps.some((re) => re.test(importPath));
     }
 
     function isAllowViolation(importPath) {
       const steps = toSteps(importPath);
 
-      const nonScopeSteps = steps.filter(step => step.indexOf('@') !== 0);
-      if (nonScopeSteps.length <= 1) return false;
+      const nonScopeSteps = steps.filter((step) => step.indexOf('@') !== 0);
+      if (nonScopeSteps.length <= 1) { return false; }
 
       // before trying to resolve, see if the raw import (with relative
       // segments resolved) matches an allowed pattern
       const justSteps = steps.join('/');
-      if (reachingAllowed(justSteps) || reachingAllowed(`/${justSteps}`)) return false;
+      if (reachingAllowed(justSteps) || reachingAllowed(`/${justSteps}`)) { return false; }
 
       // if the import statement doesn't match directly, try to match the
       // resolved path if the import is resolvable
       const resolved = resolve(importPath, context);
-      if (!resolved || reachingAllowed(normalizeSep(resolved))) return false;
+      if (!resolved || reachingAllowed(normalizeSep(resolved))) { return false; }
 
       // this import was not allowed by the allowed paths, and reaches
       // so it is a violation
@@ -109,12 +109,12 @@ module.exports = {
       // segments resolved) matches a forbidden pattern
       const justSteps = steps.join('/');
 
-      if (reachingForbidden(justSteps) || reachingForbidden(`/${justSteps}`)) return true;
+      if (reachingForbidden(justSteps) || reachingForbidden(`/${justSteps}`)) { return true; }
 
       // if the import statement doesn't match directly, try to match the
       // resolved path if the import is resolvable
       const resolved = resolve(importPath, context);
-      if (resolved && reachingForbidden(normalizeSep(resolved))) return true;
+      if (resolved && reachingForbidden(normalizeSep(resolved))) { return true; }
 
       // this import was not forbidden by the forbidden paths so it is not a violation
       return false;
@@ -125,8 +125,9 @@ module.exports = {
 
     function checkImportForReaching(importPath, node) {
       const potentialViolationTypes = ['parent', 'index', 'sibling', 'external', 'internal'];
-      if (potentialViolationTypes.indexOf(importType(importPath, context)) !== -1 &&
-        isReachViolation(importPath)
+      if (
+        potentialViolationTypes.indexOf(importType(importPath, context)) !== -1
+        && isReachViolation(importPath)
       ) {
         context.report({
           node,
@@ -135,8 +136,11 @@ module.exports = {
       }
     }
 
-    return moduleVisitor((source) => {
-      checkImportForReaching(source.value, source);
-    }, { commonjs: true });
+    return moduleVisitor(
+      (source) => {
+        checkImportForReaching(source.value, source);
+      },
+      { commonjs: true },
+    );
   },
 };
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index 75a321b62a..433d64e167 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -52,8 +52,8 @@ module.exports = {
     }
 
     return {
-      'ExportDefaultDeclaration': handleExportDefault,
-      'ExportNamedDeclaration': handleExportNamed,
+      ExportDefaultDeclaration: handleExportDefault,
+      ExportNamedDeclaration: handleExportNamed,
     };
   },
 };
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index 0fb0927249..e00a4cbc87 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -24,81 +24,68 @@ module.exports = {
   },
 
   create(context) {
-
     const fileImports = new Map();
     const allPropertyLookups = new Map();
 
-    function handleImportDefault(node) {
-      const declaration = importDeclaration(context);
-      const exportMap = Exports.get(declaration.source.value, context);
-      if (exportMap == null) return;
-
-      if (exportMap.errors.length) {
-        exportMap.reportErrors(context, declaration);
-        return;
-      }
-
-      fileImports.set(node.local.name, {
-        exportMap,
-        sourcePath: declaration.source.value,
-      });
-    }
-
     function storePropertyLookup(objectName, propName, node) {
       const lookups = allPropertyLookups.get(objectName) || [];
       lookups.push({ node, propName });
       allPropertyLookups.set(objectName, lookups);
     }
 
-    function handlePropLookup(node) {
-      const objectName = node.object.name;
-      const propName = node.property.name;
-      storePropertyLookup(objectName, propName, node);
-    }
+    return {
+      ImportDefaultSpecifier(node) {
+        const declaration = importDeclaration(context);
+        const exportMap = Exports.get(declaration.source.value, context);
+        if (exportMap == null) { return; }
 
-    function handleDestructuringAssignment(node) {
-      const isDestructure = (
-        node.id.type === 'ObjectPattern' &&
-        node.init != null &&
-        node.init.type === 'Identifier'
-      );
-      if (!isDestructure) return;
+        if (exportMap.errors.length) {
+          exportMap.reportErrors(context, declaration);
+          return;
+        }
 
-      const objectName = node.init.name;
-      for (const { key } of node.id.properties) {
-        if (key == null) continue;  // true for rest properties
-        storePropertyLookup(objectName, key.name, key);
-      }
-    }
+        fileImports.set(node.local.name, {
+          exportMap,
+          sourcePath: declaration.source.value,
+        });
+      },
 
-    function handleProgramExit() {
-      allPropertyLookups.forEach((lookups, objectName) => {
-        const fileImport = fileImports.get(objectName);
-        if (fileImport == null) return;
+      MemberExpression(node) {
+        const objectName = node.object.name;
+        const propName = node.property.name;
+        storePropertyLookup(objectName, propName, node);
+      },
 
-        for (const { propName, node } of lookups) {
-          // the default import can have a "default" property
-          if (propName === 'default') continue;
-          if (!fileImport.exportMap.namespace.has(propName)) continue;
+      VariableDeclarator(node) {
+        const isDestructure = node.id.type === 'ObjectPattern'
+          && node.init != null
+          && node.init.type === 'Identifier';
+        if (!isDestructure) { return; }
 
-          context.report({
-            node,
-            message: (
-              `Caution: \`${objectName}\` also has a named export ` +
-              `\`${propName}\`. Check if you meant to write ` +
-              `\`import {${propName}} from '${fileImport.sourcePath}'\` ` +
-              'instead.'
-            ),
-          });
+        const objectName = node.init.name;
+        for (const { key } of node.id.properties) {
+          if (key == null) { continue; }  // true for rest properties
+          storePropertyLookup(objectName, key.name, key);
         }
-      });
-    }
+      },
 
-    return {
-      'ImportDefaultSpecifier': handleImportDefault,
-      'MemberExpression': handlePropLookup,
-      'VariableDeclarator': handleDestructuringAssignment,
-      'Program:exit': handleProgramExit,
+      'Program:exit'() {
+        allPropertyLookups.forEach((lookups, objectName) => {
+          const fileImport = fileImports.get(objectName);
+          if (fileImport == null) { return; }
+
+          for (const { propName, node } of lookups) {
+            // the default import can have a "default" property
+            if (propName === 'default') { continue; }
+            if (!fileImport.exportMap.namespace.has(propName)) { continue; }
+
+            context.report({
+              node,
+              message: `Caution: \`${objectName}\` also has a named export \`${propName}\`. Check if you meant to write \`import {${propName}} from '${fileImport.sourcePath}'\` instead.`,
+            });
+          }
+        });
+      },
     };
   },
 };
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index c3a35ff64a..40b1e175b2 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -16,30 +16,30 @@ module.exports = {
   create(context) {
     function checkDefault(nameKey, defaultSpecifier) {
       // #566: default is a valid specifier
-      if (defaultSpecifier[nameKey].name === 'default') return;
+      if (defaultSpecifier[nameKey].name === 'default') { return; }
 
       const declaration = importDeclaration(context);
 
       const imports = Exports.get(declaration.source.value, context);
-      if (imports == null) return;
+      if (imports == null) { return; }
 
       if (imports.errors.length) {
         imports.reportErrors(context, declaration);
         return;
       }
 
-      if (imports.has('default') &&
-          imports.has(defaultSpecifier[nameKey].name)) {
+      if (imports.has('default') && imports.has(defaultSpecifier[nameKey].name)) {
 
-        context.report(defaultSpecifier,
-          'Using exported name \'' + defaultSpecifier[nameKey].name +
-          '\' as identifier for default export.');
+        context.report(
+          defaultSpecifier,
+          `Using exported name '${defaultSpecifier[nameKey].name}' as identifier for default export.`,
+        );
 
       }
     }
     return {
-      'ImportDefaultSpecifier': checkDefault.bind(null, 'local'),
-      'ExportDefaultSpecifier': checkDefault.bind(null, 'exported'),
+      ImportDefaultSpecifier: checkDefault.bind(null, 'local'),
+      ExportDefaultSpecifier: checkDefault.bind(null, 'exported'),
     };
   },
 };
diff --git a/src/rules/no-named-default.js b/src/rules/no-named-default.js
index 8745ce3890..1ed0e31df5 100644
--- a/src/rules/no-named-default.js
+++ b/src/rules/no-named-default.js
@@ -13,7 +13,7 @@ module.exports = {
 
   create(context) {
     return {
-      'ImportDeclaration': function (node) {
+      ImportDeclaration(node) {
         node.specifiers.forEach(function (im) {
           if (im.importKind === 'type' || im.importKind === 'typeof') {
             return;
diff --git a/src/rules/no-named-export.js b/src/rules/no-named-export.js
index b0722f3596..efaf9dc4c8 100644
--- a/src/rules/no-named-export.js
+++ b/src/rules/no-named-export.js
@@ -29,7 +29,7 @@ module.exports = {
           return context.report({ node, message });
         }
 
-        const someNamed = node.specifiers.some(specifier => (specifier.exported.name || specifier.exported.value) !== 'default');
+        const someNamed = node.specifiers.some((specifier) => (specifier.exported.name || specifier.exported.value) !== 'default');
         if (someNamed) {
           context.report({ node, message });
         }
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index a078137e65..d3e591876f 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -10,7 +10,6 @@ import docsUrl from '../docsUrl';
 // Rule Definition
 //------------------------------------------------------------------------------
 
-
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -40,20 +39,20 @@ module.exports = {
 
     return {
       ImportNamespaceSpecifier(node) {
-        if (ignoreGlobs && ignoreGlobs.find(glob => minimatch(node.parent.source.value, glob, { matchBase: true }))) {
+        if (ignoreGlobs && ignoreGlobs.find((glob) => minimatch(node.parent.source.value, glob, { matchBase: true }))) {
           return;
         }
 
         const scopeVariables = context.getScope().variables;
         const namespaceVariable = scopeVariables.find((variable) => variable.defs[0].node === node);
         const namespaceReferences = namespaceVariable.references;
-        const namespaceIdentifiers = namespaceReferences.map(reference => reference.identifier);
+        const namespaceIdentifiers = namespaceReferences.map((reference) => reference.identifier);
         const canFix = namespaceIdentifiers.length > 0 && !usesNamespaceAsObject(namespaceIdentifiers);
 
         context.report({
           node,
           message: `Unexpected namespace import.`,
-          fix: canFix && (fixer => {
+          fix: canFix && ((fixer) => {
             const scopeManager = context.getSourceCode().scopeManager;
             const fixes = [];
 
@@ -82,11 +81,10 @@ module.exports = {
             );
 
             // Replace the ImportNamespaceSpecifier with a list of ImportSpecifiers
-            const namedImportSpecifiers = importNames.map((importName) => (
-              importName === importLocalNames[importName]
-                ? importName
-                : `${importName} as ${importLocalNames[importName]}`
-            ));
+            const namedImportSpecifiers = importNames.map((importName) => importName === importLocalNames[importName]
+              ? importName
+              : `${importName} as ${importLocalNames[importName]}`,
+            );
             fixes.push(fixer.replaceText(node, `{ ${namedImportSpecifiers.join(', ')} }`));
 
             // Pass 2: Replace references to the namespace with references to the named imports
@@ -116,8 +114,9 @@ function usesNamespaceAsObject(namespaceIdentifiers) {
 
     // `namespace.x` or `namespace['x']`
     return (
-      parent && parent.type === 'MemberExpression' &&
-      (parent.property.type === 'Identifier' || parent.property.type === 'Literal')
+      parent
+      && parent.type === 'MemberExpression'
+      && (parent.property.type === 'Identifier' || parent.property.type === 'Literal')
     );
   });
 }
@@ -144,7 +143,7 @@ function getVariableNamesInScope(scopeManager, node) {
     currentNode = currentNode.parent;
     scope = scopeManager.acquire(currentNode, true);
   }
-  return new Set(scope.variables.concat(scope.upper.variables).map(variable => variable.name));
+  return new Set(scope.variables.concat(scope.upper.variables).map((variable) => variable.name));
 }
 
 /**
diff --git a/src/rules/no-nodejs-modules.js b/src/rules/no-nodejs-modules.js
index a87bff796f..82594bb603 100644
--- a/src/rules/no-nodejs-modules.js
+++ b/src/rules/no-nodejs-modules.js
@@ -4,7 +4,7 @@ import docsUrl from '../docsUrl';
 
 function reportIfMissing(context, node, allowed, name) {
   if (allowed.indexOf(name) === -1 && importType(name, context) === 'builtin') {
-    context.report(node, 'Do not import Node.js builtin module "' + name + '"');
+    context.report(node, `Do not import Node.js builtin module "${name}"`);
   }
 }
 
diff --git a/src/rules/no-relative-packages.js b/src/rules/no-relative-packages.js
index 6b0a627670..1d215519fd 100644
--- a/src/rules/no-relative-packages.js
+++ b/src/rules/no-relative-packages.js
@@ -47,7 +47,7 @@ function checkImportForRelativePackage(context, importPath, node) {
     context.report({
       node,
       message: `Relative import from another package is not allowed. Use \`${properImport}\` instead of \`${importPath}\``,
-      fix: fixer => fixer.replaceText(node, JSON.stringify(toPosixPath(properImport)))
+      fix: (fixer) => fixer.replaceText(node, JSON.stringify(toPosixPath(properImport)))
       ,
     });
   }
diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js
index fd8dcb302f..decd2ef7d2 100644
--- a/src/rules/no-relative-parent-imports.js
+++ b/src/rules/no-relative-parent-imports.js
@@ -18,7 +18,7 @@ module.exports = {
 
   create: function noRelativePackages(context) {
     const myPath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
-    if (myPath === '<text>') return {}; // can't check a non-file
+    if (myPath === '<text>') { return {}; } // can't check a non-file
 
     function checkSourceValue(sourceNode) {
       const depPath = sourceNode.value;
@@ -38,10 +38,7 @@ module.exports = {
       if (importType(relDepPath, context) === 'parent') {
         context.report({
           node: sourceNode,
-          message: 'Relative imports from parent directories are not allowed. ' +
-            `Please either pass what you're importing through at runtime ` +
-            `(dependency injection), move \`${basename(myPath)}\` to same ` +
-            `directory as \`${depPath}\` or consider making \`${depPath}\` a package.`,
+          message: `Relative imports from parent directories are not allowed. Please either pass what you're importing through at runtime (dependency injection), move \`${basename(myPath)}\` to same directory as \`${depPath}\` or consider making \`${depPath}\` a package.`,
         });
       }
     }
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 2293119592..bce9fd1a03 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -77,11 +77,9 @@ module.exports = {
     const restrictedPaths = options.zones || [];
     const basePath = options.basePath || process.cwd();
     const currentFilename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
-    const matchingZones = restrictedPaths.filter((zone) => {
-      return [].concat(zone.target)
-        .map(target => path.resolve(basePath, target))
-        .some(targetPath => isMatchingTargetPath(currentFilename, targetPath));
-    });
+    const matchingZones = restrictedPaths.filter((zone) => [].concat(zone.target)
+      .map((target) => path.resolve(basePath, target))
+      .some((targetPath) => isMatchingTargetPath(currentFilename, targetPath)));
 
     function isMatchingTargetPath(filename, targetPath) {
       if (isGlob(targetPath)) {
@@ -180,7 +178,7 @@ module.exports = {
     }
 
     function reportInvalidExceptions(validators, node) {
-      validators.forEach(validator => validator.reportInvalidException(node));
+      validators.forEach((validator) => validator.reportInvalidException(node));
     }
 
     function reportImportsInRestrictedZone(validators, node, importPath, customMessage) {
@@ -203,7 +201,7 @@ module.exports = {
 
       const isGlobPattern = areGlobPatterns.every((isGlob) => isGlob);
 
-      return allZoneFrom.map(singleZoneFrom => {
+      return allZoneFrom.map((singleZoneFrom) => {
         const absoluteFrom = path.resolve(basePath, singleZoneFrom);
 
         if (isGlobPattern) {
@@ -227,14 +225,14 @@ module.exports = {
           validators[index] = makePathValidators(zone.from, zone.except);
         }
 
-        const applicableValidatorsForImportPath = validators[index].filter(validator => validator.isPathRestricted(absoluteImportPath));
+        const applicableValidatorsForImportPath = validators[index].filter((validator) => validator.isPathRestricted(absoluteImportPath));
 
-        const validatorsWithInvalidExceptions = applicableValidatorsForImportPath.filter(validator => !validator.hasValidExceptions);
+        const validatorsWithInvalidExceptions = applicableValidatorsForImportPath.filter((validator) => !validator.hasValidExceptions);
         reportInvalidExceptions(validatorsWithInvalidExceptions, node);
 
         const applicableValidatorsForImportPathExcludingExceptions = applicableValidatorsForImportPath
-          .filter(validator => validator.hasValidExceptions)
-          .filter(validator => !validator.isPathException(absoluteImportPath));
+          .filter((validator) => validator.hasValidExceptions)
+          .filter((validator) => !validator.isPathException(absoluteImportPath));
         reportImportsInRestrictedZone(applicableValidatorsForImportPathExcludingExceptions, node, importPath, zone.message);
       });
     }
diff --git a/src/rules/no-unassigned-import.js b/src/rules/no-unassigned-import.js
index b790141927..0af9f2e9f3 100644
--- a/src/rules/no-unassigned-import.js
+++ b/src/rules/no-unassigned-import.js
@@ -24,16 +24,15 @@ function testIsAllow(globs, filename, source) {
     filePath = path.resolve(path.dirname(filename), source); // get source absolute path
   }
 
-  return globs.find(glob => (
-    minimatch(filePath, glob) ||
-    minimatch(filePath, path.join(process.cwd(), glob))
-  )) !== undefined;
+  return globs.find((glob) => minimatch(filePath, glob)
+    || minimatch(filePath, path.join(process.cwd(), glob)),
+  ) !== undefined;
 }
 
 function create(context) {
   const options = context.options[0] || {};
   const filename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
-  const isAllow = source => testIsAllow(options.allow, filename, source);
+  const isAllow = (source) => testIsAllow(options.allow, filename, source);
 
   return {
     ImportDeclaration(node) {
@@ -42,9 +41,11 @@ function create(context) {
       }
     },
     ExpressionStatement(node) {
-      if (node.expression.type === 'CallExpression' &&
-        isStaticRequire(node.expression) &&
-        !isAllow(node.expression.arguments[0].value)) {
+      if (
+        node.expression.type === 'CallExpression'
+        && isStaticRequire(node.expression)
+        && !isAllow(node.expression.arguments[0].value)
+      ) {
         report(context, node.expression);
       }
     },
@@ -62,19 +63,19 @@ module.exports = {
     },
     schema: [
       {
-        'type': 'object',
-        'properties': {
-          'devDependencies': { 'type': ['boolean', 'array'] },
-          'optionalDependencies': { 'type': ['boolean', 'array'] },
-          'peerDependencies': { 'type': ['boolean', 'array'] },
-          'allow': {
-            'type': 'array',
-            'items': {
-              'type': 'string',
+        type: 'object',
+        properties: {
+          devDependencies: { type: ['boolean', 'array'] },
+          optionalDependencies: { type: ['boolean', 'array'] },
+          peerDependencies: { type: ['boolean', 'array'] },
+          allow: {
+            type: 'array',
+            items: {
+              type: 'string',
             },
           },
         },
-        'additionalProperties': false,
+        additionalProperties: false,
       },
     ],
   },
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index bd8c524abb..4b09128a10 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -40,11 +40,12 @@ try {
       const { listFilesToProcess: originalListFilesToProcess } = require('eslint/lib/util/glob-util');
 
       listFilesToProcess = function (src, extensions) {
-        const patterns = src.reduce((carry, pattern) => {
-          return carry.concat(extensions.map((extension) => {
-            return /\*\*|\*\./.test(pattern) ? pattern : `${pattern}/**/*${extension}`;
-          }));
-        }, src.slice());
+        const patterns = src.reduce(
+          (carry, pattern) => carry.concat(
+            extensions.map((extension) => (/\*\*|\*\./).test(pattern) ? pattern : `${pattern}/**/*${extension}`),
+          ),
+          src,
+        );
 
         return originalListFilesToProcess(patterns);
       };
@@ -84,11 +85,11 @@ const DEFAULT = 'default';
 function forEachDeclarationIdentifier(declaration, cb) {
   if (declaration) {
     if (
-      declaration.type === FUNCTION_DECLARATION ||
-      declaration.type === CLASS_DECLARATION ||
-      declaration.type === TS_INTERFACE_DECLARATION ||
-      declaration.type === TS_TYPE_ALIAS_DECLARATION ||
-      declaration.type === TS_ENUM_DECLARATION
+      declaration.type === FUNCTION_DECLARATION
+      || declaration.type === CLASS_DECLARATION
+      || declaration.type === TS_INTERFACE_DECLARATION
+      || declaration.type === TS_TYPE_ALIAS_DECLARATION
+      || declaration.type === TS_ENUM_DECLARATION
     ) {
       cb(declaration.id.name);
     } else if (declaration.type === VARIABLE_DECLARATION) {
@@ -160,9 +161,7 @@ const visitorKeyMap = new Map();
 const ignoredFiles = new Set();
 const filesOutsideSrc = new Set();
 
-const isNodeModule = path => {
-  return /\/(node_modules)\//.test(path);
-};
+const isNodeModule = (path) => (/\/(node_modules)\//).test(path);
 
 /**
  * read all files matching the patterns in src and ignoreExports
@@ -191,7 +190,7 @@ const resolveFiles = (src, ignoreExports, context) => {
  */
 const prepareImportsAndExports = (srcFiles, context) => {
   const exportAll = new Map();
-  srcFiles.forEach(file => {
+  srcFiles.forEach((file) => {
     const exports = new Map();
     const imports = new Map();
     const currentExports = Exports.get(file, context);
@@ -207,7 +206,7 @@ const prepareImportsAndExports = (srcFiles, context) => {
       visitorKeyMap.set(file, visitorKeys);
       // dependencies === export * from
       const currentExportAll = new Set();
-      dependencies.forEach(getDependency => {
+      dependencies.forEach((getDependency) => {
         const dependency = getDependency();
         if (dependency === null) {
           return;
@@ -247,9 +246,11 @@ const prepareImportsAndExports = (srcFiles, context) => {
           return;
         }
         const localImport = imports.get(key) || new Set();
-        value.declarations.forEach(({ importedSpecifiers }) =>
-          importedSpecifiers.forEach(specifier => localImport.add(specifier)),
-        );
+        value.declarations.forEach(({ importedSpecifiers }) => {
+          importedSpecifiers.forEach((specifier) => {
+            localImport.add(specifier);
+          });
+        });
         imports.set(key, localImport);
       });
       importList.set(file, imports);
@@ -271,7 +272,7 @@ const prepareImportsAndExports = (srcFiles, context) => {
     exportList.set(file, exports);
   });
   exportAll.forEach((value, key) => {
-    value.forEach(val => {
+    value.forEach((val) => {
       const currentExports = exportList.get(val);
       if (currentExports) {
         const currentExport = currentExports.get(EXPORT_ALL_DECLARATION);
@@ -290,7 +291,7 @@ const determineUsage = () => {
     listValue.forEach((value, key) => {
       const exports = exportList.get(key);
       if (typeof exports !== 'undefined') {
-        value.forEach(currentImport => {
+        value.forEach((currentImport) => {
           let specifier;
           if (currentImport === IMPORT_NAMESPACE_SPECIFIER) {
             specifier = IMPORT_NAMESPACE_SPECIFIER;
@@ -313,7 +314,7 @@ const determineUsage = () => {
   });
 };
 
-const getSrc = src => {
+const getSrc = (src) => {
   if (src) {
     return src;
   }
@@ -347,33 +348,31 @@ const doPreparation = (src, ignoreExports, context) => {
   lastPrepareKey = prepareKey;
 };
 
-const newNamespaceImportExists = specifiers =>
-  specifiers.some(({ type }) => type === IMPORT_NAMESPACE_SPECIFIER);
+const newNamespaceImportExists = (specifiers) => specifiers.some(({ type }) => type === IMPORT_NAMESPACE_SPECIFIER);
 
-const newDefaultImportExists = specifiers =>
-  specifiers.some(({ type }) => type === IMPORT_DEFAULT_SPECIFIER);
+const newDefaultImportExists = (specifiers) => specifiers.some(({ type }) => type === IMPORT_DEFAULT_SPECIFIER);
 
-const fileIsInPkg = file => {
+const fileIsInPkg = (file) => {
   const { path, pkg } = readPkgUp({ cwd: file });
   const basePath = dirname(path);
 
-  const checkPkgFieldString = pkgField => {
+  const checkPkgFieldString = (pkgField) => {
     if (join(basePath, pkgField) === file) {
       return true;
     }
   };
 
-  const checkPkgFieldObject = pkgField => {
+  const checkPkgFieldObject = (pkgField) => {
     const pkgFieldFiles = values(pkgField)
       .filter((value) => typeof value !== 'boolean')
-      .map(value => join(basePath, value));
+      .map((value) => join(basePath, value));
 
     if (includes(pkgFieldFiles, file)) {
       return true;
     }
   };
 
-  const checkPkgField = pkgField => {
+  const checkPkgField = (pkgField) => {
     if (typeof pkgField === 'string') {
       return checkPkgFieldString(pkgField);
     }
@@ -452,7 +451,7 @@ module.exports = {
           missingExports: { enum: [false] },
         },
       },
-      anyOf:[{
+      anyOf: [{
         not: {
           properties: {
             unusedExports: { enum: [true] },
@@ -480,7 +479,7 @@ module.exports = {
     }],
   },
 
-  create: context => {
+  create(context) {
     const {
       src,
       ignoreExports = [],
@@ -494,7 +493,7 @@ module.exports = {
 
     const file = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
 
-    const checkExportPresence = node => {
+    const checkExportPresence = (node) => {
       if (!missingExports) {
         return;
       }
@@ -589,7 +588,7 @@ module.exports = {
      *
      * update lists of existing exports during runtime
      */
-    const updateExportUsage = node => {
+    const updateExportUsage = (node) => {
       if (ignoredFiles.has(file)) {
         return;
       }
@@ -611,7 +610,7 @@ module.exports = {
         }
         if (type === EXPORT_NAMED_DECLARATION) {
           if (specifiers.length > 0) {
-            specifiers.forEach(specifier => {
+            specifiers.forEach((specifier) => {
               if (specifier.exported) {
                 newExportIdentifiers.add(specifier.exported.name || specifier.exported.value);
               }
@@ -631,7 +630,7 @@ module.exports = {
       });
 
       // new export identifiers added: add to map of new exports
-      newExportIdentifiers.forEach(key => {
+      newExportIdentifiers.forEach((key) => {
         if (!exports.has(key)) {
           newExports.set(key, { whereUsed: new Set() });
         }
@@ -655,7 +654,7 @@ module.exports = {
      *
      * update lists of existing imports during runtime
      */
-    const updateImportUsage = node => {
+    const updateImportUsage = (node) => {
       if (!unusedExports) {
         return;
       }
@@ -686,9 +685,11 @@ module.exports = {
         if (value.has(IMPORT_DEFAULT_SPECIFIER)) {
           oldDefaultImports.add(key);
         }
-        value.forEach(val => {
-          if (val !== IMPORT_NAMESPACE_SPECIFIER &&
-              val !== IMPORT_DEFAULT_SPECIFIER) {
+        value.forEach((val) => {
+          if (
+            val !== IMPORT_NAMESPACE_SPECIFIER
+            && val !== IMPORT_DEFAULT_SPECIFIER
+          ) {
             oldImports.set(val, key);
           }
         });
@@ -716,14 +717,14 @@ module.exports = {
         },
       });
 
-      node.body.forEach(astNode => {
+      node.body.forEach((astNode) => {
         let resolvedPath;
 
         // support for export { value } from 'module'
         if (astNode.type === EXPORT_NAMED_DECLARATION) {
           if (astNode.source) {
             resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context);
-            astNode.specifiers.forEach(specifier => {
+            astNode.specifiers.forEach((specifier) => {
               const name = specifier.local.name || specifier.local.value;
               if (name === DEFAULT) {
                 newDefaultImports.add(resolvedPath);
@@ -757,17 +758,15 @@ module.exports = {
             newDefaultImports.add(resolvedPath);
           }
 
-          astNode.specifiers.forEach(specifier => {
-            if (specifier.type === IMPORT_DEFAULT_SPECIFIER ||
-                specifier.type === IMPORT_NAMESPACE_SPECIFIER) {
-              return;
-            }
-            newImports.set(specifier.imported.name || specifier.imported.value, resolvedPath);
-          });
+          astNode.specifiers
+            .filter((specifier) => specifier.type !== IMPORT_DEFAULT_SPECIFIER && specifier.type !== IMPORT_NAMESPACE_SPECIFIER)
+            .forEach((specifier) => {
+              newImports.set(specifier.imported.name || specifier.imported.value, resolvedPath);
+            });
         }
       });
 
-      newExportAll.forEach(value => {
+      newExportAll.forEach((value) => {
         if (!oldExportAll.has(value)) {
           let imports = oldImportPaths.get(value);
           if (typeof imports === 'undefined') {
@@ -795,7 +794,7 @@ module.exports = {
         }
       });
 
-      oldExportAll.forEach(value => {
+      oldExportAll.forEach((value) => {
         if (!newExportAll.has(value)) {
           const imports = oldImportPaths.get(value);
           imports.delete(EXPORT_ALL_DECLARATION);
@@ -810,7 +809,7 @@ module.exports = {
         }
       });
 
-      newDefaultImports.forEach(value => {
+      newDefaultImports.forEach((value) => {
         if (!oldDefaultImports.has(value)) {
           let imports = oldImportPaths.get(value);
           if (typeof imports === 'undefined') {
@@ -838,7 +837,7 @@ module.exports = {
         }
       });
 
-      oldDefaultImports.forEach(value => {
+      oldDefaultImports.forEach((value) => {
         if (!newDefaultImports.has(value)) {
           const imports = oldImportPaths.get(value);
           imports.delete(IMPORT_DEFAULT_SPECIFIER);
@@ -853,7 +852,7 @@ module.exports = {
         }
       });
 
-      newNamespaceImports.forEach(value => {
+      newNamespaceImports.forEach((value) => {
         if (!oldNamespaceImports.has(value)) {
           let imports = oldImportPaths.get(value);
           if (typeof imports === 'undefined') {
@@ -881,7 +880,7 @@ module.exports = {
         }
       });
 
-      oldNamespaceImports.forEach(value => {
+      oldNamespaceImports.forEach((value) => {
         if (!newNamespaceImports.has(value)) {
           const imports = oldImportPaths.get(value);
           imports.delete(IMPORT_NAMESPACE_SPECIFIER);
@@ -941,16 +940,16 @@ module.exports = {
     };
 
     return {
-      'Program:exit': node => {
+      'Program:exit'(node) {
         updateExportUsage(node);
         updateImportUsage(node);
         checkExportPresence(node);
       },
-      'ExportDefaultDeclaration': node => {
+      ExportDefaultDeclaration(node) {
         checkUsage(node, IMPORT_DEFAULT_SPECIFIER);
       },
-      'ExportNamedDeclaration': node => {
-        node.specifiers.forEach(specifier => {
+      ExportNamedDeclaration(node) {
+        node.specifiers.forEach((specifier) => {
           checkUsage(node, specifier.exported.name || specifier.exported.value);
         });
         forEachDeclarationIdentifier(node.declaration, (name) => {
diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index a328be2465..343a4f6230 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -25,7 +25,7 @@ import docsUrl from '../docsUrl';
 function toRelativePath(relativePath) {
   const stripped = relativePath.replace(/\/$/g, ''); // Remove trailing /
 
-  return /^((\.\.)|(\.))($|\/)/.test(stripped) ? stripped : `./${stripped}`;
+  return (/^((\.\.)|(\.))($|\/)/).test(stripped) ? stripped : `./${stripped}`;
 }
 
 function normalize(fn) {
@@ -71,7 +71,7 @@ module.exports = {
           node: source,
           // Note: Using messageIds is not possible due to the support for ESLint 2 and 3
           message: `Useless path segments for "${importPath}", should be "${proposedPath}"`,
-          fix: fixer => proposedPath && fixer.replaceText(source, JSON.stringify(proposedPath)),
+          fix: (fixer) => proposedPath && fixer.replaceText(source, JSON.stringify(proposedPath)),
         });
       }
 
diff --git a/src/rules/no-webpack-loader-syntax.js b/src/rules/no-webpack-loader-syntax.js
index faedeb4373..6ca7d603d6 100644
--- a/src/rules/no-webpack-loader-syntax.js
+++ b/src/rules/no-webpack-loader-syntax.js
@@ -3,9 +3,7 @@ import docsUrl from '../docsUrl';
 
 function reportIfNonStandard(context, node, name) {
   if (name && name.indexOf('!') !== -1) {
-    context.report(node, `Unexpected '!' in '${name}'. ` +
-      'Do not use import syntax to configure webpack loaders.',
-    );
+    context.report(node, `Unexpected '!' in '${name}'. Do not use import syntax to configure webpack loaders.`);
   }
 }
 
diff --git a/src/rules/order.js b/src/rules/order.js
index bdead9d40c..5921989d2b 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -13,7 +13,7 @@ const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index'];
 
 function reverse(array) {
   return array.map(function (v) {
-    return Object.assign({}, v, { rank: -v.rank });
+    return { ...v, rank: -v.rank };
   }).reverse();
 }
 
@@ -111,9 +111,9 @@ function findEndOfLineWithComments(sourceCode, node) {
 }
 
 function commentOnSameLineAs(node) {
-  return token => (token.type === 'Block' ||  token.type === 'Line') &&
-      token.loc.start.line === token.loc.end.line &&
-      token.loc.end.line === node.loc.end.line;
+  return (token) => (token.type === 'Block' ||  token.type === 'Line')
+      && token.loc.start.line === token.loc.end.line
+      && token.loc.end.line === node.loc.end.line;
 }
 
 function findStartOfLineWithComments(sourceCode, node) {
@@ -130,13 +130,13 @@ function findStartOfLineWithComments(sourceCode, node) {
 }
 
 function isRequireExpression(expr) {
-  return expr != null &&
-    expr.type === 'CallExpression' &&
-    expr.callee != null &&
-    expr.callee.name === 'require' &&
-    expr.arguments != null &&
-    expr.arguments.length === 1 &&
-    expr.arguments[0].type === 'Literal';
+  return expr != null
+    && expr.type === 'CallExpression'
+    && expr.callee != null
+    && expr.callee.name === 'require'
+    && expr.arguments != null
+    && expr.arguments.length === 1
+    && expr.arguments[0].type === 'Literal';
 }
 
 function isSupportedRequireModule(node) {
@@ -147,16 +147,16 @@ function isSupportedRequireModule(node) {
     return false;
   }
   const decl = node.declarations[0];
-  const isPlainRequire = decl.id &&
-    (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') &&
-    isRequireExpression(decl.init);
-  const isRequireWithMemberExpression = decl.id &&
-    (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') &&
-    decl.init != null &&
-    decl.init.type === 'CallExpression' &&
-    decl.init.callee != null &&
-    decl.init.callee.type === 'MemberExpression' &&
-    isRequireExpression(decl.init.callee.object);
+  const isPlainRequire = decl.id
+    && (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern')
+    && isRequireExpression(decl.init);
+  const isRequireWithMemberExpression = decl.id
+    && (decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern')
+    && decl.init != null
+    && decl.init.type === 'CallExpression'
+    && decl.init.callee != null
+    && decl.init.callee.type === 'MemberExpression'
+    && isRequireExpression(decl.init.callee.object);
   return isPlainRequire || isRequireWithMemberExpression;
 }
 
@@ -211,7 +211,7 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
 
   let newCode = sourceCode.text.substring(secondRootStart, secondRootEnd);
   if (newCode[newCode.length - 1] !== '\n') {
-    newCode = newCode + '\n';
+    newCode = `${newCode}\n`;
   }
 
   const firstImport = `${makeImportDescription(firstNode)} of \`${firstNode.displayName}\``;
@@ -222,21 +222,19 @@ function fixOutOfOrder(context, firstNode, secondNode, order) {
     context.report({
       node: secondNode.node,
       message,
-      fix: canFix && (fixer =>
-        fixer.replaceTextRange(
-          [firstRootStart, secondRootEnd],
-          newCode + sourceCode.text.substring(firstRootStart, secondRootStart),
-        )),
+      fix: canFix && ((fixer) => fixer.replaceTextRange(
+        [firstRootStart, secondRootEnd],
+        newCode + sourceCode.text.substring(firstRootStart, secondRootStart),
+      )),
     });
   } else if (order === 'after') {
     context.report({
       node: secondNode.node,
       message,
-      fix: canFix && (fixer =>
-        fixer.replaceTextRange(
-          [secondRootStart, firstRootEnd],
-          sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode,
-        )),
+      fix: canFix && ((fixer) => fixer.replaceTextRange(
+        [secondRootStart, firstRootEnd],
+        sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode,
+      )),
     });
   }
 }
@@ -285,8 +283,8 @@ const getNormalizedValue = (node, toLowerCase) => {
 function getSorter(alphabetizeOptions) {
   const multiplier = alphabetizeOptions.order === 'asc' ? 1 : -1;
   const orderImportKind = alphabetizeOptions.orderImportKind;
-  const multiplierImportKind = orderImportKind !== 'ignore' &&
-    (alphabetizeOptions.orderImportKind === 'asc' ? 1 : -1);
+  const multiplierImportKind = orderImportKind !== 'ignore'
+    && (alphabetizeOptions.orderImportKind === 'asc' ? 1 : -1);
 
   return function importsSorter(nodeA, nodeB) {
     const importA = getNormalizedValue(nodeA, alphabetizeOptions.caseInsensitive);
@@ -303,7 +301,7 @@ function getSorter(alphabetizeOptions) {
 
       for (let i = 0; i < Math.min(a, b); i++) {
         result = compareString(A[i], B[i]);
-        if (result) break;
+        if (result) { break; }
       }
 
       if (!result && a !== b) {
@@ -368,7 +366,7 @@ function computePathRank(ranks, pathGroups, path, maxPosition) {
   for (let i = 0, l = pathGroups.length; i < l; i++) {
     const { pattern, patternOptions, group, position = 1 } = pathGroups[i];
     if (minimatch(path, pattern, patternOptions || { nocomment: true })) {
-      return ranks[group] + (position / maxPosition);
+      return ranks[group] + position / maxPosition;
     }
   }
 }
@@ -399,7 +397,7 @@ function computeRank(context, ranks, importEntry, excludedImportTypes) {
 function registerNode(context, importEntry, ranks, imported, excludedImportTypes) {
   const rank = computeRank(context, ranks, importEntry, excludedImportTypes);
   if (rank !== -1) {
-    imported.push(Object.assign({}, importEntry, { rank }));
+    imported.push({ ...importEntry, rank });
   }
 }
 
@@ -408,15 +406,15 @@ function getRequireBlock(node) {
   // Handle cases like `const baz = require('foo').bar.baz`
   // and `const foo = require('foo')()`
   while (
-    (n.parent.type === 'MemberExpression' && n.parent.object === n) ||
-    (n.parent.type === 'CallExpression' && n.parent.callee === n)
+    n.parent.type === 'MemberExpression' && n.parent.object === n
+    || n.parent.type === 'CallExpression' && n.parent.callee === n
   ) {
     n = n.parent;
   }
   if (
-    n.parent.type === 'VariableDeclarator' &&
-    n.parent.parent.type === 'VariableDeclaration' &&
-    n.parent.parent.parent.type === 'Program'
+    n.parent.type === 'VariableDeclarator'
+    && n.parent.parent.type === 'VariableDeclaration'
+    && n.parent.parent.parent.type === 'Program'
   ) {
     return n.parent.parent.parent;
   }
@@ -434,11 +432,10 @@ function convertGroupsToRanks(groups) {
     }
     group.forEach(function (groupItem) {
       if (types.indexOf(groupItem) === -1) {
-        throw new Error('Incorrect configuration of the rule: Unknown type `' +
-          JSON.stringify(groupItem) + '`');
+        throw new Error(`Incorrect configuration of the rule: Unknown type \`${JSON.stringify(groupItem)}\``);
       }
       if (res[groupItem] !== undefined) {
-        throw new Error('Incorrect configuration of the rule: `' + groupItem + '` is duplicated');
+        throw new Error(`Incorrect configuration of the rule: \`${groupItem}\` is duplicated`);
       }
       res[groupItem] = index * 2;
     });
@@ -476,7 +473,7 @@ function convertPathGroupsForRanks(pathGroups) {
       before[group].push(index);
     }
 
-    return Object.assign({}, pathGroup, { position });
+    return { ...pathGroup, position };
   });
 
   let maxPosition = 1;
@@ -520,7 +517,7 @@ function removeNewLineAfterImport(context, currentImport, previousImport) {
     findEndOfLineWithComments(sourceCode, prevRoot),
     findStartOfLineWithComments(sourceCode, currRoot),
   ];
-  if (/^\s*$/.test(sourceCode.text.substring(rangeToRemove[0], rangeToRemove[1]))) {
+  if ((/^\s*$/).test(sourceCode.text.substring(rangeToRemove[0], rangeToRemove[1]))) {
     return (fixer) => fixer.removeRange(rangeToRemove);
   }
   return undefined;
@@ -535,9 +532,7 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, di
 
     return linesBetweenImports.filter((line) => !line.trim().length).length;
   };
-  const getIsStartOfDistinctGroup = (currentImport, previousImport) => {
-    return currentImport.rank - 1 >= previousImport.rank;
-  };
+  const getIsStartOfDistinctGroup = (currentImport, previousImport) => currentImport.rank - 1 >= previousImport.rank;
   let previousImport = imported[0];
 
   imported.slice(1).forEach(function (currentImport) {
@@ -547,7 +542,7 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, di
     if (newlinesBetweenImports === 'always'
         || newlinesBetweenImports === 'always-and-inside-groups') {
       if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
-        if (distinctGroup || (!distinctGroup && isStartOfDistinctGroup)) {
+        if (distinctGroup || !distinctGroup && isStartOfDistinctGroup) {
           context.report({
             node: previousImport.node,
             message: 'There should be at least one empty line between import groups',
@@ -556,7 +551,7 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, di
         }
       } else if (emptyLinesBetween > 0
         && newlinesBetweenImports !== 'always-and-inside-groups') {
-        if ((distinctGroup && currentImport.rank === previousImport.rank) || (!distinctGroup && !isStartOfDistinctGroup)) {
+        if (distinctGroup && currentImport.rank === previousImport.rank || !distinctGroup && !isStartOfDistinctGroup) {
           context.report({
             node: previousImport.node,
             message: 'There should be no empty line within import group',
@@ -675,7 +670,7 @@ module.exports = {
   create: function importOrderRule(context) {
     const options = context.options[0] || {};
     const newlinesBetweenImports = options['newlines-between'] || 'ignore';
-    const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external', 'object']);
+    const pathGroupsExcludedImportTypes = new Set(options.pathGroupsExcludedImportTypes || ['builtin', 'external', 'object']);
     const alphabetize = getAlphabetizeConfig(options);
     const distinctGroup = options.distinctGroup == null ? defaultDistinctGroup : !!options.distinctGroup;
     let ranks;
diff --git a/src/rules/prefer-default-export.js b/src/rules/prefer-default-export.js
index 32ef5004fa..581f02502e 100644
--- a/src/rules/prefer-default-export.js
+++ b/src/rules/prefer-default-export.js
@@ -15,7 +15,7 @@ module.exports = {
     },
     schema: [{
       type: 'object',
-      properties:{
+      properties: {
         target: {
           type: 'string',
           enum: ['single', 'any'],
@@ -51,11 +51,11 @@ module.exports = {
     }
 
     return {
-      'ExportDefaultSpecifier': function () {
+      ExportDefaultSpecifier() {
         hasDefaultExport = true;
       },
 
-      'ExportSpecifier': function (node) {
+      ExportSpecifier(node) {
         if ((node.exported.name || node.exported.value) === 'default') {
           hasDefaultExport = true;
         } else {
@@ -64,17 +64,17 @@ module.exports = {
         }
       },
 
-      'ExportNamedDeclaration': function (node) {
+      ExportNamedDeclaration(node) {
         // if there are specifiers, node.declaration should be null
-        if (!node.declaration) return;
+        if (!node.declaration) { return; }
 
         const { type } = node.declaration;
 
         if (
-          type === 'TSTypeAliasDeclaration' ||
-          type === 'TypeAlias' ||
-          type === 'TSInterfaceDeclaration' ||
-          type === 'InterfaceDeclaration'
+          type === 'TSTypeAliasDeclaration'
+          || type === 'TypeAlias'
+          || type === 'TSInterfaceDeclaration'
+          || type === 'InterfaceDeclaration'
         ) {
           specifierExportCount++;
           hasTypeExport = true;
@@ -93,15 +93,15 @@ module.exports = {
         namedExportNode = node;
       },
 
-      'ExportDefaultDeclaration': function () {
+      ExportDefaultDeclaration() {
         hasDefaultExport = true;
       },
 
-      'ExportAllDeclaration': function () {
+      ExportAllDeclaration() {
         hasStarExport = true;
       },
 
-      'Program:exit': function () {
+      'Program:exit'() {
         if (hasDefaultExport || hasStarExport || hasTypeExport) {
           return;
         }
diff --git a/tests/src/cli.js b/tests/src/cli.js
index e6afd8e441..8a73454878 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -21,7 +21,7 @@ describe('CLI regression tests', function () {
           rulePaths: ['./src/rules'],
           overrideConfig: {
             rules: {
-              'named': 2,
+              named: 2,
             },
           },
           plugins: { 'eslint-plugin-import': importPlugin },
@@ -32,7 +32,7 @@ describe('CLI regression tests', function () {
           configFile: './tests/files/issue210.config.js',
           rulePaths: ['./src/rules'],
           rules: {
-            'named': 2,
+            named: 2,
           },
         });
         cli.addPlugin('eslint-plugin-import', importPlugin);
@@ -78,7 +78,7 @@ describe('CLI regression tests', function () {
     it('throws an error on invalid JSON', () => {
       const invalidJSON = './tests/files/just-json-files/invalid.json';
       if (eslint) {
-        return eslint.lintFiles([invalidJSON]).then(results => {
+        return eslint.lintFiles([invalidJSON]).then((results) => {
           expect(results).to.eql(
             [
               {
@@ -97,16 +97,16 @@ describe('CLI regression tests', function () {
                   },
                 ],
                 errorCount: 1,
-                ...(semver.satisfies(eslintPkg.version, '>= 7.32 || ^8.0.0') && {
+                ...semver.satisfies(eslintPkg.version, '>= 7.32 || ^8.0.0') && {
                   fatalErrorCount: 0,
-                }),
+                },
                 warningCount: 0,
                 fixableErrorCount: 0,
                 fixableWarningCount: 0,
                 source: results[0].source, // NewLine-characters might differ depending on git-settings
-                ...(semver.satisfies(eslintPkg.version, '>= 8.8') && {
+                ...semver.satisfies(eslintPkg.version, '>= 8.8') && {
                   suppressedMessages: [],
-                }),
+                },
                 usedDeprecatedRules: results[0].usedDeprecatedRules, // we don't care about this one
               },
             ],
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 86c1915968..1dd6e88014 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -58,11 +58,10 @@ describe('ExportMap', function () {
     const firstAccess = ExportMap.get('./named-exports', fakeContext);
     expect(firstAccess).to.exist;
 
-    const differentSettings = Object.assign(
-      {},
-      fakeContext,
-      { parserPath: 'espree' },
-    );
+    const differentSettings = {
+      ...fakeContext,
+      parserPath: 'espree',
+    };
 
     expect(ExportMap.get('./named-exports', differentSettings))
       .to.exist.and
@@ -320,17 +319,19 @@ describe('ExportMap', function () {
     });
     it(`'has' circular reference`, function () {
       expect(ExportMap.get('./narcissist', fakeContext))
-        .to.exist.and.satisfy(m => m.has('soGreat'));
+        .to.exist.and.satisfy((m) => m.has('soGreat'));
     });
     it(`can 'get' circular reference`, function () {
       expect(ExportMap.get('./narcissist', fakeContext))
-        .to.exist.and.satisfy(m => m.get('soGreat') != null);
+        .to.exist.and.satisfy((m) => m.get('soGreat') != null);
     });
   });
 
   context('issue #478: never parse non-whitelist extensions', function () {
-    const context = Object.assign({}, fakeContext,
-      { settings: { 'import/extensions': ['.js'] } });
+    const context = {
+      ...fakeContext,
+      settings: { 'import/extensions': ['.js'] },
+    };
 
     let imports;
     before('load imports', function () {
@@ -359,11 +360,13 @@ describe('ExportMap', function () {
     configs.forEach(([description, parserConfig]) => {
 
       describe(description, function () {
-        const context = Object.assign({}, fakeContext,
-          { settings: {
+        const context = {
+          ...fakeContext,
+          settings: {
             'import/extensions': ['.js'],
             'import/parsers': parserConfig,
-          } });
+          },
+        };
 
         let imports;
         before('load imports', function () {
@@ -404,30 +407,24 @@ describe('ExportMap', function () {
         });
 
         it('should cache tsconfig until tsconfigRootDir parser option changes', function () {
-          const customContext = Object.assign(
-            {},
-            context,
-            {
-              parserOptions: {
-                tsconfigRootDir: null,
-              },
+          const customContext = {
+            ...context,
+            parserOptions: {
+              tsconfigRootDir: null,
             },
-          );
+          };
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(0);
           ExportMap.parse('./baz.ts', 'export const baz = 5', customContext);
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(1);
           ExportMap.parse('./baz.ts', 'export const baz = 5', customContext);
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(1);
 
-          const differentContext = Object.assign(
-            {},
-            context,
-            {
-              parserOptions: {
-                tsconfigRootDir: process.cwd(),
-              },
+          const differentContext = {
+            ...context,
+            parserOptions: {
+              tsconfigRootDir: process.cwd(),
             },
-          );
+          };
 
           ExportMap.parse('./baz.ts', 'export const baz = 5', differentContext);
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(2);
@@ -460,7 +457,7 @@ describe('ExportMap', function () {
 
     for (const [testFile, expectedRegexResult] of testFiles) {
       it(`works for ${testFile} (${expectedRegexResult})`, function () {
-        const content = fs.readFileSync('./tests/files/' + testFile, 'utf8');
+        const content = fs.readFileSync(`./tests/files/${testFile}`, 'utf8');
         expect(testUnambiguous(content)).to.equal(expectedRegexResult);
       });
     }
diff --git a/tests/src/core/hash.js b/tests/src/core/hash.js
index e75783fb06..1d6a9eb85c 100644
--- a/tests/src/core/hash.js
+++ b/tests/src/core/hash.js
@@ -7,7 +7,7 @@ const createHash = require('crypto').createHash;
 function expectHash(actualHash, expectedString) {
   const expectedHash = createHash('sha256');
   expectedHash.update(expectedString);
-  expect(actualHash.digest('hex'), 'to be a hex digest of sha256 hash of string <' + expectedString + '>').to.equal(expectedHash.digest('hex'));
+  expect(actualHash.digest('hex'), `to be a hex digest of sha256 hash of string <${expectedString}>`).to.equal(expectedHash.digest('hex'));
 }
 
 describe('hash', function () {
diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index 4ab8370ed2..9c59453602 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -13,9 +13,19 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
   const eslintParserPath = require.resolve('./eslintParser');
   let content;
 
-  before((done) =>
-    fs.readFile(path, { encoding: 'utf8' },
-      (err, f) => { if (err) { done(err); } else { content = f; done(); }}));
+  before((done) => {
+    fs.readFile(
+      path,
+      { encoding: 'utf8' },
+      (err, f) => {
+        if (err) {
+          done(err);
+        } else {
+          content = f; done();
+        }
+      },
+    );
+  });
 
   it('doesn\'t support JSX by default', function () {
     expect(() => parse(path, content, { parserPath: 'espree' })).to.throw(Error);
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index 05a6aaeb68..6b69fb7f12 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -21,32 +21,38 @@ describe('resolve', function () {
   it('resolves via a custom resolver with interface version 1', function () {
     const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' });
 
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(utils.testFilePath('./bar.jsx'));
 
-    expect(resolve( '../files/exception'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('exception.js'); } }),
+    expect(resolve(
+      '../files/exception',
+      { ...testContext, getFilename() { return utils.getFilename('exception.js'); } },
     )).to.equal(undefined);
 
-    expect(resolve( '../files/not-found'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('not-found.js'); } }),
+    expect(resolve(
+      '../files/not-found',
+      { ...testContext, getFilename() { return utils.getFilename('not-found.js'); } },
     )).to.equal(undefined);
   });
 
   it('resolves via a custom resolver with interface version 1 assumed if not specified', function () {
     const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' });
 
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(utils.testFilePath('./bar.jsx'));
 
-    expect(resolve( '../files/exception'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('exception.js'); } }),
+    expect(resolve(
+      '../files/exception',
+      { ...testContext, getFilename() { return utils.getFilename('exception.js'); } },
     )).to.equal(undefined);
 
-    expect(resolve( '../files/not-found'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('not-found.js'); } }),
+    expect(resolve(
+      '../files/not-found',
+      { ...testContext, getFilename() { return utils.getFilename('not-found.js'); } },
     )).to.equal(undefined);
   });
 
@@ -57,21 +63,24 @@ describe('resolve', function () {
       testContextReports.push(reportInfo);
     };
 
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(utils.testFilePath('./bar.jsx'));
 
     testContextReports.length = 0;
-    expect(resolve( '../files/exception'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('exception.js'); } }),
+    expect(resolve(
+      '../files/exception',
+      { ...testContext, getFilename() { return utils.getFilename('exception.js'); } },
     )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>');
     expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
 
     testContextReports.length = 0;
-    expect(resolve( '../files/not-found'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('not-found.js'); } }),
+    expect(resolve(
+      '../files/not-found',
+      { ...testContext, getFilename() { return utils.getFilename('not-found.js'); } },
     )).to.equal(undefined);
     expect(testContextReports.length).to.equal(0);
   });
@@ -79,32 +88,36 @@ describe('resolve', function () {
   it('respects import/resolver as array of strings', function () {
     const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
 
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
   it('respects import/resolver as object', function () {
     const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } });
 
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
   it('respects import/resolver as array of objects', function () {
     const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
 
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
   it('finds resolvers from the source files rather than eslint-module-utils', function () {
-    const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } });
+    const testContext = utils.testContext({ 'import/resolver': { foo: {} } });
 
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(utils.testFilePath('./bar.jsx'));
   });
 
@@ -116,8 +129,9 @@ describe('resolve', function () {
     };
 
     testContextReports.length = 0;
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config');
@@ -132,8 +146,9 @@ describe('resolve', function () {
       testContextReports.push(reportInfo);
     };
     testContextReports.length = 0;
-    expect(resolve( '../files/foo'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('foo.js'); } }),
+    expect(resolve(
+      '../files/foo',
+      { ...testContext, getFilename() { return utils.getFilename('foo.js'); } },
     )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`);
@@ -141,10 +156,11 @@ describe('resolve', function () {
   });
 
   it('respects import/resolve extensions', function () {
-    const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] } });
+    const testContext = utils.testContext({ 'import/resolve': { extensions: ['.jsx'] } });
 
-    expect(resolve( './jsx/MyCoolComponent'
-      , testContext,
+    expect(resolve(
+      './jsx/MyCoolComponent',
+      testContext,
     )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx'));
   });
 
@@ -155,8 +171,9 @@ describe('resolve', function () {
       testContextReports.push(reportInfo);
     };
 
-    expect(resolve( '../files/exception'
-      , Object.assign({}, testContext, { getFilename() { return utils.getFilename('exception.js'); } }),
+    expect(resolve(
+      '../files/exception',
+      { ...testContext, getFilename() { return utils.getFilename('exception.js'); } },
     )).to.equal(undefined);
     expect(testContextReports[0]).to.be.an('object');
     expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>');
@@ -172,32 +189,38 @@ describe('resolve', function () {
     it('resolves via a custom resolver with interface version 1', function () {
       const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-v1' });
 
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(utils.testFilePath('./bar.jsx'));
 
-      expect(resolve( '../files/exception'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } }),
+      expect(resolve(
+        '../files/exception',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } },
       )).to.equal(undefined);
 
-      expect(resolve( '../files/not-found'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } }),
+      expect(resolve(
+        '../files/not-found',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } },
       )).to.equal(undefined);
     });
 
     it('resolves via a custom resolver with interface version 1 assumed if not specified', function () {
       const testContext = utils.testContext({ 'import/resolver': './foo-bar-resolver-no-version' });
 
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(utils.testFilePath('./bar.jsx'));
 
-      expect(resolve( '../files/exception'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } }),
+      expect(resolve(
+        '../files/exception',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } },
       )).to.equal(undefined);
 
-      expect(resolve( '../files/not-found'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } }),
+      expect(resolve(
+        '../files/not-found',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } },
       )).to.equal(undefined);
     });
 
@@ -208,21 +231,24 @@ describe('resolve', function () {
         testContextReports.push(reportInfo);
       };
 
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(utils.testFilePath('./bar.jsx'));
 
       testContextReports.length = 0;
-      expect(resolve( '../files/exception'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } }),
+      expect(resolve(
+        '../files/exception',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } },
       )).to.equal(undefined);
       expect(testContextReports[0]).to.be.an('object');
       expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: foo-bar-resolver-v2 resolve test exception\n<stack-was-here>');
       expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 });
 
       testContextReports.length = 0;
-      expect(resolve( '../files/not-found'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } }),
+      expect(resolve(
+        '../files/not-found',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('not-found.js'); } },
       )).to.equal(undefined);
       expect(testContextReports.length).to.equal(0);
     });
@@ -230,32 +256,36 @@ describe('resolve', function () {
     it('respects import/resolver as array of strings', function () {
       const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
 
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(utils.testFilePath('./bar.jsx'));
     });
 
     it('respects import/resolver as object', function () {
       const testContext = utils.testContext({ 'import/resolver': { './foo-bar-resolver-v2': {} } });
 
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(utils.testFilePath('./bar.jsx'));
     });
 
     it('respects import/resolver as array of objects', function () {
       const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
 
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(utils.testFilePath('./bar.jsx'));
     });
 
     it('finds resolvers from the source files rather than eslint-module-utils', function () {
-      const testContext = utils.testContext({ 'import/resolver': { 'foo': {} } });
+      const testContext = utils.testContext({ 'import/resolver': { foo: {} } });
 
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(utils.testFilePath('./bar.jsx'));
     });
 
@@ -267,8 +297,9 @@ describe('resolve', function () {
       };
 
       testContextReports.length = 0;
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(undefined);
       expect(testContextReports[0]).to.be.an('object');
       expect(testContextReports[0].message).to.equal('Resolve error: invalid resolver config');
@@ -283,8 +314,9 @@ describe('resolve', function () {
         testContextReports.push(reportInfo);
       };
       testContextReports.length = 0;
-      expect(resolve( '../files/foo'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } }),
+      expect(resolve(
+        '../files/foo',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('foo.js'); } },
       )).to.equal(undefined);
       expect(testContextReports[0]).to.be.an('object');
       expect(testContextReports[0].message).to.equal(`Resolve error: ${resolverName} with invalid interface loaded as resolver`);
@@ -292,10 +324,11 @@ describe('resolve', function () {
     });
 
     it('respects import/resolve extensions', function () {
-      const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] } });
+      const testContext = utils.testContext({ 'import/resolve': { extensions: ['.jsx'] } });
 
-      expect(resolve( './jsx/MyCoolComponent'
-        , testContext,
+      expect(resolve(
+        './jsx/MyCoolComponent',
+        testContext,
       )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx'));
     });
 
@@ -306,8 +339,9 @@ describe('resolve', function () {
         testContextReports.push(reportInfo);
       };
 
-      expect(resolve( '../files/exception'
-        , Object.assign({}, testContext, { getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } }),
+      expect(resolve(
+        '../files/exception',
+        { ...testContext, getFilename: unexpectedCallToGetFilename, getPhysicalFilename() { return utils.getFilename('exception.js'); } },
       )).to.equal(undefined);
       expect(testContextReports[0]).to.be.an('object');
       expect(replaceErrorStackForTest(testContextReports[0].message)).to.equal('Resolve error: SyntaxError: TEST SYNTAX ERROR\n<stack-was-here>');
@@ -315,11 +349,11 @@ describe('resolve', function () {
     });
   });
 
-  const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip);
+  const caseDescribe = !CASE_SENSITIVE_FS ? describe : describe.skip;
   caseDescribe('case sensitivity', function () {
     let file;
     const testContext = utils.testContext({
-      'import/resolve': { 'extensions': ['.jsx'] },
+      'import/resolve': { extensions: ['.jsx'] },
       'import/cache': { lifetime: 0 },
     });
     const testSettings = testContext.settings;
@@ -333,31 +367,30 @@ describe('resolve', function () {
     });
     it('detects case does not match FS', function () {
       expect(fileExistsWithCaseSync(file, testSettings))
-        .to.be.false;
+        .to.equal(false);
     });
     it('detecting case does not include parent folder path (issue #720)', function () {
       const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx');
       expect(fileExistsWithCaseSync(f, testSettings))
-        .to.be.true;
+        .to.equal(true);
     });
     it('detecting case should include parent folder path', function () {
       const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx');
       expect(fileExistsWithCaseSync(f, testSettings, true))
-        .to.be.false;
+        .to.equal(false);
     });
   });
 
   describe('rename cache correctness', function () {
     const context = utils.testContext({
-      'import/cache': { 'lifetime': 1 },
+      'import/cache': { lifetime: 1 },
     });
 
-    const infiniteContexts = [ '∞', 'Infinity' ].map(inf => [inf,
+    const infiniteContexts = [ '∞', 'Infinity' ].map((inf) => [inf,
       utils.testContext({
-        'import/cache': { 'lifetime': inf },
+        'import/cache': { lifetime: inf },
       })]);
 
-
     const pairs = [
       ['./CaseyKasem.js', './CASEYKASEM2.js'],
     ];
@@ -372,7 +405,7 @@ describe('resolve', function () {
 
         // settings are part of cache key
         before('warm up infinite entries', function () {
-          infiniteContexts.forEach(([,c]) => {
+          infiniteContexts.forEach(([, c]) => {
             expect(resolve(original, c)).to.exist;
           });
         });
@@ -384,10 +417,9 @@ describe('resolve', function () {
             done);
         });
 
-        before('verify rename', (done) =>
-          fs.exists(
-            utils.testFilePath(changed),
-            exists => done(exists ? null : new Error('new file does not exist'))));
+        before('verify rename', (done) => fs.exists(
+          utils.testFilePath(changed),
+          (exists) => done(exists ? null : new Error('new file does not exist'))));
 
         it('gets cached values within cache lifetime', function () {
           // get cached values initially
@@ -426,7 +458,8 @@ describe('resolve', function () {
           fs.rename(
             utils.testFilePath(changed),
             utils.testFilePath(original),
-            done);
+            done,
+          );
         });
       });
     });
diff --git a/tests/src/package.js b/tests/src/package.js
index f759819758..dd55e2740b 100644
--- a/tests/src/package.js
+++ b/tests/src/package.js
@@ -38,8 +38,8 @@ describe('package', function () {
   it('exports all configs', function (done) {
     fs.readdir(path.join(process.cwd(), 'config'), function (err, files) {
       if (err) { done(err); return; }
-      files.filter(isJSFile).forEach(file => {
-        if (file[0] === '.') return;
+      files.filter(isJSFile).forEach((file) => {
+        if (file[0] === '.') { return; }
         expect(module.configs).to.have.property(path.basename(file, '.js'));
       });
       done();
@@ -66,7 +66,7 @@ describe('package', function () {
 
   it('marks deprecated rules in their metadata', function () {
     expect(module.rules['imports-first'].meta.deprecated).to.be.true;
-    expect(module.rules['first'].meta.deprecated).not.to.be.true;
+    expect(module.rules.first.meta.deprecated).not.to.be.true;
   });
 
 });
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index 46a1b97afe..73617a6f36 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -969,7 +969,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
 
 context('TypeScript', () => {
   getTSParsers().forEach((typescriptParser) => {
-    const nodeType = typescriptParser === parsers.TS_OLD || (typescriptParser === parsers.TS_NEW && semver.satisfies(require('@typescript-eslint/parser/package.json').version, '^2'))
+    const nodeType = typescriptParser === parsers.TS_OLD || typescriptParser === parsers.TS_NEW && semver.satisfies(require('@typescript-eslint/parser/package.json').version, '^2')
       ? 'CallExpression'
       : 'ImportExpression';
 
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index 95093bf4a8..a7f2bec122 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -137,7 +137,6 @@ ruleTester.run('export', rule, {
     //   errors: ['Parsing error: Duplicate export \'bar\''],
     // }),
 
-
     // #328: "export * from" does not export a default
     test({
       code: 'export * from "./default-export"',
@@ -158,7 +157,6 @@ ruleTester.run('export', rule, {
   ),
 });
 
-
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     const parserConfig = {
diff --git a/tests/src/rules/exports-last.js b/tests/src/rules/exports-last.js
index 9f01f27f42..d7122e9a00 100644
--- a/tests/src/rules/exports-last.js
+++ b/tests/src/rules/exports-last.js
@@ -5,7 +5,7 @@ import rule from 'rules/exports-last';
 
 const ruleTester = new RuleTester();
 
-const error = type => ({
+const error = (type) => ({
   message: 'Export statements should appear at the end of the file',
   type,
 });
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 45b4498fe9..ede1a8d88a 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -31,7 +31,7 @@ ruleTester.run('extensions', rule, {
         'import data from "./bar.json"',
       ].join('\n'),
       options: [ 'never' ],
-      settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
+      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
     }),
 
     test({
@@ -41,7 +41,7 @@ ruleTester.run('extensions', rule, {
         'import barhbs from "./bar.hbs"',
       ].join('\n'),
       options: [ 'always', { js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json', '.hbs' ] } },
+      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json', '.hbs' ] } },
     }),
 
     test({
@@ -50,7 +50,7 @@ ruleTester.run('extensions', rule, {
         'import pack from "./package"',
       ].join('\n'),
       options: [ 'never', { js: 'always', json: 'never' } ],
-      settings: { 'import/resolve': { 'extensions': [ '.js', '.json' ] } },
+      settings: { 'import/resolve': { extensions: [ '.js', '.json' ] } },
     }),
 
     // unresolved (#271/#295)
@@ -96,8 +96,8 @@ ruleTester.run('extensions', rule, {
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
       settings: {
         'import/resolver': {
-          'node': { 'extensions': [ '.js', '.jsx', '.json' ] },
-          'webpack': { 'config': 'webpack.empty.config.js' },
+          node: { extensions: [ '.js', '.jsx', '.json' ] },
+          webpack: { config: 'webpack.empty.config.js' },
         },
       },
     }),
@@ -174,7 +174,7 @@ ruleTester.run('extensions', rule, {
         'import packageConfig from "./package"',
       ].join('\n'),
       options: [ { json: 'always', js: 'never' } ],
-      settings: { 'import/resolve': { 'extensions': [ '.js', '.json' ] } },
+      settings: { 'import/resolve': { extensions: [ '.js', '.json' ] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "a/index.js"',
@@ -195,7 +195,7 @@ ruleTester.run('extensions', rule, {
         'import data from "./bar.json"',
       ].join('\n'),
       options: [ 'never' ],
-      settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
+      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./bar.js"',
@@ -211,7 +211,7 @@ ruleTester.run('extensions', rule, {
         'import data from "./bar.json"',
       ].join('\n'),
       options: [ { json: 'always', js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
+      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./bar.js"',
@@ -227,7 +227,7 @@ ruleTester.run('extensions', rule, {
         'import data from "./bar.json"',
       ].join('\n'),
       options: [ { json: 'always', js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { 'extensions': [ '.jsx', '.json', '.js' ] } },
+      settings: { 'import/resolve': { extensions: [ '.jsx', '.json', '.js' ] } },
       errors: [
         {
           message: 'Unexpected use of file extension "jsx" for "./bar.jsx"',
@@ -246,7 +246,7 @@ ruleTester.run('extensions', rule, {
         },
       ],
       options: ['never', { js: 'always', jsx: 'always' }],
-      settings: { 'import/resolve': { 'extensions': ['.coffee', '.js'] } },
+      settings: { 'import/resolve': { extensions: ['.coffee', '.js'] } },
     }),
 
     test({
@@ -256,7 +256,7 @@ ruleTester.run('extensions', rule, {
         'import barnone from "./bar"',
       ].join('\n'),
       options: [ 'always', { json: 'always', js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
+      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./bar.js"',
@@ -273,7 +273,7 @@ ruleTester.run('extensions', rule, {
         'import barnone from "./bar"',
       ].join('\n'),
       options: [ 'never', { json: 'always', js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { 'extensions': [ '.js', '.jsx', '.json' ] } },
+      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./bar.js"',
@@ -331,7 +331,6 @@ ruleTester.run('extensions', rule, {
       ],
     }),
 
-
     test({
       code: `
         import foo from './foo.js'
diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index 8892ff3d62..f34f227b2d 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -81,7 +81,7 @@ ruleTester.run('first', rule, {
       code: "if (true) { console.log(1) }import a from 'b'",
       errors: 1,
       output: "import a from 'b'\nif (true) { console.log(1) }",
-    }),  
+    }),
   ],
 });
 
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 227e242ef8..110cfff52a 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -4,12 +4,11 @@ import path from 'path';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
-
 const ruleTester = new RuleTester();
 const rule = require('rules/named');
 
 function error(name, module, type = 'Identifier') {
-  return { message: name + ' not found in \'' + module + '\'', type };
+  return { message: `${name} not found in '${module}'`, type };
 }
 
 ruleTester.run('named', rule, {
@@ -30,11 +29,10 @@ ruleTester.run('named', rule, {
     test({ code: 'import {RuleTester} from "./re-export-node_modules"' }),
 
     test({ code: 'import { jsxFoo } from "./jsx/AnotherComponent"',
-      settings: { 'import/resolve': { 'extensions': ['.js', '.jsx'] } } }),
+      settings: { 'import/resolve': { extensions: ['.js', '.jsx'] } } }),
 
     // validate that eslint-disable-line silences this properly
-    test({ code: 'import {a, b, d} from "./common"; ' +
-                '// eslint-disable-line named' }),
+    test({ code: 'import {a, b, d} from "./common"; // eslint-disable-line named' }),
 
     test({ code: 'import { foo, bar } from "./re-export-names"' }),
 
@@ -192,7 +190,7 @@ ruleTester.run('named', rule, {
       },
     })),
 
-    testVersion('>=7.8.0', () =>({ code: 'const { something } = require("./dynamic-import-in-commonjs")',
+    testVersion('>=7.8.0', () => ({ code: 'const { something } = require("./dynamic-import-in-commonjs")',
       parserOptions: { ecmaVersion: 2021 },
       options: [{ commonjs: true }],
     })),
@@ -323,7 +321,6 @@ ruleTester.run('named', rule, {
       errors: ["bap not found in './re-export-default'"],
     }),
 
-
     // #328: * exports do not include default
     test({
       code: 'import { default as barDefault } from "./re-export"',
@@ -381,7 +378,6 @@ ruleTester.run('named (export *)', rule, {
   ],
 });
 
-
 context('TypeScript', function () {
   getTSParsers().forEach((parser) => {
     const settings = {
@@ -459,7 +455,7 @@ context('TypeScript', function () {
           parser,
           settings,
         }),
-        (source === 'typescript-declare'
+        source === 'typescript-declare'
           ? testVersion('> 5', () => ({
             code: `import { getFoo } from "./${source}"`,
             parser,
@@ -470,7 +466,7 @@ context('TypeScript', function () {
             parser,
             settings,
           })
-        ),
+        ,
         test({
           code: `import { MyEnum } from "./${source}"`,
           parser,
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 163ff163ea..d368fd3fe9 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -5,7 +5,6 @@ import flatMap from 'array.prototype.flatmap';
 const ruleTester = new RuleTester({ env: { es6: true } });
 const rule = require('rules/namespace');
 
-
 function error(name, namespace) {
   return { message: `'${name}' not found in imported namespace '${namespace}'.` };
 }
@@ -14,13 +13,10 @@ const valid = [
   test({ code: 'import "./malformed.js"' }),
 
   test({ code: "import * as foo from './empty-folder';" }),
-  test({ code: 'import * as names from "./named-exports"; ' +
-               'console.log((names.b).c); ' }),
+  test({ code: 'import * as names from "./named-exports"; console.log((names.b).c); ' }),
 
-  test({ code: 'import * as names from "./named-exports"; ' +
-               'console.log(names.a);' }),
-  test({ code: 'import * as names from "./re-export-names"; ' +
-               'console.log(names.foo);' }),
+  test({ code: 'import * as names from "./named-exports"; console.log(names.a);' }),
+  test({ code: 'import * as names from "./re-export-names"; console.log(names.foo);' }),
   test({
     code: "import * as elements from './jsx';",
     parserOptions: {
@@ -61,26 +57,23 @@ const valid = [
   test({ code: "import * as foo from './common';" }),
 
   // destructuring namespaces
-  test({ code: 'import * as names from "./named-exports";' +
-               'const { a } = names' }),
-  test({ code: 'import * as names from "./named-exports";' +
-               'const { d: c } = names' }),
-  test({ code: 'import * as names from "./named-exports";' +
-               'const { c } = foo\n' +
-               '    , { length } = "names"\n' +
-               '    , alt = names' }),
+  test({ code: 'import * as names from "./named-exports"; const { a } = names' }),
+  test({ code: 'import * as names from "./named-exports"; const { d: c } = names' }),
+  test({
+    code: `
+      import * as names from "./named-exports";
+      const { c } = foo,
+        { length } = "names",
+        alt = names;
+      `,
+  }),
   // deep destructuring only cares about top level
-  test({ code: 'import * as names from "./named-exports";' +
-               'const { ExportedClass: { length } } = names' }),
+  test({ code: 'import * as names from "./named-exports"; const { ExportedClass: { length } } = names' }),
 
   // detect scope redefinition
-  test({ code: 'import * as names from "./named-exports";' +
-               'function b(names) { const { c } = names }' }),
-  test({ code: 'import * as names from "./named-exports";' +
-               'function b() { let names = null; const { c } = names }' }),
-  test({ code: 'import * as names from "./named-exports";' +
-               'const x = function names() { const { c } = names }' }),
-
+  test({ code: 'import * as names from "./named-exports"; function b(names) { const { c } = names }' }),
+  test({ code: 'import * as names from "./named-exports"; function b() { let names = null; const { c } = names }' }),
+  test({ code: 'import * as names from "./named-exports"; const x = function names() { const { c } = names }' }),
 
   /////////
   // es7 //
@@ -101,8 +94,7 @@ const valid = [
   // respect hoisting
   test({
     code:
-      'function x() { console.log((names.b).c); } ' +
-      'import * as names from "./named-exports"; ',
+      'function x() { console.log((names.b).c); } import * as names from "./named-exports"; ',
   }),
 
   // names.default is valid export
@@ -241,13 +233,11 @@ const valid = [
 ];
 
 const invalid = [].concat(
-  test({ code: "import * as names from './named-exports'; " +
-               ' console.log(names.c);',
-  errors: [error('c', 'names')] }),
+  test({ code: "import * as names from './named-exports'; console.log(names.c)",
+    errors: [error('c', 'names')] }),
 
-  test({ code: "import * as names from './named-exports';" +
-               " console.log(names['a']);",
-  errors: ["Unable to validate computed reference to imported namespace 'names'."] }),
+  test({ code: "import * as names from './named-exports'; console.log(names['a']);",
+    errors: ["Unable to validate computed reference to imported namespace 'names'."] }),
 
   // assignment warning (from no-reassign)
   test({ code: 'import * as foo from \'./bar\'; foo.foo = \'y\';',
@@ -269,8 +259,7 @@ const invalid = [].concat(
     errors: [{ type: 'Property', message: "'c' not found in imported namespace 'names'." }],
   }),
   test({
-    code: 'import * as names from "./named-exports";' +
-           'const { c: { d } } = names',
+    code: 'import * as names from "./named-exports"; const { c: { d } } = names',
     errors: [{ type: 'Property', message: "'c' not found in imported namespace 'names'." }],
   }),
 
@@ -300,15 +289,11 @@ const invalid = [].concat(
 
   // respect hoisting
   test({
-    code:
-      'console.log(names.c);' +
-      "import * as names from './named-exports'; ",
+    code: `console.log(names.c); import * as names from './named-exports';`,
     errors: [error('c', 'names')],
   }),
   test({
-    code:
-      'function x() { console.log(names.c) } ' +
-      "import * as names from './named-exports'; ",
+    code: `function x() { console.log(names.c) } import * as names from './named-exports';`,
     errors: [error('c', 'names')],
   }),
 
@@ -340,12 +325,12 @@ const invalid = [].concat(
     errors: [ "'e' not found in deeply imported namespace 'b.c'." ],
     parserOptions: { ecmaVersion: 2022 },
   })),
-)
+);
 
 ///////////////////////
 // deep dereferences //
 //////////////////////
-;[['deep', require.resolve('espree')], ['deep-es7', parsers.BABEL_OLD]].forEach(function ([folder, parser]) { // close over params
+[['deep', require.resolve('espree')], ['deep-es7', parsers.BABEL_OLD]].forEach(function ([folder, parser]) { // close over params
   valid.push(
     test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.c.d.e)` }),
     test({ parser, code: `import { b } from "./${folder}/a"; console.log(b.c.d.e)` }),
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index bf91064f85..5e14b570ee 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -6,9 +6,7 @@ import { version as tsEslintVersion } from 'typescript-eslint-parser/package.jso
 import { getTSParsers, parsers, testVersion } from '../utils';
 
 const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.';
-const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => {
-  return `Expected ${count} empty lines after import statement not followed by another import.`;
-};
+const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => `Expected ${count} empty lines after import statement not followed by another import.`;
 const REQUIRE_ERROR_MESSAGE = 'Expected 1 empty line after require statement not followed by another require.';
 
 const ruleTester = new RuleTester();
@@ -22,7 +20,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       code: `
         const x = () => require('baz')
             , y = () => require('bar')`,
-      parserOptions: { ecmaVersion: 6 } ,
+      parserOptions: { ecmaVersion: 6 },
     },
     {
       code: `
@@ -31,12 +29,12 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
             
         // some comment here
       `,
-      parserOptions: { ecmaVersion: 6 } ,
+      parserOptions: { ecmaVersion: 6 },
       options: [{ considerComments: true }],
     },
     {
       code: `const x = () => require('baz') && require('bar')`,
-      parserOptions: { ecmaVersion: 6 } ,
+      parserOptions: { ecmaVersion: 6 },
     },
     {
       code: `
@@ -45,8 +43,8 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         // Some random single line comment
         var bar = 42;
       `,
-      parserOptions: { ecmaVersion: 6 } ,
-      options: [{ 'considerComments': true }],
+      parserOptions: { ecmaVersion: 6 },
+      options: [{ considerComments: true }],
     },
     {
       code: `
@@ -57,7 +55,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         **/
         var bar = 42;
       `,
-      parserOptions: { ecmaVersion: 6 } ,
+      parserOptions: { ecmaVersion: 6 },
     },
     `function x() { require('baz'); }`,
     `a(require('b'), require('c'), require('d'));`,
@@ -122,12 +120,12 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
     {
       code: `import foo from 'foo';\n\n\nvar bar = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      options: [{ 'count': 2 }],
+      options: [{ count: 2 }],
     },
     {
       code: `import foo from 'foo';\n\n\n\n\nvar bar = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      options: [{ 'count': 4 }],
+      options: [{ count: 4 }],
     },
     {
       code: `var foo = require('foo-module');\n\nvar foo = 'bar';`,
@@ -136,12 +134,12 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
     {
       code: `var foo = require('foo-module');\n\n\nvar foo = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      options: [{ 'count': 2 }],
+      options: [{ count: 2 }],
     },
     {
       code: `var foo = require('foo-module');\n\n\n\n\nvar foo = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      options: [{ 'count': 4 }],
+      options: [{ count: 4 }],
     },
     {
       code: `require('foo-module');\n\nvar foo = 'bar';`,
@@ -202,12 +200,12 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parser: parsers.BABEL_OLD,
     },
     {
-      code : `// issue 1004\nimport foo from 'foo';\n\n@SomeDecorator(foo)\nexport default class Test {}`,
+      code: `// issue 1004\nimport foo from 'foo';\n\n@SomeDecorator(foo)\nexport default class Test {}`,
       parserOptions: { sourceType: 'module' },
       parser: parsers.BABEL_OLD,
     },
     {
-      code : `// issue 1004\nconst foo = require('foo');\n\n@SomeDecorator(foo)\nexport default class Test {}`,
+      code: `// issue 1004\nconst foo = require('foo');\n\n@SomeDecorator(foo)\nexport default class Test {}`,
       parserOptions: { sourceType: 'module' },
       parser: parsers.BABEL_OLD,
     },
@@ -296,7 +294,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         **/
         var bar = 42;
       `,
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
       code: `
@@ -308,8 +306,8 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         **/
         var bar = 42;
       `,
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
-      options: [{ 'considerComments': true }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ considerComments: true }],
     },
     {
       code: `
@@ -319,7 +317,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         // Some random single line comment
         var bar = 42;
       `,
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
   ),
 
@@ -344,7 +342,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: IMPORT_ERROR_MESSAGE,
       } ],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      options: [{ 'considerComments': true }],
+      options: [{ considerComments: true }],
     },
     {
       code: `
@@ -370,8 +368,8 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         column: 9,
         message: IMPORT_ERROR_MESSAGE,
       } ],
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
-      options: [{ 'considerComments': true }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ considerComments: true }],
     },
     {
       code: `
@@ -391,8 +389,8 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         column: 9,
         message: IMPORT_ERROR_MESSAGE,
       } ],
-      parserOptions: { ecmaVersion: 2015, sourceType: 'module' } ,
-      options: [{ 'considerComments': true, 'count': 1 }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ considerComments: true, count: 1 }],
     },
     {
       code: `import foo from 'foo';\nexport default function() {};`,
@@ -407,7 +405,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
     {
       code: `import foo from 'foo';\n\nexport default function() {};`,
       output: `import foo from 'foo';\n\n\nexport default function() {};`,
-      options: [{ 'count': 2 }],
+      options: [{ count: 2 }],
       errors: [ {
         line: 1,
         column: 1,
@@ -428,7 +426,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
     {
       code: `import foo from 'foo';\nexport default function() {};`,
       output: `import foo from 'foo';\n\nexport default function() {};`,
-      options: [{ 'count': 1 }],
+      options: [{ count: 1 }],
       errors: [ {
         line: 1,
         column: 1,
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index a2e3464ca7..baa3b907f6 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -19,12 +19,12 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
     { code: 'export default "x"', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
     { code: 'export function house() {}', parserOptions: { ecmaVersion: 2015, sourceType: 'module' } },
     {
-      code:
-      'function someFunc() {\n'+
-      '  const exports = someComputation();\n'+
-      '\n'+
-      '  expect(exports.someProp).toEqual({ a: \'value\' });\n'+
-      '}',
+      code: `
+        function someFunc() {
+          const exports = someComputation();
+          expect(exports.someProp).toEqual({ a: 'value' });
+        }
+      `,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
 
@@ -68,7 +68,7 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
   invalid: [
 
     // imports
-    ...(semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
+    ...semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
       { code: 'var x = require("x")', output: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
       { code: 'x = require("x")', output: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
       { code: 'require("x")', output: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] },
@@ -93,7 +93,7 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
         output: 'try { require("x") } catch (error) {}',
         errors: [ { message: IMPORT_MESSAGE }],
       },
-    ]),
+    ],
 
     // exports
     { code: 'exports.face = "palm"', output: 'exports.face = "palm"', errors: [ { message: EXPORT_MESSAGE }] },
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index 155f257b71..d2adbf61f9 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -6,9 +6,9 @@ import flatMap from 'array.prototype.flatmap';
 const ruleTester = new RuleTester();
 const rule = require('rules/no-cycle');
 
-const error = message => ({ message });
+const error = (message) => ({ message });
 
-const test = def => _test(Object.assign(def, {
+const test = (def) => _test(Object.assign(def, {
   filename: testFilePath('./cycles/depth-zero.js'),
 }));
 const testVersion = (specifier, t) => _testVersion(specifier, () => Object.assign(t(), {
diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index 290946735f..318ea7c368 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -38,7 +38,6 @@ ruleTester.run('no-deprecated', rule, {
       code: "import { deepDep } from './deep-deprecated'; function x(deepDep) { console.log(deepDep.MY_TERRIBLE_ACTION) }",
     }),
 
-
     ...SYNTAX_CASES,
   ],
   invalid: [
@@ -210,18 +209,20 @@ describe('TypeScript', function () {
 
     ruleTester.run(parser, rule, {
       valid: [
-        test(Object.assign({
+        test({
           code: 'import * as hasDeprecated from \'./ts-deprecated.ts\'',
-        }, parserConfig)),
+          ...parserConfig,
+        }),
       ],
       invalid: [
-        test(Object.assign({
+        test({
           code: 'import { foo } from \'./ts-deprecated.ts\'; console.log(foo())',
           errors: [
             { type: 'ImportSpecifier', message: 'Deprecated: don\'t use this!' },
             { type: 'Identifier', message: 'Deprecated: don\'t use this!' },
-          ] },
-        parserConfig)),
+          ],
+          ...parserConfig,
+        }),
       ],
     });
   });
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index ac76c3070a..33e1e632e2 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -12,7 +12,7 @@ const rule = require('rules/no-duplicates');
 
 // autofix only possible with eslint 4+
 const test = semver.satisfies(eslintPkg.version, '< 4')
-  ? t => testUtil(Object.assign({}, t, { output: t.code }))
+  ? (t) => testUtil({ ...t, output: t.code })
   : testUtil;
 
 ruleTester.run('no-duplicates', rule, {
@@ -22,8 +22,7 @@ ruleTester.run('no-duplicates', rule, {
     test({ code: "import { x } from './foo'; import { y } from './bar'" }),
 
     // #86: every unresolved module should not show up as 'null' and duplicate
-    test({ code: 'import foo from "234artaf";' +
-                 'import { shoop } from "234q25ad"' }),
+    test({ code: 'import foo from "234artaf"; import { shoop } from "234q25ad"' }),
 
     // #225: ignore duplicate if is a flow type import
     test({
@@ -34,12 +33,12 @@ ruleTester.run('no-duplicates', rule, {
     // #1107: Using different query strings that trigger different webpack loaders.
     test({
       code: "import x from './bar?optionX'; import y from './bar?optionY';",
-      options: [{ 'considerQueryString': true }],
+      options: [{ considerQueryString: true }],
       settings: { 'import/resolver': 'webpack' },
     }),
     test({
       code: "import x from './foo'; import y from './bar';",
-      options: [{ 'considerQueryString': true }],
+      options: [{ considerQueryString: true }],
       settings: { 'import/resolver': 'webpack' },
     }),
 
@@ -68,10 +67,11 @@ ruleTester.run('no-duplicates', rule, {
     test({
       code: "import { x } from './bar'; import { y } from 'bar';",
       output: "import { x , y } from './bar'; ",
-      settings: { 'import/resolve': {
-        paths: [path.join( process.cwd()
-          , 'tests', 'files',
-        )] } },
+      settings: {
+        'import/resolve': {
+          paths: [path.join(process.cwd(), 'tests', 'files')],
+        },
+      },
       errors: 2, // path ends up hardcoded
     }),
 
@@ -90,7 +90,7 @@ ruleTester.run('no-duplicates', rule, {
     // #1107: Using same query strings that trigger the same loader.
     test({
       code: "import x from './bar?optionX'; import y from './bar.js?optionX';",
-      options: [{ 'considerQueryString': true }],
+      options: [{ considerQueryString: true }],
       settings: { 'import/resolver': 'webpack' },
       errors: 2, // path ends up hardcoded
     }),
@@ -132,8 +132,8 @@ ruleTester.run('no-duplicates', rule, {
     }),
 
     // These test cases use duplicate import identifiers, which causes a fatal parsing error using ESPREE (default) and TS_OLD.
-    ...flatMap([parsers.BABEL_OLD, parsers.TS_NEW], parser => {
-      if (!parser) return []; // TS_NEW is not always available
+    ...flatMap([parsers.BABEL_OLD, parsers.TS_NEW], (parser) => {
+      if (!parser) { return []; } // TS_NEW is not always available
       return [
         // #2347: duplicate identifiers should be removed
         test({
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index 0b141ccd76..e316470ec8 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -30,10 +30,9 @@ ruleTester.run('no-dynamic-require', rule, {
 
     //dynamic import
     ...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => {
-      const _test =
-        parser === parsers.ESPREE
-          ? (testObj) => testVersion('>= 6.2.0', () => testObj)
-          : (testObj) => test(testObj);
+      const _test = parser === parsers.ESPREE
+        ? (testObj) => testVersion('>= 6.2.0', () => testObj)
+        : (testObj) => test(testObj);
       return [].concat(
         _test({
           code: 'import("foo")',
@@ -143,10 +142,9 @@ ruleTester.run('no-dynamic-require', rule, {
 
     // dynamic import
     ...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => {
-      const _test =
-        parser === parsers.ESPREE
-          ? (testObj) => testVersion('>= 6.2.0', () => testObj)
-          : (testObj) => test(testObj);
+      const _test = parser === parsers.ESPREE
+        ? (testObj) => testVersion('>= 6.2.0', () => testObj)
+        : (testObj) => test(testObj);
       return [].concat(
         _test({
           code: 'import("../" + name)',
diff --git a/tests/src/rules/no-empty-named-blocks.js b/tests/src/rules/no-empty-named-blocks.js
index 87a0a3e7c9..f65e5a2045 100644
--- a/tests/src/rules/no-empty-named-blocks.js
+++ b/tests/src/rules/no-empty-named-blocks.js
@@ -5,9 +5,8 @@ import { RuleTester } from 'eslint';
 const ruleTester = new RuleTester();
 const rule = require('rules/no-empty-named-blocks');
 
-
 function generateSuggestionsTestCases(cases, parser) {
-  return cases.map(code => test({
+  return cases.map((code) => test({
     code,
     parser,
     errors: [{
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 84aa8bb35d..6f4e710f9d 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -308,7 +308,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import foo from "foo"',
       options: [{ packageDir: packageDirWithSyntaxError }],
       errors: [{
-        message: 'The package.json file could not be parsed: ' + packageFileWithSyntaxErrorMessage,
+        message: `The package.json file could not be parsed: ${packageFileWithSyntaxErrorMessage}`,
       }],
     }),
     test({
@@ -422,31 +422,29 @@ describe('TypeScript', () => {
 
       ruleTester.run('no-extraneous-dependencies', rule, {
         valid: [
-          test(Object.assign({
+          test({
             code: 'import type T from "a";',
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
-          }, parserConfig)),
+            ...parserConfig,
+          }),
         ],
         invalid: [
-          test(Object.assign({
+          test({
             code: 'import T from "a";',
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
-            errors: [{
-              message: "'a' should be listed in the project's dependencies, not devDependencies.",
-            }],
-          }, parserConfig)),
+            errors: [{ message: "'a' should be listed in the project's dependencies, not devDependencies." }],
+            ...parserConfig,
+          }),
 
-          test(Object.assign({
-            code: 'import type T from "a";',
+          test({ code: 'import type T from "a";',
             options: [{
               packageDir: packageDirWithTypescriptDevDependencies,
               devDependencies: false,
               includeTypes: true,
             }],
-            errors: [{
-              message: "'a' should be listed in the project's dependencies, not devDependencies.",
-            }],
-          }, parserConfig)),
+            errors: [{ message: "'a' should be listed in the project's dependencies, not devDependencies." }],
+            ...parserConfig,
+          }),
         ],
       });
     });
diff --git a/tests/src/rules/no-import-module-exports.js b/tests/src/rules/no-import-module-exports.js
index 81faceba98..c2bf7ed132 100644
--- a/tests/src/rules/no-import-module-exports.js
+++ b/tests/src/rules/no-import-module-exports.js
@@ -9,8 +9,7 @@ const ruleTester = new RuleTester({
 const rule = require('rules/no-import-module-exports');
 
 const error = {
-  message: `Cannot use import declarations in modules that export using CommonJS ` +
-    `(module.exports = 'foo' or exports.bar = 'hi')`,
+  message: `Cannot use import declarations in modules that export using CommonJS (module.exports = 'foo' or exports.bar = 'hi')`,
   type: 'ImportDeclaration',
 };
 
diff --git a/tests/src/rules/no-named-as-default-member.js b/tests/src/rules/no-named-as-default-member.js
index 53cba230ba..1773176f4f 100644
--- a/tests/src/rules/no-named-as-default-member.js
+++ b/tests/src/rules/no-named-as-default-member.js
@@ -25,40 +25,28 @@ ruleTester.run('no-named-as-default-member', rule, {
     test({
       code: 'import bar from "./bar"; const foo = bar.foo;',
       errors: [{
-        message: (
-          'Caution: `bar` also has a named export `foo`. ' +
-          'Check if you meant to write `import {foo} from \'./bar\'` instead.'
-        ),
+        message: 'Caution: `bar` also has a named export `foo`. Check if you meant to write `import {foo} from \'./bar\'` instead.',
         type: 'MemberExpression',
       }],
     }),
     test({
       code: 'import bar from "./bar"; bar.foo();',
       errors: [{
-        message: (
-          'Caution: `bar` also has a named export `foo`. ' +
-          'Check if you meant to write `import {foo} from \'./bar\'` instead.'
-        ),
+        message: 'Caution: `bar` also has a named export `foo`. Check if you meant to write `import {foo} from \'./bar\'` instead.',
         type: 'MemberExpression',
       }],
     }),
     test({
       code: 'import bar from "./bar"; const {foo} = bar;',
       errors: [{
-        message: (
-          'Caution: `bar` also has a named export `foo`. ' +
-          'Check if you meant to write `import {foo} from \'./bar\'` instead.'
-        ),
+        message: 'Caution: `bar` also has a named export `foo`. Check if you meant to write `import {foo} from \'./bar\'` instead.',
         type: 'Identifier',
       }],
     }),
     test({
       code: 'import bar from "./bar"; const {foo: foo2, baz} = bar;',
       errors: [{
-        message: (
-          'Caution: `bar` also has a named export `foo`. ' +
-          'Check if you meant to write `import {foo} from \'./bar\'` instead.'
-        ),
+        message: 'Caution: `bar` also has a named export `foo`. Check if you meant to write `import {foo} from \'./bar\'` instead.',
         type: 'Identifier',
       }],
     }),
@@ -66,10 +54,7 @@ ruleTester.run('no-named-as-default-member', rule, {
     testVersion('>= 8.7', () => ({
       code: 'import bar from "./export-default-string-and-named"; const foo = bar.foo;',
       errors: [{
-        message: (
-          'Caution: `bar` also has a named export `foo`. ' +
-          'Check if you meant to write `import {foo} from \'./export-default-string-and-named\'` instead.'
-        ),
+        message: 'Caution: `bar` also has a named export `foo`. Check if you meant to write `import {foo} from \'./export-default-string-and-named\'` instead.',
         type: 'MemberExpression',
       }],
       parserOptions: { ecmaVersion: 2022 },
diff --git a/tests/src/rules/no-nodejs-modules.js b/tests/src/rules/no-nodejs-modules.js
index 9be605709a..b25eb0ce85 100644
--- a/tests/src/rules/no-nodejs-modules.js
+++ b/tests/src/rules/no-nodejs-modules.js
@@ -6,7 +6,7 @@ const isCore = require('is-core-module');
 const ruleTester = new RuleTester();
 const rule = require('rules/no-nodejs-modules');
 
-const error = message => ({
+const error = (message) => ({
   message,
 });
 
@@ -69,7 +69,7 @@ ruleTester.run('no-nodejs-modules', rule, {
           allow: ['node:events'],
         }],
       }),
-    ]: [],
+    ] : [],
     isCore('node:path') ? [
       test({
         code: 'import path from "node:path"',
diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js
index 3050498026..bfd4e16bcd 100644
--- a/tests/src/rules/no-relative-parent-imports.js
+++ b/tests/src/rules/no-relative-parent-imports.js
@@ -2,7 +2,7 @@ import { RuleTester } from 'eslint';
 import rule from 'rules/no-relative-parent-imports';
 import { parsers, test as _test, testFilePath } from '../utils';
 
-const test = def => _test(Object.assign(def, {
+const test = (def) => _test(Object.assign(def, {
   filename: testFilePath('./internal-modules/plugins/plugin2/index.js'),
   parser: parsers.BABEL_OLD,
 }));
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index 81182189f2..a83a804a0a 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -713,7 +713,7 @@ ruleTester.run('no-restricted-paths', rule, {
 });
 
 context('Typescript', function () {
-  getTSParsers().forEach(parser => {
+  getTSParsers().forEach((parser) => {
     const settings = {
       'import/parsers': { [parser]: ['.ts'] },
       'import/resolver': { 'eslint-import-resolver-typescript': true },
@@ -933,8 +933,7 @@ context('Typescript', function () {
             }],
           }],
           errors: [{
-            message: 'Restricted path exceptions must be descendants of the configured ' +
-              '`from` path for that zone.',
+            message: 'Restricted path exceptions must be descendants of the configured `from` path for that zone.',
             line: 1,
             column: 20,
           }],
diff --git a/tests/src/rules/no-unassigned-import.js b/tests/src/rules/no-unassigned-import.js
index 8724b80d30..f96808cbcc 100644
--- a/tests/src/rules/no-unassigned-import.js
+++ b/tests/src/rules/no-unassigned-import.js
@@ -29,48 +29,48 @@ ruleTester.run('no-unassigned-import', rule, {
     test({ code: 'require("lodash")()' }),
     test({
       code: 'import "app.css"',
-      options: [{ 'allow': ['**/*.css'] }],
+      options: [{ allow: ['**/*.css'] }],
     }),
     test({
       code: 'import "app.css";',
-      options: [{ 'allow': ['*.css'] }],
+      options: [{ allow: ['*.css'] }],
     }),
     test({
       code: 'import "./app.css"',
-      options: [{ 'allow': ['**/*.css'] }],
+      options: [{ allow: ['**/*.css'] }],
     }),
     test({
       code: 'import "foo/bar"',
-      options: [{ 'allow': ['foo/**'] }],
+      options: [{ allow: ['foo/**'] }],
     }),
     test({
       code: 'import "foo/bar"',
-      options: [{ 'allow': ['foo/bar'] }],
+      options: [{ allow: ['foo/bar'] }],
     }),
     test({
       code: 'import "../dir/app.css"',
-      options: [{ 'allow': ['**/*.css'] }],
+      options: [{ allow: ['**/*.css'] }],
     }),
     test({
       code: 'import "../dir/app.js"',
-      options: [{ 'allow': ['**/dir/**'] }],
+      options: [{ allow: ['**/dir/**'] }],
     }),
     test({
       code: 'require("./app.css")',
-      options: [{ 'allow': ['**/*.css'] }],
+      options: [{ allow: ['**/*.css'] }],
     }),
     test({
       code: 'import "babel-register"',
-      options: [{ 'allow': ['babel-register'] }],
+      options: [{ allow: ['babel-register'] }],
     }),
     test({
       code: 'import "./styles/app.css"',
-      options: [{ 'allow': ['src/styles/**'] }],
+      options: [{ allow: ['src/styles/**'] }],
       filename: path.join(process.cwd(), 'src/app.js'),
     }),
     test({
       code: 'import "../scripts/register.js"',
-      options: [{ 'allow': ['src/styles/**', '**/scripts/*.js'] }],
+      options: [{ allow: ['src/styles/**', '**/scripts/*.js'] }],
       filename: path.join(process.cwd(), 'src/app.js'),
     }),
   ],
@@ -85,22 +85,22 @@ ruleTester.run('no-unassigned-import', rule, {
     }),
     test({
       code: 'import "./app.css"',
-      options: [{ 'allow': ['**/*.js'] }],
+      options: [{ allow: ['**/*.js'] }],
       errors: [error],
     }),
     test({
       code: 'import "./app.css"',
-      options: [{ 'allow': ['**/dir/**'] }],
+      options: [{ allow: ['**/dir/**'] }],
       errors: [error],
     }),
     test({
       code: 'require("./app.css")',
-      options: [{ 'allow': ['**/*.js'] }],
+      options: [{ allow: ['**/*.js'] }],
       errors: [error],
     }),
     test({
       code: 'import "./styles/app.css"',
-      options: [{ 'allow': ['styles/*.css'] }],
+      options: [{ allow: ['styles/*.css'] }],
       filename: path.join(process.cwd(), 'src/app.js'),
       errors: [error],
     }),
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 024e8965ae..109099c389 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -17,7 +17,7 @@ function runResolverTests(resolver) {
       ...specs,
       settings: {
         ...specs.settings,
-        'import/resolver': resolver, 
+        'import/resolver': resolver,
         'import/cache': { lifetime: 0 },
       },
     });
@@ -161,7 +161,7 @@ function runResolverTests(resolver) {
             message: "Unable to resolve path to module './empty-folder'.",
             type: 'Literal',
           },
-        ], 
+        ],
       }),
 
       // sanity check that this module is _not_ found without proper settings
@@ -185,7 +185,7 @@ function runResolverTests(resolver) {
         parser: parsers.BABEL_OLD,
       }),
 
-      rest({ 
+      rest({
         code: 'export { foo } from "./does-not-exist"',
         errors: ["Unable to resolve path to module './does-not-exist'."],
       }),
@@ -359,7 +359,7 @@ ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
       code: "import { DEEP } from 'in-alternate-root';",
       settings: {
         'import/resolve': {
-          'paths': [
+          paths: [
             path.join(process.cwd(), 'tests', 'files', 'alternate-root'),
           ],
         },
@@ -373,14 +373,14 @@ ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
           paths: [
             path.join('tests', 'files', 'src-root'),
             path.join('tests', 'files', 'alternate-root'),
-          ], 
+          ],
         },
       },
     }),
 
     test({
       code: 'import * as foo from "jsx-module/foo"',
-      settings: { 'import/resolve': { 'extensions': ['.jsx'] } },
+      settings: { 'import/resolve': { extensions: ['.jsx'] } },
     }),
   ],
 
@@ -417,7 +417,6 @@ ruleTester.run('no-unresolved (webpack-specific)', rule, {
   ],
 });
 
-
 ruleTester.run('no-unresolved ignore list', rule, {
   valid: [
     test({
@@ -440,7 +439,7 @@ ruleTester.run('no-unresolved ignore list', rule, {
     }),
   ],
 
-  invalid:[
+  invalid: [
     test({
       code: 'import "./test.gif"',
       options: [{ ignore: ['.png$'] }],
@@ -458,7 +457,7 @@ ruleTester.run('no-unresolved ignore list', rule, {
 ruleTester.run('no-unresolved unknown resolver', rule, {
   valid: [],
 
-  invalid:[
+  invalid: [
 
     // logs resolver load error
     test({
@@ -490,7 +489,7 @@ ruleTester.run('no-unresolved electron', rule, {
       settings: { 'import/core-modules': ['electron'] },
     }),
   ],
-  invalid:[
+  invalid: [
     test({
       code: 'import "electron"',
       errors: [`Unable to resolve path to module 'electron'.`],
@@ -500,7 +499,7 @@ ruleTester.run('no-unresolved electron', rule, {
 
 ruleTester.run('no-unresolved syntax verification', rule, {
   valid: SYNTAX_CASES,
-  invalid:[],
+  invalid: [],
 });
 
 // https://github.com/import-js/eslint-plugin-import/issues/2024
@@ -522,7 +521,7 @@ ruleTester.run('import() with built-in parser', rule, {
 
 context('TypeScript', () => {
   // Type-only imports were added in TypeScript ESTree 2.23.0
-  getTSParsers().filter(x => x !== parsers.TS_OLD).forEach((parser) => {
+  getTSParsers().filter((x) => x !== parsers.TS_OLD).forEach((parser) => {
     ruleTester.run(`${parser}: no-unresolved ignore type-only`, rule, {
       valid: [
         test({
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 87714b599b..936123ab71 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -20,7 +20,7 @@ const typescriptRuleTester = new RuleTester(typescriptConfig);
 const jsxRuleTester = new RuleTester(jsxConfig);
 const rule = require('rules/no-unused-modules');
 
-const error = message => ({ message });
+const error = (message) => ({ message });
 
 const missingExportsOptions = [{
   missingExports: true,
@@ -109,7 +109,6 @@ ruleTester.run('no-unused-modules', rule, {
   ],
 });
 
-
 // tests for exports
 ruleTester.run('no-unused-modules', rule, {
   valid: [
@@ -247,7 +246,6 @@ ruleTester.run('no-unused-modules', rule, {
   ],
 });
 
-
 describe('dynamic imports', function () {
   if (semver.satisfies(eslintPkg.version, '< 6')) {
     beforeEach(function () {
@@ -817,7 +815,6 @@ describe('test behavior for new file', () => {
     ],
   });
 
-
   describe('test behavior for new file', () => {
     before(() => {
       fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', { encoding: 'utf8' });
@@ -1382,7 +1379,7 @@ describe('supports flat eslint', { skip: !FlatRuleTester }, () => {
   flatRuleTester.run('no-unused-modules', rule, {
     valid: [{
       options: unusedExportsOptions,
-      code: 'import { o2 } from "./file-o";export default () => 12',
+      code: 'import { o2 } from "./file-o"; export default () => 12',
       filename: testFilePath('./no-unused-modules/file-a.js'),
     }],
     invalid: [{
diff --git a/tests/src/rules/no-webpack-loader-syntax.js b/tests/src/rules/no-webpack-loader-syntax.js
index 2b841e18a3..05ad242f50 100644
--- a/tests/src/rules/no-webpack-loader-syntax.js
+++ b/tests/src/rules/no-webpack-loader-syntax.js
@@ -88,12 +88,8 @@ context('TypeScript', function () {
     if (!(parser === parsers.TS_NEW && semver.satisfies(require('@typescript-eslint/parser/package.json').version, '>= 5'))) {
       ruleTester.run('no-webpack-loader-syntax', rule, {
         valid: [
-          test(Object.assign({
-            code: 'import { foo } from\nalert()',
-          }, parserConfig)),
-          test(Object.assign({
-            code: 'import foo from\nalert()',
-          }, parserConfig)),
+          test({ code: 'import { foo } from\nalert()', ...parserConfig }),
+          test({ code: 'import foo from\nalert()', ...parserConfig }),
         ],
         invalid: [],
       });
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 291dae33b0..8d0b315e71 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -7,7 +7,6 @@ import flatMap from 'array.prototype.flatmap';
 import { resolve } from 'path';
 import { default as babelPresetFlow } from 'babel-preset-flow';
 
-
 const ruleTester = new RuleTester();
 const flowRuleTester = new RuleTester({
   parser: resolve(__dirname, '../../../node_modules/babel-eslint'),
@@ -22,7 +21,7 @@ const flowRuleTester = new RuleTester({
 const rule = require('rules/order');
 
 function withoutAutofixOutput(test) {
-  return Object.assign({}, test, { output: test.code });
+  return { ...test, output: test.code };
 }
 
 ruleTester.run('order', rule, {
@@ -193,7 +192,7 @@ ruleTester.run('order', rule, {
         var index = require('./');
       `,
     }),
-    ...flatMap(getTSParsers(), parser => [
+    ...flatMap(getTSParsers(), (parser) => [
       // Export equals expressions should be on top alongside with ordinary import-statements.
       test({
         code: `
@@ -829,7 +828,7 @@ ruleTester.run('order', rule, {
         pathGroupsExcludedImportTypes: [],
       }],
     }),
-    ...flatMap(getTSParsers, parser => [
+    ...flatMap(getTSParsers, (parser) => [
       // Order of the `import ... = require(...)` syntax
       test({
         code: `
@@ -950,18 +949,18 @@ ruleTester.run('order', rule, {
       options: [
         {
           'newlines-between': 'always',
-          'distinctGroup': true,
-          'pathGroupsExcludedImportTypes': [],
-          'pathGroups': [
+          distinctGroup: true,
+          pathGroupsExcludedImportTypes: [],
+          pathGroups: [
             {
-              'pattern': 'a',
-              'group': 'external',
-              'position': 'before',
+              pattern: 'a',
+              group: 'external',
+              position: 'before',
             },
             {
-              'pattern': 'b',
-              'group': 'external',
-              'position': 'after',
+              pattern: 'b',
+              group: 'external',
+              position: 'after',
             },
           ],
         },
@@ -977,18 +976,18 @@ ruleTester.run('order', rule, {
       options: [
         {
           'newlines-between': 'always',
-          'distinctGroup': false,
-          'pathGroupsExcludedImportTypes': [],
-          'pathGroups': [
+          distinctGroup: false,
+          pathGroupsExcludedImportTypes: [],
+          pathGroups: [
             {
-              'pattern': 'a',
-              'group': 'external',
-              'position': 'before',
+              pattern: 'a',
+              group: 'external',
+              position: 'before',
             },
             {
-              'pattern': 'b',
-              'group': 'external',
-              'position': 'after',
+              pattern: 'b',
+              group: 'external',
+              position: 'after',
             },
           ],
         },
@@ -1005,17 +1004,17 @@ ruleTester.run('order', rule, {
       options: [
         {
           'newlines-between': 'always',
-          'distinctGroup': false,
-          'pathGroupsExcludedImportTypes': [],
-          'pathGroups': [
+          distinctGroup: false,
+          pathGroupsExcludedImportTypes: [],
+          pathGroups: [
             {
-              'pattern': 'a',
-              'group': 'external',
+              pattern: 'a',
+              group: 'external',
             },
             {
-              'pattern': 'b',
-              'group': 'internal',
-              'position': 'before',
+              pattern: 'b',
+              group: 'internal',
+              position: 'before',
             },
           ],
         },
@@ -1041,53 +1040,53 @@ ruleTester.run('order', rule, {
       `,
       options: [
         {
-          'alphabetize': {
-            'caseInsensitive': false,
-            'order': 'asc',
+          alphabetize: {
+            caseInsensitive: false,
+            order: 'asc',
           },
           'newlines-between': 'always',
-          'groups': [
+          groups: [
             ['builtin', 'external', 'internal', 'unknown', 'object', 'type'],
             'parent',
             ['sibling', 'index'],
           ],
-          'distinctGroup': false,
-          'pathGroupsExcludedImportTypes': [],
-          'pathGroups': [
+          distinctGroup: false,
+          pathGroupsExcludedImportTypes: [],
+          pathGroups: [
             {
-              'pattern': './',
-              'group': 'sibling',
-              'position': 'before',
+              pattern: './',
+              group: 'sibling',
+              position: 'before',
             },
             {
-              'pattern': '.',
-              'group': 'sibling',
-              'position': 'before',
+              pattern: '.',
+              group: 'sibling',
+              position: 'before',
             },
             {
-              'pattern': '..',
-              'group': 'parent',
-              'position': 'before',
+              pattern: '..',
+              group: 'parent',
+              position: 'before',
             },
             {
-              'pattern': '../',
-              'group': 'parent',
-              'position': 'before',
+              pattern: '../',
+              group: 'parent',
+              position: 'before',
             },
             {
-              'pattern': '[a-z]*',
-              'group': 'external',
-              'position': 'before',
+              pattern: '[a-z]*',
+              group: 'external',
+              position: 'before',
             },
             {
-              'pattern': '../[a-z]*',
-              'group': 'parent',
-              'position': 'before',
+              pattern: '../[a-z]*',
+              group: 'parent',
+              position: 'before',
             },
             {
-              'pattern': './[a-z]*',
-              'group': 'sibling',
-              'position': 'before',
+              pattern: './[a-z]*',
+              group: 'sibling',
+              position: 'before',
             },
           ],
         },
@@ -1101,7 +1100,7 @@ ruleTester.run('order', rule, {
       `,
       options: [
         {
-          'alphabetize': { order: 'asc', orderImportKind: 'asc', 'caseInsensitive': true },
+          alphabetize: { order: 'asc', orderImportKind: 'asc', caseInsensitive: true },
         },
       ],
     }),
@@ -1179,12 +1178,8 @@ ruleTester.run('order', rule, {
     }),
     // fix order with windows end of lines
     test({
-      code:
-        `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n` +
-        `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n`,
-      output:
-        `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n` +
-        `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n`,
+      code: `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n` + `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n`,
+      output: `/* comment3 */  var fs = require('fs'); /* comment4 */` + `\r\n` + `/* comment0 */  /* comment1 */  var async = require('async'); /* comment2 */` + `\r\n`,
       errors: [{
         message: '`fs` import should occur before import of `async`',
       }],
@@ -1558,7 +1553,7 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur after import of `../foo/bar`',
       }],
     }),
-    ...flatMap(getTSParsers(), parser => [
+    ...flatMap(getTSParsers(), (parser) => [
       // Order of the `import ... = require(...)` syntax
       test({
         code: `
@@ -2676,8 +2671,8 @@ ruleTester.run('order', rule, {
       options: [
         {
           'newlines-between': 'always',
-          'distinctGroup': false,
-          'pathGroupsExcludedImportTypes': [],
+          distinctGroup: false,
+          pathGroupsExcludedImportTypes: [],
         },
       ],
       errors: [{
@@ -2698,18 +2693,18 @@ ruleTester.run('order', rule, {
       options: [
         {
           'newlines-between': 'always',
-          'distinctGroup': false,
-          'pathGroupsExcludedImportTypes': [],
-          'pathGroups': [
+          distinctGroup: false,
+          pathGroupsExcludedImportTypes: [],
+          pathGroups: [
             {
-              'pattern': 'a',
-              'group': 'external',
-              'position': 'before',
+              pattern: 'a',
+              group: 'external',
+              position: 'before',
             },
             {
-              'pattern': 'c',
-              'group': 'external',
-              'position': 'after',
+              pattern: 'c',
+              group: 'external',
+              position: 'after',
             },
           ],
         },
@@ -2743,7 +2738,6 @@ ruleTester.run('order', rule, {
   ].filter((t) => !!t),
 });
 
-
 context('TypeScript', function () {
   getNonDefaultParsers()
     // Type-only imports were added in TypeScript ESTree 2.23.0
@@ -3182,7 +3176,7 @@ context('TypeScript', function () {
             `,
             errors: [{
               message: '`fs` type import should occur before type import of `path`',
-            },{
+            }, {
               message: '`fs` type import should occur before type import of `path`',
             }],
             ...parserConfig,
@@ -3303,34 +3297,34 @@ flowRuleTester.run('order', rule, {
       `,
       options: [
         {
-          'groups': [
+          groups: [
             ['builtin', 'external'],
             'internal',
             ['sibling', 'parent'],
             'object',
             'type',
           ],
-          'pathGroups': [
+          pathGroups: [
             {
-              'pattern': 'react',
-              'group': 'builtin',
-              'position': 'before',
-              'patternOptions': {
-                'matchBase': true,
+              pattern: 'react',
+              group: 'builtin',
+              position: 'before',
+              patternOptions: {
+                matchBase: true,
               },
             },
             {
-              'pattern': '*.+(css|svg)',
-              'group': 'type',
-              'position': 'after',
-              'patternOptions': {
-                'matchBase': true,
+              pattern: '*.+(css|svg)',
+              group: 'type',
+              position: 'after',
+              patternOptions: {
+                matchBase: true,
               },
             },
           ],
-          'pathGroupsExcludedImportTypes': ['react'],
-          'alphabetize': {
-            'order': 'asc',
+          pathGroupsExcludedImportTypes: ['react'],
+          alphabetize: {
+            order: 'asc',
           },
           'newlines-between': 'always',
         },
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index ae7c16a40e..a7310445b5 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -362,15 +362,15 @@ context('TypeScript', function () {
           ...parserConfig,
         }),
         semver.satisfies(tsEslintVersion, '>= 22') ? test({
-          code: 'export type foo = string /* ' + parser.replace(process.cwd(), '$$PWD') + '*/',
+          code: `export type foo = string /* ${parser.replace(process.cwd(), '$$PWD')}*/`,
           ...parserConfig,
         }) : [],
         semver.satisfies(tsEslintVersion, '> 20') ? test({
-          code: 'export interface foo { bar: string; } /* ' + parser.replace(process.cwd(), '$$PWD') + '*/',
+          code: `export interface foo { bar: string; } /* ${parser.replace(process.cwd(), '$$PWD')}*/`,
           ...parserConfig,
         }) : [],
         test({
-          code: 'export interface foo { bar: string; }; export function goo() {} /* ' + parser.replace(process.cwd(), '$$PWD') + '*/',
+          code: `export interface foo { bar: string; }; export function goo() {} /* ${parser.replace(process.cwd(), '$$PWD')}*/`,
           ...parserConfig,
         }),
       ),
diff --git a/tests/src/utils.js b/tests/src/utils.js
index b82883a6f4..d5215b02e3 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -50,14 +50,15 @@ export function test(t) {
   if (arguments.length !== 1) {
     throw new SyntaxError('`test` requires exactly one object argument');
   }
-  return Object.assign({
+  return {
     filename: FILENAME,
-  }, t, {
-    parserOptions: Object.assign({
+    ...t,
+    parserOptions: {
       sourceType: 'module',
       ecmaVersion: 9,
-    }, t.parserOptions),
-  });
+      ...t.parserOptions,
+    },
+  };
 }
 
 export function testContext(settings) {
@@ -133,5 +134,4 @@ export const SYNTAX_CASES = [
   test({
     code: 'import { foo } from "./ignore.invalid.extension"',
   }),
-
 ];
diff --git a/utils/ModuleCache.js b/utils/ModuleCache.js
index a06616de9b..4b1edc0eff 100644
--- a/utils/ModuleCache.js
+++ b/utils/ModuleCache.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 const log = require('debug')('eslint-module-utils:ModuleCache');
@@ -23,8 +24,10 @@ class ModuleCache {
     if (this.map.has(cacheKey)) {
       const f = this.map.get(cacheKey);
       // check freshness
-      if (process.hrtime(f.lastSeen)[0] < settings.lifetime) return f.result;
-    } else log('cache miss for', cacheKey);
+      if (process.hrtime(f.lastSeen)[0] < settings.lifetime) { return f.result; }
+    } else {
+      log('cache miss for', cacheKey);
+    }
     // cache miss
     return undefined;
   }
diff --git a/utils/declaredScope.js b/utils/declaredScope.js
index ded2131e49..dd2a20149f 100644
--- a/utils/declaredScope.js
+++ b/utils/declaredScope.js
@@ -1,9 +1,10 @@
 'use strict';
+
 exports.__esModule = true;
 
 exports.default = function declaredScope(context, name) {
   const references = context.getScope().references;
-  const reference = references.find(x => x.identifier.name === name);
-  if (!reference) return undefined;
+  const reference = references.find((x) => x.identifier.name === name);
+  if (!reference) { return undefined; }
   return reference.resolved.scope.type;
 };
diff --git a/utils/hash.js b/utils/hash.js
index fcf00de38c..b9bff25bd9 100644
--- a/utils/hash.js
+++ b/utils/hash.js
@@ -2,7 +2,9 @@
  * utilities for hashing config objects.
  * basically iteratively updates hash with a JSON-like format
  */
+
 'use strict';
+
 exports.__esModule = true;
 
 const createHash = require('crypto').createHash;
@@ -10,7 +12,7 @@ const createHash = require('crypto').createHash;
 const stringify = JSON.stringify;
 
 function hashify(value, hash) {
-  if (!hash) hash = createHash('sha256');
+  if (!hash) { hash = createHash('sha256'); }
 
   if (Array.isArray(value)) {
     hashArray(value, hash);
@@ -25,7 +27,7 @@ function hashify(value, hash) {
 exports.default = hashify;
 
 function hashArray(array, hash) {
-  if (!hash) hash = createHash('sha256');
+  if (!hash) { hash = createHash('sha256'); }
 
   hash.update('[');
   for (let i = 0; i < array.length; i++) {
@@ -40,10 +42,10 @@ hashify.array = hashArray;
 exports.hashArray = hashArray;
 
 function hashObject(object, hash) {
-  if (!hash) hash = createHash('sha256');
+  if (!hash) { hash = createHash('sha256'); }
 
   hash.update('{');
-  Object.keys(object).sort().forEach(key => {
+  Object.keys(object).sort().forEach((key) => {
     hash.update(stringify(key));
     hash.update(':');
     hashify(object[key], hash);
@@ -56,4 +58,3 @@ function hashObject(object, hash) {
 hashify.object = hashObject;
 exports.hashObject = hashObject;
 
-
diff --git a/utils/ignore.js b/utils/ignore.js
index 32bbbc6249..e41d1e5a50 100644
--- a/utils/ignore.js
+++ b/utils/ignore.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 const extname = require('path').extname;
@@ -28,7 +29,7 @@ function makeValidExtensionSet(settings) {
       if (!Array.isArray(parserSettings)) {
         throw new TypeError('"settings" for ' + parser + ' must be an array');
       }
-      parserSettings.forEach(ext => exts.add(ext));
+      parserSettings.forEach((ext) => exts.add(ext));
     }
   }
 
@@ -38,9 +39,9 @@ exports.getFileExtensions = makeValidExtensionSet;
 
 exports.default = function ignore(path, context) {
   // check extension whitelist first (cheap)
-  if (!hasValidExtension(path, context)) return true;
+  if (!hasValidExtension(path, context)) { return true; }
 
-  if (!('import/ignore' in context.settings)) return false;
+  if (!('import/ignore' in context.settings)) { return false; }
   const ignoreStrings = context.settings['import/ignore'];
 
   for (let i = 0; i < ignoreStrings.length; i++) {
diff --git a/utils/module-require.js b/utils/module-require.js
index c03671ce5a..96ef82ba51 100644
--- a/utils/module-require.js
+++ b/utils/module-require.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 const Module = require('module');
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index 4d93a0199b..c312ca2d45 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 /**
@@ -16,14 +17,14 @@ exports.default = function visitModules(visitor, options) {
 
   let ignoreRegExps = [];
   if (options.ignore != null) {
-    ignoreRegExps = options.ignore.map(p => new RegExp(p));
+    ignoreRegExps = options.ignore.map((p) => new RegExp(p));
   }
 
   function checkSourceValue(source, importer) {
-    if (source == null) return; //?
+    if (source == null) { return; } //?
 
     // handle ignore
-    if (ignoreRegExps.some(re => re.test(source.value))) return;
+    if (ignoreRegExps.some((re) => re.test(source.value))) { return; }
 
     // fire visitor
     visitor(source, importer);
@@ -41,14 +42,14 @@ exports.default = function visitModules(visitor, options) {
     if (node.type === 'ImportExpression') {
       modulePath = node.source;
     } else if (node.type === 'CallExpression') {
-      if (node.callee.type !== 'Import') return;
-      if (node.arguments.length !== 1) return;
+      if (node.callee.type !== 'Import') { return; }
+      if (node.arguments.length !== 1) { return; }
 
       modulePath = node.arguments[0];
     }
 
-    if (modulePath.type !== 'Literal') return;
-    if (typeof modulePath.value !== 'string') return;
+    if (modulePath.type !== 'Literal') { return; }
+    if (typeof modulePath.value !== 'string') { return; }
 
     checkSourceValue(modulePath, node);
   }
@@ -56,32 +57,35 @@ exports.default = function visitModules(visitor, options) {
   // for CommonJS `require` calls
   // adapted from @mctep: https://git.io/v4rAu
   function checkCommon(call) {
-    if (call.callee.type !== 'Identifier') return;
-    if (call.callee.name !== 'require') return;
-    if (call.arguments.length !== 1) return;
+    if (call.callee.type !== 'Identifier') { return; }
+    if (call.callee.name !== 'require') { return; }
+    if (call.arguments.length !== 1) { return; }
 
     const modulePath = call.arguments[0];
-    if (modulePath.type !== 'Literal') return;
-    if (typeof modulePath.value !== 'string') return;
+    if (modulePath.type !== 'Literal') { return; }
+    if (typeof modulePath.value !== 'string') { return; }
 
     checkSourceValue(modulePath, call);
   }
 
   function checkAMD(call) {
-    if (call.callee.type !== 'Identifier') return;
-    if (call.callee.name !== 'require' &&
-        call.callee.name !== 'define') return;
-    if (call.arguments.length !== 2) return;
+    if (call.callee.type !== 'Identifier') { return; }
+    if (call.callee.name !== 'require' && call.callee.name !== 'define') { return; }
+    if (call.arguments.length !== 2) { return; }
 
     const modules = call.arguments[0];
-    if (modules.type !== 'ArrayExpression') return;
+    if (modules.type !== 'ArrayExpression') { return; }
 
     for (const element of modules.elements) {
-      if (element.type !== 'Literal') continue;
-      if (typeof element.value !== 'string') continue;
+      if (element.type !== 'Literal') { continue; }
+      if (typeof element.value !== 'string') { continue; }
 
-      if (element.value === 'require' ||
-          element.value === 'exports') continue; // magic modules: https://github.com/requirejs/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#magic-modules
+      if (
+        element.value === 'require'
+        || element.value === 'exports'
+      ) {
+        continue; // magic modules: https://github.com/requirejs/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#magic-modules
+      }
 
       checkSourceValue(element, element);
     }
@@ -90,20 +94,20 @@ exports.default = function visitModules(visitor, options) {
   const visitors = {};
   if (options.esmodule) {
     Object.assign(visitors, {
-      'ImportDeclaration': checkSource,
-      'ExportNamedDeclaration': checkSource,
-      'ExportAllDeclaration': checkSource,
-      'CallExpression': checkImportCall,
-      'ImportExpression': checkImportCall,
+      ImportDeclaration: checkSource,
+      ExportNamedDeclaration: checkSource,
+      ExportAllDeclaration: checkSource,
+      CallExpression: checkImportCall,
+      ImportExpression: checkImportCall,
     });
   }
 
   if (options.commonjs || options.amd) {
-    const currentCallExpression = visitors['CallExpression'];
-    visitors['CallExpression'] = function (call) {
-      if (currentCallExpression) currentCallExpression(call);
-      if (options.commonjs) checkCommon(call);
-      if (options.amd) checkAMD(call);
+    const currentCallExpression = visitors.CallExpression;
+    visitors.CallExpression = function (call) {
+      if (currentCallExpression) { currentCallExpression(call); }
+      if (options.commonjs) { checkCommon(call); }
+      if (options.amd) { checkAMD(call); }
     };
   }
 
@@ -116,19 +120,19 @@ exports.default = function visitModules(visitor, options) {
  */
 function makeOptionsSchema(additionalProperties) {
   const base =  {
-    'type': 'object',
-    'properties': {
-      'commonjs': { 'type': 'boolean' },
-      'amd': { 'type': 'boolean' },
-      'esmodule': { 'type': 'boolean' },
-      'ignore': {
-        'type': 'array',
-        'minItems': 1,
-        'items': { 'type': 'string' },
-        'uniqueItems': true,
+    type: 'object',
+    properties: {
+      commonjs: { type: 'boolean' },
+      amd: { type: 'boolean' },
+      esmodule: { type: 'boolean' },
+      ignore: {
+        type: 'array',
+        minItems: 1,
+        items: { type: 'string' },
+        uniqueItems: true,
       },
     },
-    'additionalProperties': false,
+    additionalProperties: false,
   };
 
   if (additionalProperties) {
diff --git a/utils/parse.js b/utils/parse.js
index dd0746aaa7..7646b3177c 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 const moduleRequire = require('./module-require').default;
@@ -23,10 +24,10 @@ function keysFromParser(parserPath, parserInstance, parsedResult) {
   if (parsedResult && parsedResult.visitorKeys) {
     return parsedResult.visitorKeys;
   }
-  if (typeof parserPath === 'string' && /.*espree.*/.test(parserPath)) {
+  if (typeof parserPath === 'string' && (/.*espree.*/).test(parserPath)) {
     return parserInstance.VisitorKeys;
   }
-  if (typeof parserPath === 'string' && /.*babel-eslint.*/.test(parserPath)) {
+  if (typeof parserPath === 'string' && (/.*babel-eslint.*/).test(parserPath)) {
     return getBabelEslintVisitorKeys(parserPath);
   }
   return null;
@@ -51,13 +52,13 @@ function transformHashbang(text) {
 }
 
 exports.default = function parse(path, content, context) {
-  if (context == null) throw new Error('need context to parse properly');
+  if (context == null) { throw new Error('need context to parse properly'); }
 
   // ESLint in "flat" mode only sets context.languageOptions.parserOptions
-  let parserOptions = (context.languageOptions && context.languageOptions.parserOptions) || context.parserOptions;
+  let parserOptions = context.languageOptions && context.languageOptions.parserOptions || context.parserOptions;
   const parserOrPath = getParser(path, context);
 
-  if (!parserOrPath) throw new Error('parserPath or languageOptions.parser is required!');
+  if (!parserOrPath) { throw new Error('parserPath or languageOptions.parser is required!'); }
 
   // hack: espree blows up with frozen options
   parserOptions = Object.assign({}, parserOptions);
@@ -103,9 +104,8 @@ exports.default = function parse(path, content, context) {
     }
     if (!ast || typeof ast !== 'object') {
       console.warn(
-        '`parseForESLint` from parser `' +
-          (typeof parserOrPath === 'string' ? parserOrPath : '`context.languageOptions.parser`') + // Can only be invalid for custom parser per imports/parser
-          '` is invalid and will just be ignored'
+        // Can only be invalid for custom parser per imports/parser
+        '`parseForESLint` from parser `' + (typeof parserOrPath === 'string' ? parserOrPath : '`context.languageOptions.parser`') + '` is invalid and will just be ignored'
       );
     } else {
       return makeParseReturn(ast, keysFromParser(parserOrPath, parser, undefined));
diff --git a/utils/pkgUp.js b/utils/pkgUp.js
index 049869719b..889f62265f 100644
--- a/utils/pkgUp.js
+++ b/utils/pkgUp.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 const fs = require('fs');
@@ -6,22 +7,22 @@ const path = require('path');
 
 /**
  * Derived significantly from package find-up@2.0.0. See license below.
- * 
+ *
  * @copyright Sindre Sorhus
  * MIT License
  *
  * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
diff --git a/utils/readPkgUp.js b/utils/readPkgUp.js
index 6a6a1eea3e..d34fa6c818 100644
--- a/utils/readPkgUp.js
+++ b/utils/readPkgUp.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 const fs = require('fs');
@@ -10,22 +11,22 @@ function stripBOM(str) {
 
 /**
  * Derived significantly from read-pkg-up@2.0.0. See license below.
- * 
+ *
  * @copyright Sindre Sorhus
  * MIT License
  *
  * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
diff --git a/utils/resolve.js b/utils/resolve.js
index 9d9dfa8439..0ed5bdb0c9 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 const fs = require('fs');
@@ -53,16 +54,16 @@ function tryRequire(target, sourceFile) {
 // https://stackoverflow.com/a/27382838
 exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings, strict) {
   // don't care if the FS is case-sensitive
-  if (CASE_SENSITIVE_FS) return true;
+  if (CASE_SENSITIVE_FS) { return true; }
 
   // null means it resolved to a builtin
-  if (filepath === null) return true;
-  if (filepath.toLowerCase() === process.cwd().toLowerCase() && !strict) return true;
+  if (filepath === null) { return true; }
+  if (filepath.toLowerCase() === process.cwd().toLowerCase() && !strict) { return true; }
   const parsedPath = path.parse(filepath);
   const dir = parsedPath.dir;
 
   let result = fileExistsCache.get(filepath, cacheSettings);
-  if (result != null) return result;
+  if (result != null) { return result; }
 
   // base case
   if (dir === '' || parsedPath.root === filepath) {
@@ -88,7 +89,7 @@ let memoizedHash = '';
 function fullResolve(modulePath, sourceFile, settings) {
   // check if this is a bonus core module
   const coreSet = new Set(settings['import/core-modules']);
-  if (coreSet.has(modulePath)) return { found: true, path: null };
+  if (coreSet.has(modulePath)) { return { found: true, path: null }; }
 
   const sourceDir = path.dirname(sourceFile);
 
@@ -102,40 +103,28 @@ function fullResolve(modulePath, sourceFile, settings) {
   const cacheSettings = ModuleCache.getSettings(settings);
 
   const cachedPath = fileExistsCache.get(cacheKey, cacheSettings);
-  if (cachedPath !== undefined) return { found: true, path: cachedPath };
+  if (cachedPath !== undefined) { return { found: true, path: cachedPath }; }
 
   function cache(resolvedPath) {
     fileExistsCache.set(cacheKey, resolvedPath);
   }
 
   function withResolver(resolver, config) {
-
-    function v1() {
-      try {
-        const resolved = resolver.resolveImport(modulePath, sourceFile, config);
-        if (resolved === undefined) return { found: false };
-        return { found: true, path: resolved };
-      } catch (err) {
-        return { found: false };
-      }
-    }
-
-    function v2() {
+    if (resolver.interfaceVersion === 2) {
       return resolver.resolve(modulePath, sourceFile, config);
     }
 
-    switch (resolver.interfaceVersion) {
-    case 2:
-      return v2();
-
-    default:
-    case 1:
-      return v1();
+    try {
+      const resolved = resolver.resolveImport(modulePath, sourceFile, config);
+      if (resolved === undefined) { return { found: false }; }
+      return { found: true, path: resolved };
+    } catch (err) {
+      return { found: false };
     }
   }
 
-  const configResolvers = (settings['import/resolver']
-    || { 'node': settings['import/resolve'] }); // backward compatibility
+  const configResolvers = settings['import/resolver']
+    || { node: settings['import/resolve'] }; // backward compatibility
 
   const resolvers = resolverReducer(configResolvers, new Map());
 
@@ -145,7 +134,7 @@ function fullResolve(modulePath, sourceFile, settings) {
     const resolver = requireResolver(name, sourceFile);
     const resolved = withResolver(resolver, config);
 
-    if (!resolved.found) continue;
+    if (!resolved.found) { continue; }
 
     // else, counts
     cache(resolved.path);
@@ -160,7 +149,7 @@ exports.relative = relative;
 
 function resolverReducer(resolvers, map) {
   if (Array.isArray(resolvers)) {
-    resolvers.forEach(r => resolverReducer(r, map));
+    resolvers.forEach((r) => resolverReducer(r, map));
     return map;
   }
 
@@ -186,9 +175,9 @@ function getBaseDir(sourceFile) {
 }
 function requireResolver(name, sourceFile) {
   // Try to resolve package with conventional name
-  const resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile) ||
-    tryRequire(name, sourceFile) ||
-    tryRequire(path.resolve(getBaseDir(sourceFile), name));
+  const resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile)
+    || tryRequire(name, sourceFile)
+    || tryRequire(path.resolve(getBaseDir(sourceFile), name));
 
   if (!resolver) {
     const err = new Error(`unable to load resolver "${name}".`);
diff --git a/utils/unambiguous.js b/utils/unambiguous.js
index 75f21693b7..24cb123157 100644
--- a/utils/unambiguous.js
+++ b/utils/unambiguous.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))|import\(/m;
@@ -25,5 +26,5 @@ const unambiguousNodeType = /^(?:(?:Exp|Imp)ort.*Declaration|TSExportAssignment)
  * @return {Boolean}
  */
 exports.isModule = function isUnambiguousModule(ast) {
-  return ast.body && ast.body.some(node => unambiguousNodeType.test(node.type));
+  return ast.body && ast.body.some((node) => unambiguousNodeType.test(node.type));
 };
diff --git a/utils/visit.js b/utils/visit.js
index 77b09850ae..6178faeaa0 100644
--- a/utils/visit.js
+++ b/utils/visit.js
@@ -1,4 +1,5 @@
 'use strict';
+
 exports.__esModule = true;
 
 exports.default = function visit(node, keys, visitorSpec) {

From 7e9f651625ac6835ec73f21490ecd68eebac100b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 Apr 2023 16:41:18 -0700
Subject: [PATCH 580/767] [resolvers] [*] [deps] update `is-core-module`,
 `resolve`

---
 resolvers/node/package.json    | 4 ++--
 resolvers/webpack/package.json | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index d13b48635f..c63ee976b6 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -30,8 +30,8 @@
   "homepage": "https://github.com/import-js/eslint-plugin-import",
   "dependencies": {
     "debug": "^3.2.7",
-    "is-core-module": "^2.11.0",
-    "resolve": "^1.22.1"
+    "is-core-module": "^2.12.0",
+    "resolve": "^1.22.2"
   },
   "devDependencies": {
     "chai": "^3.5.0",
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 42d5e7470e..ba21801e61 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -36,10 +36,10 @@
     "find-root": "^1.1.0",
     "has": "^1.0.3",
     "interpret": "^1.4.0",
-    "is-core-module": "^2.11.0",
+    "is-core-module": "^2.12.0",
     "is-regex": "^1.1.4",
     "lodash": "^4.17.21",
-    "resolve": "^1.22.1",
+    "resolve": "^1.22.2",
     "semver": "^5.7.1"
   },
   "peerDependencies": {

From a89eadf3247af844da6b0f9e7bca7690777bf665 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 13 Apr 2023 16:44:24 -0700
Subject: [PATCH 581/767] [deps] update `is-core-module`, `resolve`

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 3733e2d76f..013422c71e 100644
--- a/package.json
+++ b/package.json
@@ -108,11 +108,11 @@
     "eslint-import-resolver-node": "^0.3.7",
     "eslint-module-utils": "^2.7.4",
     "has": "^1.0.3",
-    "is-core-module": "^2.11.0",
+    "is-core-module": "^2.12.0",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.values": "^1.1.6",
-    "resolve": "^1.22.1",
+    "resolve": "^1.22.2",
     "semver": "^6.3.0",
     "tsconfig-paths": "^3.14.2"
   }

From 1fa29717518732e3143aaf8155713133c383bf3c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 Apr 2023 11:48:48 -0700
Subject: [PATCH 582/767] [Fix] `order`: partial fix for #2687

---
 src/rules/order.js           | 12 +++---
 tests/src/core/importType.js |  4 ++
 tests/src/rules/order.js     | 73 +++++++++++++++++++++++++++++++++---
 3 files changed, 79 insertions(+), 10 deletions(-)

diff --git a/src/rules/order.js b/src/rules/order.js
index 5921989d2b..27c3f4b0f9 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -253,6 +253,7 @@ function makeOutOfOrderReport(context, imported) {
   if (!outOfOrder.length) {
     return;
   }
+
   // There are things to report. Try to minimize the number of reported errors.
   const reversedImported = reverse(imported);
   const reversedOrder = findOutOfOrder(reversedImported);
@@ -426,11 +427,12 @@ const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling'
 // Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
 // Will throw an error if it contains a type that does not exist, or has a duplicate
 function convertGroupsToRanks(groups) {
+  if (groups.length === 1) {
+    // TODO: remove this `if` and fix the bug
+    return convertGroupsToRanks(groups[0]);
+  }
   const rankObject = groups.reduce(function (res, group, index) {
-    if (typeof group === 'string') {
-      group = [group];
-    }
-    group.forEach(function (groupItem) {
+    [].concat(group).forEach(function (groupItem) {
       if (types.indexOf(groupItem) === -1) {
         throw new Error(`Incorrect configuration of the rule: Unknown type \`${JSON.stringify(groupItem)}\``);
       }
@@ -443,7 +445,7 @@ function convertGroupsToRanks(groups) {
   }, {});
 
   const omittedTypes = types.filter(function (type) {
-    return rankObject[type] === undefined;
+    return typeof rankObject[type] === 'undefined';
   });
 
   const ranks = omittedTypes.reduce(function (res, type) {
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 937f193033..bdc93d8a3e 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -17,7 +17,11 @@ describe('importType(name)', function () {
 
   it("should return 'builtin' for node.js modules", function () {
     expect(importType('fs', context)).to.equal('builtin');
+    expect(importType('node:fs', context)).to.equal('builtin');
+    expect(importType('fs/promises', context)).to.equal('builtin');
+    expect(importType('node:fs/promises', context)).to.equal('builtin');
     expect(importType('path', context)).to.equal('builtin');
+    expect(importType('node:path', context)).to.equal('builtin');
   });
 
   it("should return 'external' for non-builtin modules without a relative path", function () {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 8d0b315e71..e7a9cb9c9b 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -3174,11 +3174,10 @@ context('TypeScript', function () {
                 import type { ParsedPath } from 'path';
               }
             `,
-            errors: [{
-              message: '`fs` type import should occur before type import of `path`',
-            }, {
-              message: '`fs` type import should occur before type import of `path`',
-            }],
+            errors: [
+              { message: '`fs` type import should occur before type import of `path`' },
+              { message: '`fs` type import should occur before type import of `path`' },
+            ],
             ...parserConfig,
             options: [
               {
@@ -3186,6 +3185,70 @@ context('TypeScript', function () {
               },
             ],
           }),
+
+          test({
+            code: `
+              import express from 'express';
+              import log4js from 'log4js';
+              import chpro from 'node:child_process';
+              // import fsp from 'node:fs/promises';
+            `,
+            output: `
+              import chpro from 'node:child_process';
+              import express from 'express';
+              import log4js from 'log4js';
+              // import fsp from 'node:fs/promises';
+            `,
+            options: [{
+              groups: [
+                'builtin',
+                'external',
+                'internal',
+                'parent',
+                'sibling',
+                'index',
+                'object',
+                'type',
+              ],
+            }],
+            errors: [
+              { message: '`node:child_process` import should occur before import of `express`' },
+              // { message: '`node:fs/promises` import should occur before import of `express`' },
+            ],
+          }),
+
+          test({
+            code: `
+              import express from 'express';
+              import log4js from 'log4js';
+              import chpro from 'node:child_process';
+              // import fsp from 'node:fs/promises';
+            `,
+            output: `
+              import chpro from 'node:child_process';
+              import express from 'express';
+              import log4js from 'log4js';
+              // import fsp from 'node:fs/promises';
+            `,
+            options: [{
+              groups: [
+                [
+                  'builtin',
+                  'external',
+                  'internal',
+                  'parent',
+                  'sibling',
+                  'index',
+                  'object',
+                  'type',
+                ],
+              ],
+            }],
+            errors: [
+              { message: '`node:child_process` import should occur before import of `express`' },
+              // { message: '`node:fs/promises` import should occur before import of `express`' },
+            ],
+          }),
         ],
       });
     });

From ef094f2031dcb219e3aae1a9b508d8d49fd2489f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 Apr 2023 11:50:25 -0700
Subject: [PATCH 583/767] [meta] add missing CHANGELOG entry

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe7f6771b8..8a8ec36692 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`consistent-type-specifier-style`]: fix accidental removal of comma in certain cases ([#2754], thanks [@bradzacher])
 - [Perf] `ExportMap`: Improve `ExportMap.for` performance on larger codebases ([#2756], thanks [@leipert])
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing inline type from dev dependencies ([#1820], thanks [@andyogo])
+* [`order`]: partial fix for [#2687] (thanks [@ljharb])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
@@ -1397,6 +1398,7 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+[#2687]: https://github.com/import-js/eslint-plugin-import/issues/2687
 [#2684]: https://github.com/import-js/eslint-plugin-import/issues/2684
 [#2674]: https://github.com/import-js/eslint-plugin-import/issues/2674
 [#2668]: https://github.com/import-js/eslint-plugin-import/issues/2668

From 261ee3aa7666edb0131e08db3d3d3428b013df42 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 Apr 2023 11:51:58 -0700
Subject: [PATCH 584/767] [Deps] update `resolve`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 013422c71e..a0fdc66100 100644
--- a/package.json
+++ b/package.json
@@ -112,7 +112,7 @@
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.values": "^1.1.6",
-    "resolve": "^1.22.2",
+    "resolve": "^1.22.3",
     "semver": "^6.3.0",
     "tsconfig-paths": "^3.14.2"
   }

From 4c6fa3e1e47198eb448690c1c5ef486c162e6c00 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 Apr 2023 11:58:36 -0700
Subject: [PATCH 585/767] [Tests] fix tests for older nodes

---
 tests/src/core/importType.js |  13 ++--
 tests/src/rules/order.js     | 113 ++++++++++++++++++-----------------
 2 files changed, 65 insertions(+), 61 deletions(-)

diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index bdc93d8a3e..c4dca866e2 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -1,5 +1,6 @@
 import { expect } from 'chai';
 import * as path from 'path';
+import isCoreModule from 'is-core-module';
 
 import importType, { isExternalModule, isScoped, isAbsolute } from 'core/importType';
 
@@ -16,12 +17,12 @@ describe('importType(name)', function () {
   });
 
   it("should return 'builtin' for node.js modules", function () {
-    expect(importType('fs', context)).to.equal('builtin');
-    expect(importType('node:fs', context)).to.equal('builtin');
-    expect(importType('fs/promises', context)).to.equal('builtin');
-    expect(importType('node:fs/promises', context)).to.equal('builtin');
-    expect(importType('path', context)).to.equal('builtin');
-    expect(importType('node:path', context)).to.equal('builtin');
+    ['fs', 'fs/promises', 'path'].filter((x) => isCoreModule(x)).forEach((x) => {
+      expect(importType(x, context)).to.equal('builtin');
+      if (isCoreModule(`node:${x}`)) {
+        expect(importType(`node:${x}`, context)).to.equal('builtin');
+      }
+    });
   });
 
   it("should return 'external' for non-builtin modules without a relative path", function () {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index e7a9cb9c9b..84b341e1b0 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -5,6 +5,7 @@ import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import flatMap from 'array.prototype.flatmap';
 import { resolve } from 'path';
+import isCoreModule from 'is-core-module';
 import { default as babelPresetFlow } from 'babel-preset-flow';
 
 const ruleTester = new RuleTester();
@@ -2962,7 +2963,7 @@ context('TypeScript', function () {
             ],
           }),
         ],
-        invalid: [
+        invalid: [].concat(
           // Option alphabetize: {order: 'asc'}
           test({
             code: `
@@ -3186,53 +3187,22 @@ context('TypeScript', function () {
             ],
           }),
 
-          test({
-            code: `
-              import express from 'express';
-              import log4js from 'log4js';
-              import chpro from 'node:child_process';
-              // import fsp from 'node:fs/promises';
-            `,
-            output: `
-              import chpro from 'node:child_process';
-              import express from 'express';
-              import log4js from 'log4js';
-              // import fsp from 'node:fs/promises';
-            `,
-            options: [{
-              groups: [
-                'builtin',
-                'external',
-                'internal',
-                'parent',
-                'sibling',
-                'index',
-                'object',
-                'type',
-              ],
-            }],
-            errors: [
-              { message: '`node:child_process` import should occur before import of `express`' },
-              // { message: '`node:fs/promises` import should occur before import of `express`' },
-            ],
-          }),
-
-          test({
-            code: `
-              import express from 'express';
-              import log4js from 'log4js';
-              import chpro from 'node:child_process';
-              // import fsp from 'node:fs/promises';
-            `,
-            output: `
-              import chpro from 'node:child_process';
-              import express from 'express';
-              import log4js from 'log4js';
-              // import fsp from 'node:fs/promises';
-            `,
-            options: [{
-              groups: [
-                [
+          isCoreModule('node:child_process') && isCoreModule('node:fs/promises') ? [
+            test({
+              code: `
+                import express from 'express';
+                import log4js from 'log4js';
+                import chpro from 'node:child_process';
+                // import fsp from 'node:fs/promises';
+              `,
+              output: `
+                import chpro from 'node:child_process';
+                import express from 'express';
+                import log4js from 'log4js';
+                // import fsp from 'node:fs/promises';
+              `,
+              options: [{
+                groups: [
                   'builtin',
                   'external',
                   'internal',
@@ -3242,14 +3212,47 @@ context('TypeScript', function () {
                   'object',
                   'type',
                 ],
+              }],
+              errors: [
+                { message: '`node:child_process` import should occur before import of `express`' },
+                // { message: '`node:fs/promises` import should occur before import of `express`' },
               ],
-            }],
-            errors: [
-              { message: '`node:child_process` import should occur before import of `express`' },
-              // { message: '`node:fs/promises` import should occur before import of `express`' },
-            ],
-          }),
-        ],
+            }),
+
+            test({
+              code: `
+                import express from 'express';
+                import log4js from 'log4js';
+                import chpro from 'node:child_process';
+                // import fsp from 'node:fs/promises';
+              `,
+              output: `
+                import chpro from 'node:child_process';
+                import express from 'express';
+                import log4js from 'log4js';
+                // import fsp from 'node:fs/promises';
+              `,
+              options: [{
+                groups: [
+                  [
+                    'builtin',
+                    'external',
+                    'internal',
+                    'parent',
+                    'sibling',
+                    'index',
+                    'object',
+                    'type',
+                  ],
+                ],
+              }],
+              errors: [
+                { message: '`node:child_process` import should occur before import of `express`' },
+                // { message: '`node:fs/promises` import should occur before import of `express`' },
+              ],
+            }),
+          ] : [],
+        ),
       });
     });
 });

From 463ce199da3002cbf49d56917085bed94b5a43de Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 Apr 2023 12:03:43 -0700
Subject: [PATCH 586/767] [utils] v2.8.0

---
 utils/CHANGELOG.md | 9 ++++++++-
 utils/package.json | 2 +-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 7d2057dec2..ae3588a390 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.8.0 - 2023-04-14
+
+### New
+- `parse`: support flat config ([#2714], thanks [@DMartens])
+
 ### Fixed
 - Improve performance of `fullResolve` for large projects ([#2755], thanks [@leipert])
 
@@ -19,7 +24,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## v2.7.3 - 2022-01-26
 
 ### Fixed
-- [Fix] `parse`: restore compatibility by making the return value `ast` again ([#2350], thanks [@ljharb])
+- `parse`: restore compatibility by making the return value `ast` again ([#2350], thanks [@ljharb])
 
 ## v2.7.2 - 2022-01-01
 
@@ -127,6 +132,7 @@ Yanked due to critical issue with cache key resulting from #839.
 - `unambiguous.test()` regex is now properly in multiline mode
 
 [#2755]: https://github.com/import-js/eslint-plugin-import/pull/2755
+[#2714]: https://github.com/import-js/eslint-plugin-import/pull/2714
 [#2523]: https://github.com/import-js/eslint-plugin-import/pull/2523
 [#2431]: https://github.com/import-js/eslint-plugin-import/pull/2431
 [#2350]: https://github.com/import-js/eslint-plugin-import/issues/2350
@@ -159,6 +165,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@bradzacher]: https://github.com/bradzacher
 [@brettz9]: https://github.com/brettz9
 [@christophercurrie]: https://github.com/christophercurrie
+[@DMartens]: https://github.com/DMartens
 [@hulkish]: https://github.com/hulkish
 [@Hypnosphi]: https://github.com/Hypnosphi
 [@iamnapo]: https://github.com/iamnapo
diff --git a/utils/package.json b/utils/package.json
index 0c0678a5ec..d56c442b1a 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.7.4",
+  "version": "2.8.0",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From 683d3a5927adf97a1654cfb4d9d3caf148e1eb8a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 14 Apr 2023 13:02:33 -0700
Subject: [PATCH 587/767] [Deps] update `eslint-module-utils`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index a0fdc66100..59ab24c57b 100644
--- a/package.json
+++ b/package.json
@@ -106,7 +106,7 @@
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.7",
-    "eslint-module-utils": "^2.7.4",
+    "eslint-module-utils": "^2.8.0",
     "has": "^1.0.3",
     "is-core-module": "^2.12.0",
     "is-glob": "^4.0.3",

From eaa1591c47679b3523696bca346d997b9598b508 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 17 Apr 2023 13:58:40 -0700
Subject: [PATCH 588/767] [Tests] switch some files to unix line endings

---
 tests/files/foo-bar-resolver-no-version.js | 24 +++++++++----------
 tests/files/foo-bar-resolver-v1.js         | 28 +++++++++++-----------
 tests/files/foo-bar-resolver-v2.js         | 28 +++++++++++-----------
 3 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/tests/files/foo-bar-resolver-no-version.js b/tests/files/foo-bar-resolver-no-version.js
index f00198562e..2a2d451850 100644
--- a/tests/files/foo-bar-resolver-no-version.js
+++ b/tests/files/foo-bar-resolver-no-version.js
@@ -1,12 +1,12 @@
-var path = require('path')
-
-exports.resolveImport = function (modulePath, sourceFile, config) {
-  var sourceFileName = path.basename(sourceFile)
-  if (sourceFileName === 'foo.js') {
-    return path.join(__dirname, 'bar.jsx')
-  }
-  if (sourceFileName === 'exception.js') {
-    throw new Error('foo-bar-resolver-v1 resolveImport test exception')
-  }
-  return undefined;
-}
+var path = require('path')
+
+exports.resolveImport = function (modulePath, sourceFile, config) {
+  var sourceFileName = path.basename(sourceFile)
+  if (sourceFileName === 'foo.js') {
+    return path.join(__dirname, 'bar.jsx')
+  }
+  if (sourceFileName === 'exception.js') {
+    throw new Error('foo-bar-resolver-v1 resolveImport test exception')
+  }
+  return undefined;
+}
diff --git a/tests/files/foo-bar-resolver-v1.js b/tests/files/foo-bar-resolver-v1.js
index af9da1b7a6..7ba97cb55f 100644
--- a/tests/files/foo-bar-resolver-v1.js
+++ b/tests/files/foo-bar-resolver-v1.js
@@ -1,14 +1,14 @@
-var path = require('path')
-
-exports.resolveImport = function (modulePath, sourceFile, config) {
-  var sourceFileName = path.basename(sourceFile)
-  if (sourceFileName === 'foo.js') {
-    return path.join(__dirname, 'bar.jsx');
-  }
-  if (sourceFileName === 'exception.js') {
-    throw new Error('foo-bar-resolver-v1 resolveImport test exception');
-  }
-  return undefined;
-};
-
-exports.interfaceVersion = 1;
+var path = require('path')
+
+exports.resolveImport = function (modulePath, sourceFile, config) {
+  var sourceFileName = path.basename(sourceFile)
+  if (sourceFileName === 'foo.js') {
+    return path.join(__dirname, 'bar.jsx');
+  }
+  if (sourceFileName === 'exception.js') {
+    throw new Error('foo-bar-resolver-v1 resolveImport test exception');
+  }
+  return undefined;
+};
+
+exports.interfaceVersion = 1;
diff --git a/tests/files/foo-bar-resolver-v2.js b/tests/files/foo-bar-resolver-v2.js
index 7f8bcc0f86..13135e3925 100644
--- a/tests/files/foo-bar-resolver-v2.js
+++ b/tests/files/foo-bar-resolver-v2.js
@@ -1,14 +1,14 @@
-var path = require('path')
-
-exports.resolve = function (modulePath, sourceFile, config) {
-  var sourceFileName = path.basename(sourceFile)
-  if (sourceFileName === 'foo.js') {
-    return { found: true, path: path.join(__dirname, 'bar.jsx') }
-  }
-  if (sourceFileName === 'exception.js') {
-    throw new Error('foo-bar-resolver-v2 resolve test exception')
-  }
-  return { found: false };
-};
-
-exports.interfaceVersion = 2;
+var path = require('path')
+
+exports.resolve = function (modulePath, sourceFile, config) {
+  var sourceFileName = path.basename(sourceFile)
+  if (sourceFileName === 'foo.js') {
+    return { found: true, path: path.join(__dirname, 'bar.jsx') }
+  }
+  if (sourceFileName === 'exception.js') {
+    throw new Error('foo-bar-resolver-v2 resolve test exception')
+  }
+  return { found: false };
+};
+
+exports.interfaceVersion = 2;

From afaefbbda83ed7b637ed4a039be6ad19727ea244 Mon Sep 17 00:00:00 2001
From: JounQin <admin@1stg.me>
Date: Sun, 7 Aug 2022 12:29:33 +0800
Subject: [PATCH 589/767] [Refactor] `ExportMap`: rename `tsConfig` to
 `tsconfig`

---
 src/ExportMap.js | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/ExportMap.js b/src/ExportMap.js
index cd5bad56c3..f61d3c170a 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -24,7 +24,7 @@ let ts;
 const log = debug('eslint-plugin-import:ExportMap');
 
 const exportCache = new Map();
-const tsConfigCache = new Map();
+const tsconfigCache = new Map();
 
 export default class ExportMap {
   constructor(path) {
@@ -549,20 +549,20 @@ ExportMap.parse = function (path, content, context) {
   const source = makeSourceCode(content, ast);
 
   function readTsConfig(context) {
-    const tsConfigInfo = tsConfigLoader({
+    const tsconfigInfo = tsConfigLoader({
       cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
       getEnv: (key) => process.env[key],
     });
     try {
-      if (tsConfigInfo.tsConfigPath !== undefined) {
+      if (tsconfigInfo.tsConfigPath !== undefined) {
         // Projects not using TypeScript won't have `typescript` installed.
         if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
 
-        const configFile = ts.readConfigFile(tsConfigInfo.tsConfigPath, ts.sys.readFile);
+        const configFile = ts.readConfigFile(tsconfigInfo.tsConfigPath, ts.sys.readFile);
         return ts.parseJsonConfigFileContent(
           configFile.config,
           ts.sys,
-          dirname(tsConfigInfo.tsConfigPath),
+          dirname(tsconfigInfo.tsConfigPath),
         );
       }
     } catch (e) {
@@ -576,10 +576,10 @@ ExportMap.parse = function (path, content, context) {
     const cacheKey = hashObject({
       tsconfigRootDir: context.parserOptions && context.parserOptions.tsconfigRootDir,
     }).digest('hex');
-    let tsConfig = tsConfigCache.get(cacheKey);
+    let tsConfig = tsconfigCache.get(cacheKey);
     if (typeof tsConfig === 'undefined') {
       tsConfig = readTsConfig(context);
-      tsConfigCache.set(cacheKey, tsConfig);
+      tsconfigCache.set(cacheKey, tsConfig);
     }
 
     return tsConfig && tsConfig.options ? tsConfig.options.esModuleInterop : false;

From 328064abc707d3289772a8a29da5783c6dc345f6 Mon Sep 17 00:00:00 2001
From: silverwind <me@silverwind.io>
Date: Tue, 18 Apr 2023 20:03:39 +0200
Subject: [PATCH 590/767] Fix invalid YAML in import/parsers example

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 5c6f1a3211..ca99b8fafb 100644
--- a/README.md
+++ b/README.md
@@ -355,7 +355,7 @@ directly using webpack, for example:
 # .eslintrc.yml
 settings:
   import/parsers:
-    @typescript-eslint/parser: [ .ts, .tsx ]
+    "@typescript-eslint/parser": [ .ts, .tsx ]
 ```
 
 In this case, [`@typescript-eslint/parser`](https://www.npmjs.com/package/@typescript-eslint/parser)

From 88dd8153571373151c3c7b508c5944cb2bba1588 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 28 May 2023 09:02:13 -0800
Subject: [PATCH 591/767] [Deps] update `is-core-module`

---
 package.json         | 2 +-
 src/rules/default.js | 2 --
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 59ab24c57b..feee6e46de 100644
--- a/package.json
+++ b/package.json
@@ -108,7 +108,7 @@
     "eslint-import-resolver-node": "^0.3.7",
     "eslint-module-utils": "^2.8.0",
     "has": "^1.0.3",
-    "is-core-module": "^2.12.0",
+    "is-core-module": "^2.12.1",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.values": "^1.1.6",
diff --git a/src/rules/default.js b/src/rules/default.js
index f6b786020d..297a80c463 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -13,9 +13,7 @@ module.exports = {
   },
 
   create(context) {
-
     function checkDefault(specifierType, node) {
-
       const defaultSpecifier = node.specifiers.find(
         (specifier) => specifier.type === specifierType,
       );

From a24a03b5ab4a257c78e5e0742b08023a002645e0 Mon Sep 17 00:00:00 2001
From: Kirill Korolyov <kirill.korolyov@gmail.com>
Date: Mon, 3 Jul 2023 21:18:16 +0100
Subject: [PATCH 592/767] [meta] Add "eslint-plugin" to the list of keywords in
 package.json

---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index feee6e46de..37911c90d8 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
   "keywords": [
     "eslint",
     "eslintplugin",
+    "eslint-plugin",
     "es6",
     "jsnext",
     "modules",

From 66e755fb32d900517df97efcd7707561a53dfc99 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 3 Jul 2023 22:37:00 -0500
Subject: [PATCH 593/767] [Refactor] `exports-last`: use
 `array.prototype.findlastindex`

---
 CHANGELOG.md              |  1 +
 package.json              |  1 +
 src/rules/exports-last.js | 11 ++++-------
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a8ec36692..2c0fe3fdf0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
 - [Docs] [`group-exports`]: fix syntax highlighting ([#2699], thanks [@devinrhode2])
 - [Docs] [`extensions`]: reference node ESM behavior ([#2748], thanks [@xM8WVqaG])
+- [Refactor] [`exports-last`]: use `array.prototype.findlastindex` (thanks [@ljharb])
 
 ## [2.27.5] - 2023-01-16
 
diff --git a/package.json b/package.json
index 37911c90d8..9127841b3d 100644
--- a/package.json
+++ b/package.json
@@ -102,6 +102,7 @@
   },
   "dependencies": {
     "array-includes": "^3.1.6",
+    "array.prototype.findlastindex": "^1.2.2",
     "array.prototype.flat": "^1.3.1",
     "array.prototype.flatmap": "^1.3.1",
     "debug": "^3.2.7",
diff --git a/src/rules/exports-last.js b/src/rules/exports-last.js
index c4ed97e22f..1e79f8339c 100644
--- a/src/rules/exports-last.js
+++ b/src/rules/exports-last.js
@@ -1,3 +1,5 @@
+import findLastIndex from 'array.prototype.findlastindex';
+
 import docsUrl from '../docsUrl';
 
 function isNonExportStatement({ type }) {
@@ -20,15 +22,10 @@ module.exports = {
   create(context) {
     return {
       Program({ body }) {
-        const lastNonExportStatementIndex = body.reduce(function findLastIndex(acc, item, index) {
-          if (isNonExportStatement(item)) {
-            return index;
-          }
-          return acc;
-        }, -1);
+        const lastNonExportStatementIndex = findLastIndex(body, isNonExportStatement);
 
         if (lastNonExportStatementIndex !== -1) {
-          body.slice(0, lastNonExportStatementIndex).forEach(function checkNonExport(node) {
+          body.slice(0, lastNonExportStatementIndex).forEach((node) => {
             if (!isNonExportStatement(node)) {
               context.report({
                 node,

From 2c196b097f7812992c5987c45ce53e33a66a8021 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 3 Jul 2023 22:44:09 -0500
Subject: [PATCH 594/767] [Refactor] `no-anonymous-default-export`: use
 `object.fromentries`

---
 CHANGELOG.md                             |  1 +
 package.json                             |  1 +
 src/rules/no-anonymous-default-export.js | 12 +++++-------
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c0fe3fdf0..fdc41210b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] [`group-exports`]: fix syntax highlighting ([#2699], thanks [@devinrhode2])
 - [Docs] [`extensions`]: reference node ESM behavior ([#2748], thanks [@xM8WVqaG])
 - [Refactor] [`exports-last`]: use `array.prototype.findlastindex` (thanks [@ljharb])
+- [Refactor] [`no-anonymous-default-export`]: use `object.fromentries` (thanks [@ljharb])
 
 ## [2.27.5] - 2023-01-16
 
diff --git a/package.json b/package.json
index 9127841b3d..763b5efc0c 100644
--- a/package.json
+++ b/package.json
@@ -113,6 +113,7 @@
     "is-core-module": "^2.12.1",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
+    "object.fromentries": "^2.0.6",
     "object.values": "^1.1.6",
     "resolve": "^1.22.3",
     "semver": "^6.3.0",
diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js
index 80950d550e..06ea854b33 100644
--- a/src/rules/no-anonymous-default-export.js
+++ b/src/rules/no-anonymous-default-export.js
@@ -3,8 +3,11 @@
  * @author Duncan Beevers
  */
 
-import docsUrl from '../docsUrl';
 import has from 'has';
+import values from 'object.values';
+import fromEntries from 'object.fromentries';
+
+import docsUrl from '../docsUrl';
 
 const defs = {
   ArrayExpression: {
@@ -68,12 +71,7 @@ const schemaProperties = Object.keys(defs)
     return acc;
   }, {});
 
-const defaults = Object.keys(defs)
-  .map((key) => defs[key])
-  .reduce((acc, def) => {
-    acc[def.option] = has(def, 'default') ? def.default : false;
-    return acc;
-  }, {});
+const defaults = fromEntries(values(defs).map((def) => [def.option, has(def, 'default') ? def.default : false]));
 
 module.exports = {
   meta: {

From 3a5ad34ca69a5c3239fff56241eb7e353d87274c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 3 Jul 2023 22:48:40 -0500
Subject: [PATCH 595/767] [Refactor] `no-unused-modules`: use
 `array.prototype.flatmap`

---
 CHANGELOG.md                   |  1 +
 src/rules/no-unused-modules.js | 24 ++++++++++--------------
 2 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fdc41210b4..68d7156784 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] [`extensions`]: reference node ESM behavior ([#2748], thanks [@xM8WVqaG])
 - [Refactor] [`exports-last`]: use `array.prototype.findlastindex` (thanks [@ljharb])
 - [Refactor] [`no-anonymous-default-export`]: use `object.fromentries` (thanks [@ljharb])
+- [Refactor] [`no-unused-modules`]: use `array.prototype.flatmap` (thanks [@ljharb])
 
 ## [2.27.5] - 2023-01-16
 
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 4b09128a10..a2b6f4ea27 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -4,15 +4,17 @@
  * @author René Fermann
  */
 
-import Exports, { recursivePatternCapture } from '../ExportMap';
 import { getFileExtensions } from 'eslint-module-utils/ignore';
 import resolve from 'eslint-module-utils/resolve';
 import visit from 'eslint-module-utils/visit';
-import docsUrl from '../docsUrl';
 import { dirname, join } from 'path';
 import readPkgUp from 'eslint-module-utils/readPkgUp';
 import values from 'object.values';
 import includes from 'array-includes';
+import flatMap from 'array.prototype.flatmap';
+
+import Exports, { recursivePatternCapture } from '../ExportMap';
+import docsUrl from '../docsUrl';
 
 let FileEnumerator;
 let listFilesToProcess;
@@ -40,12 +42,7 @@ try {
       const { listFilesToProcess: originalListFilesToProcess } = require('eslint/lib/util/glob-util');
 
       listFilesToProcess = function (src, extensions) {
-        const patterns = src.reduce(
-          (carry, pattern) => carry.concat(
-            extensions.map((extension) => (/\*\*|\*\./).test(pattern) ? pattern : `${pattern}/**/*${extension}`),
-          ),
-          src,
-        );
+        const patterns = src.concat(flatMap(src, (pattern) => extensions.map((extension) => (/\*\*|\*\./).test(pattern) ? pattern : `${pattern}/**/*${extension}`)));
 
         return originalListFilesToProcess(patterns);
       };
@@ -171,18 +168,17 @@ const isNodeModule = (path) => (/\/(node_modules)\//).test(path);
 const resolveFiles = (src, ignoreExports, context) => {
   const extensions = Array.from(getFileExtensions(context.settings));
 
-  const srcFiles = new Set();
   const srcFileList = listFilesToProcess(src, extensions);
 
   // prepare list of ignored files
-  const ignoredFilesList =  listFilesToProcess(ignoreExports, extensions);
+  const ignoredFilesList = listFilesToProcess(ignoreExports, extensions);
   ignoredFilesList.forEach(({ filename }) => ignoredFiles.add(filename));
 
   // prepare list of source files, don't consider files from node_modules
-  srcFileList.filter(({ filename }) => !isNodeModule(filename)).forEach(({ filename }) => {
-    srcFiles.add(filename);
-  });
-  return srcFiles;
+
+  return new Set(
+    srcFileList.filter(({ filename }) => !isNodeModule(filename)).map(({ filename }) => filename),
+  );
 };
 
 /**

From ee00a1cc702cdfccbb2f10cddcb2797827115974 Mon Sep 17 00:00:00 2001
From: laurens-dg <laurens.degraeve@outlook.com>
Date: Tue, 18 Jul 2023 15:35:15 +0200
Subject: [PATCH 596/767] [Fix] guard against empty parent

---
 CHANGELOG.md                            |  3 +++
 src/rules/newline-after-import.js       |  5 +++++
 tests/src/rules/newline-after-import.js | 16 +++++++++++++---
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 68d7156784..dcfb192d2a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`consistent-type-specifier-style`]: fix accidental removal of comma in certain cases ([#2754], thanks [@bradzacher])
 - [Perf] `ExportMap`: Improve `ExportMap.for` performance on larger codebases ([#2756], thanks [@leipert])
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing inline type from dev dependencies ([#1820], thanks [@andyogo])
+- [`newline-after-import`]/TypeScript: do not error when re-exporting a namespaced import ([#2832], thanks [@laurens-dg])
 * [`order`]: partial fix for [#2687] (thanks [@ljharb])
 
 ### Changed
@@ -1072,6 +1073,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2832]: https://github.com/import-js/eslint-plugin-import/pull/2832
 [#2756]: https://github.com/import-js/eslint-plugin-import/pull/2756
 [#2754]: https://github.com/import-js/eslint-plugin-import/pull/2754
 [#2748]: https://github.com/import-js/eslint-plugin-import/pull/2748
@@ -1746,6 +1748,7 @@ for info on changes for earlier releases.
 [@KostyaZgara]: https://github.com/KostyaZgara
 [@kylemh]: https://github.com/kylemh
 [@laysent]: https://github.com/laysent
+[@laurens-dg]: https://github.com/laurens-dg
 [@le0nik]: https://github.com/le0nik
 [@leipert]: https://github.com/leipert
 [@lemonmade]: https://github.com/lemonmade
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index c63bb21b24..8855e26e52 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -149,6 +149,11 @@ module.exports = {
 
     function checkImport(node) {
       const { parent } = node;
+
+      if (!parent || !parent.body) {
+        return;
+      }
+
       const nodePosition = parent.body.indexOf(node);
       const nextNode = parent.body[nodePosition + 1];
       const endLine = node.loc.end.line;
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 5e14b570ee..9ec6eb757b 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -26,7 +26,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       code: `
         const x = () => require('baz')
             , y = () => require('bar')
-            
+
         // some comment here
       `,
       parserOptions: { ecmaVersion: 6 },
@@ -273,6 +273,16 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         parser,
         parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       },
+      {
+        code: `
+        import { ns } from 'namespace';
+        import Bar = ns.baz.foo.Bar;
+
+        export import Foo = ns.baz.bar.Foo;
+      `,
+        parser,
+        parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      },
     )),
     {
       code: `
@@ -299,7 +309,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
     {
       code: `
         import path from 'path';import foo from 'foo';
-        
+
         /**
          * some multiline comment here
          * another line of comment
@@ -313,7 +323,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       code: `
         import path from 'path';
         import foo from 'foo';
-        
+
         // Some random single line comment
         var bar = 42;
       `,

From e2cf99c21130404fbf68394434b8cfa6d88a1bd0 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 24 Jul 2023 11:34:22 -0700
Subject: [PATCH 597/767] [Deps] update `semver`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 763b5efc0c..e870082e34 100644
--- a/package.json
+++ b/package.json
@@ -116,7 +116,7 @@
     "object.fromentries": "^2.0.6",
     "object.values": "^1.1.6",
     "resolve": "^1.22.3",
-    "semver": "^6.3.0",
+    "semver": "^6.3.1",
     "tsconfig-paths": "^3.14.2"
   }
 }

From f302f7d31d28c91bd483c5da14600ce6e26cd0e3 Mon Sep 17 00:00:00 2001
From: ben <benkrejci@gmail.com>
Date: Tue, 18 Jul 2023 21:46:55 -0400
Subject: [PATCH 598/767] [Fix] `no-duplicates`: Prefer combined type and
 regular imports when using `prefer-inline`

---
 CHANGELOG.md                     |  3 +++
 docs/rules/no-duplicates.md      |  5 +++++
 src/rules/no-duplicates.js       |  5 +++--
 tests/src/rules/no-duplicates.js | 19 +++++++++++++++++++
 4 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dcfb192d2a..a46b1b0326 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing inline type from dev dependencies ([#1820], thanks [@andyogo])
 - [`newline-after-import`]/TypeScript: do not error when re-exporting a namespaced import ([#2832], thanks [@laurens-dg])
 * [`order`]: partial fix for [#2687] (thanks [@ljharb])
+- [`no-duplicates`]: Detect across type and regular imports ([#2835], thanks [@benkrejci])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
@@ -1073,6 +1074,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2835]: https://github.com/import-js/eslint-plugin-import/pull/2835
 [#2832]: https://github.com/import-js/eslint-plugin-import/pull/2832
 [#2756]: https://github.com/import-js/eslint-plugin-import/pull/2756
 [#2754]: https://github.com/import-js/eslint-plugin-import/pull/2754
@@ -1647,6 +1649,7 @@ for info on changes for earlier releases.
 [@BarryThePenguin]: https://github.com/BarryThePenguin
 [@be5invis]: https://github.com/be5invis
 [@beatrizrezener]: https://github.com/beatrizrezener
+[@benkrejci]: https://github.com/benkrejci
 [@benmosher]: https://github.com/benmosher
 [@benmunro]: https://github.com/benmunro
 [@BenoitZugmeyer]: https://github.com/BenoitZugmeyer
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index 5f3cfbd426..dd741c21a5 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -84,12 +84,17 @@ Config:
 ```js
 import { AValue, type AType } from './mama-mia'
 import type { BType } from './mama-mia'
+
+import { CValue } from './papa-mia'
+import type { CType } from './papa-mia'
 ```
 
 ✅ Valid with `["error", {"prefer-inline": true}]`
 
 ```js
 import { AValue, type AType, type BType } from './mama-mia'
+
+import { CValue, type CType } from './papa-mia'
 ```
 
 <!--tabs-->
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 76bf187b2e..2373202cb6 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -318,10 +318,11 @@ module.exports = {
         });
       }
       const map = moduleMaps.get(n.parent);
-      if (n.importKind === 'type') {
+      const preferInline = context.options[0] && context.options[0]['prefer-inline'];
+      if (!preferInline && n.importKind === 'type') {
         return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? map.defaultTypesImported : map.namedTypesImported;
       }
-      if (n.specifiers.some((spec) => spec.importKind === 'type')) {
+      if (!preferInline && n.specifiers.some((spec) => spec.importKind === 'type')) {
         return map.namedTypesImported;
       }
 
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index 33e1e632e2..d61fda86e1 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -711,6 +711,25 @@ context('TypeScript', function () {
             },
           ],
         }),
+        // #2834 Detect duplicates across type and regular imports
+        test({
+          code: "import {AValue} from './foo'; import type {AType} from './foo'",
+          ...parserConfig,
+          options: [{ 'prefer-inline': true }],
+          output: `import {AValue,type AType} from './foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 22,
+              message: "'./foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 56,
+              message: "'./foo' imported multiple times.",
+            },
+          ],
+        }),
       ]);
 
       ruleTester.run('no-duplicates', rule, {

From d8002bee587dad9c574fb06a23b4bcb25e90bc39 Mon Sep 17 00:00:00 2001
From: Ben Asher <ben@ashbyhq.com>
Date: Sun, 7 May 2023 18:57:33 -0700
Subject: [PATCH 599/767] [Fix] `extensions`: handle `.` and `..` properly

---
 CHANGELOG.md                         |  5 ++-
 src/rules/extensions.js              |  1 +
 tests/files/internal-modules/test.js |  0
 tests/index.js                       |  1 +
 tests/src/rules/extensions.js        | 49 ++++++++++++++++++++++++++++
 5 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 tests/files/internal-modules/test.js
 create mode 100644 tests/index.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a46b1b0326..7febb37111 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,8 +12,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Perf] `ExportMap`: Improve `ExportMap.for` performance on larger codebases ([#2756], thanks [@leipert])
 - [`no-extraneous-dependencies`]/TypeScript: do not error when importing inline type from dev dependencies ([#1820], thanks [@andyogo])
 - [`newline-after-import`]/TypeScript: do not error when re-exporting a namespaced import ([#2832], thanks [@laurens-dg])
-* [`order`]: partial fix for [#2687] (thanks [@ljharb])
+- [`order`]: partial fix for [#2687] (thanks [@ljharb])
 - [`no-duplicates`]: Detect across type and regular imports ([#2835], thanks [@benkrejci])
+- [`extensions`]: handle `.` and `..` properly ([#2778], thanks [@benasher44])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
@@ -1076,6 +1077,7 @@ for info on changes for earlier releases.
 
 [#2835]: https://github.com/import-js/eslint-plugin-import/pull/2835
 [#2832]: https://github.com/import-js/eslint-plugin-import/pull/2832
+[#2778]: https://github.com/import-js/eslint-plugin-import/pull/2778
 [#2756]: https://github.com/import-js/eslint-plugin-import/pull/2756
 [#2754]: https://github.com/import-js/eslint-plugin-import/pull/2754
 [#2748]: https://github.com/import-js/eslint-plugin-import/pull/2748
@@ -1649,6 +1651,7 @@ for info on changes for earlier releases.
 [@BarryThePenguin]: https://github.com/BarryThePenguin
 [@be5invis]: https://github.com/be5invis
 [@beatrizrezener]: https://github.com/beatrizrezener
+[@benasher44]: https://github.com/benasher44
 [@benkrejci]: https://github.com/benkrejci
 [@benmosher]: https://github.com/benmosher
 [@benmunro]: https://github.com/benmunro
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 50debc6c8c..3acefcd31b 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -130,6 +130,7 @@ module.exports = {
     }
 
     function isExternalRootModule(file) {
+      if (file === '.' || file === '..') { return false; }
       const slashCount = file.split('/').length - 1;
 
       if (slashCount === 0)  { return true; }
diff --git a/tests/files/internal-modules/test.js b/tests/files/internal-modules/test.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/index.js b/tests/index.js
new file mode 100644
index 0000000000..abc02b839c
--- /dev/null
+++ b/tests/index.js
@@ -0,0 +1 @@
+export * from './files';
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index ede1a8d88a..22a5fc3023 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -266,6 +266,26 @@ ruleTester.run('extensions', rule, {
       ],
     }),
 
+    test({
+      code: [
+        'import barjs from "."',
+        'import barjs2 from ".."',
+      ].join('\n'),
+      options: [ 'always' ],
+      errors: [
+        {
+          message: 'Missing file extension "js" for "."',
+          line: 1,
+          column: 19,
+        },
+        {
+          message: 'Missing file extension "js" for ".."',
+          line: 2,
+          column: 20,
+        },
+      ],
+    }),
+
     test({
       code: [
         'import barjs from "./bar.js"',
@@ -594,6 +614,35 @@ ruleTester.run('extensions', rule, {
         },
       ],
     }),
+
+    // TODO: properly ignore packages resolved via relative imports
+    test({
+      code: [
+        'import * as test from "."',
+      ].join('\n'),
+      filename: testFilePath('./internal-modules/test.js'),
+      options: [ 'ignorePackages' ],
+      errors: [
+        {
+          message: 'Missing file extension for "."',
+          line: 1,
+        },
+      ],
+    }),
+    // TODO: properly ignore packages resolved via relative imports
+    test({
+      code: [
+        'import * as test from ".."',
+      ].join('\n'),
+      filename: testFilePath('./internal-modules/plugins/plugin.js'),
+      options: [ 'ignorePackages' ],
+      errors: [
+        {
+          message: 'Missing file extension for ".."',
+          line: 1,
+        },
+      ],
+    }),
   ],
 });
 

From 68bf51019b0e9ee86c572393781a75b9dba2ea8b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 25 Jul 2023 22:52:17 -0700
Subject: [PATCH 600/767] [eslint] enable `array-bracket-spacing`

---
 .eslintrc                                     |   1 +
 src/rules/extensions.js                       |   2 +-
 src/rules/no-absolute-path.js                 |   2 +-
 tests/src/core/hash.js                        |   8 +-
 tests/src/core/ignore.js                      |   4 +-
 tests/src/core/parse.js                       |   4 +-
 tests/src/core/resolve.js                     |  10 +-
 tests/src/rules/extensions.js                 | 120 +++++------
 tests/src/rules/named.js                      |   4 +-
 tests/src/rules/namespace.js                  |  18 +-
 tests/src/rules/newline-after-import.js       |  60 +++---
 tests/src/rules/no-amd.js                     |   8 +-
 tests/src/rules/no-commonjs.js                |  28 +--
 tests/src/rules/no-extraneous-dependencies.js |   4 +-
 tests/src/rules/no-internal-modules.js        | 204 +++++++++---------
 tests/src/rules/no-named-as-default.js        |  16 +-
 tests/src/rules/no-namespace.js               |  18 +-
 tests/src/rules/no-relative-packages.js       |  16 +-
 tests/src/rules/no-relative-parent-imports.js |  18 +-
 tests/src/rules/no-unresolved.js              |   6 +-
 tests/src/rules/no-useless-path-segments.js   |  38 ++--
 tests/src/rules/order.js                      |   2 +-
 utils/ignore.js                               |   2 +-
 23 files changed, 297 insertions(+), 296 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 709a474484..932055e8d4 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -19,6 +19,7 @@
         "ecmaVersion": 2020,
     },
     "rules": {
+        "array-bracket-spacing": [2, "never"],
         "arrow-body-style": [2, "as-needed"],
         "arrow-parens": [2, "always"],
         "arrow-spacing": [2, { "before": true, "after": true }],
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index 3acefcd31b..b1e5c6d9f1 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -5,7 +5,7 @@ import { isBuiltIn, isExternalModule, isScoped } from '../core/importType';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
-const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] };
+const enumValues = { enum: ['always', 'ignorePackages', 'never'] };
 const patternProperties = {
   type: 'object',
   patternProperties: { '.*': enumValues },
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index a5498ec765..04f67383f2 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -12,7 +12,7 @@ module.exports = {
       url: docsUrl('no-absolute-path'),
     },
     fixable: 'code',
-    schema: [ makeOptionsSchema() ],
+    schema: [makeOptionsSchema()],
   },
 
   create(context) {
diff --git a/tests/src/core/hash.js b/tests/src/core/hash.js
index 1d6a9eb85c..785b8abc34 100644
--- a/tests/src/core/hash.js
+++ b/tests/src/core/hash.js
@@ -29,7 +29,7 @@ describe('hash', function () {
     });
 
     it('handles Array instances', function () {
-      expectHash(hashify([ 'a string' ]), '["a string",]');
+      expectHash(hashify(['a string']), '["a string",]');
     });
 
     it('handles empty Array instances', function () {
@@ -45,13 +45,13 @@ describe('hash', function () {
     });
 
     it('handles nested Object and Array instances', function () {
-      expectHash(hashify({ foo: 123.456, 'a key': 'a value', obj: { arr: [ { def: 'ghi' } ] } }), '{"a key":"a value","foo":123.456,"obj":{"arr":[{"def":"ghi",},],},}');
+      expectHash(hashify({ foo: 123.456, 'a key': 'a value', obj: { arr: [{ def: 'ghi' }] } }), '{"a key":"a value","foo":123.456,"obj":{"arr":[{"def":"ghi",},],},}');
     });
   });
 
   describe('hashArray', function () {
     it('handles Array instances', function () {
-      expectHash(hashArray([ 'a string' ]), '["a string",]');
+      expectHash(hashArray(['a string']), '["a string",]');
     });
 
     it('handles empty Array instances', function () {
@@ -69,7 +69,7 @@ describe('hash', function () {
     });
 
     it('handles nested Object and Array instances', function () {
-      expectHash(hashObject({ foo: 123.456, 'a key': 'a value', obj: { arr: [ { def: 'ghi' } ] } }), '{"a key":"a value","foo":123.456,"obj":{"arr":[{"def":"ghi",},],},}');
+      expectHash(hashObject({ foo: 123.456, 'a key': 'a value', obj: { arr: [{ def: 'ghi' }] } }), '{"a key":"a value","foo":123.456,"obj":{"arr":[{"def":"ghi",},],},}');
     });
   });
 
diff --git a/tests/src/core/ignore.js b/tests/src/core/ignore.js
index 2b2126c8b5..3212781363 100644
--- a/tests/src/core/ignore.js
+++ b/tests/src/core/ignore.js
@@ -19,7 +19,7 @@ describe('ignore', function () {
     });
 
     it('ignores paths with invalid extensions when configured with import/extensions', function () {
-      const testContext = utils.testContext({ 'import/extensions': [ '.js', '.jsx', '.ts' ] });
+      const testContext = utils.testContext({ 'import/extensions': ['.js', '.jsx', '.ts'] });
 
       expect(isIgnored('../files/foo.js', testContext)).to.equal(false);
 
@@ -45,7 +45,7 @@ describe('ignore', function () {
     });
 
     it('can be configured with import/extensions', function () {
-      const testContext = utils.testContext({ 'import/extensions': [ '.foo', '.bar' ] });
+      const testContext = utils.testContext({ 'import/extensions': ['.foo', '.bar'] });
 
       expect(hasValidExtension('../files/foo.foo', testContext)).to.equal(true);
 
diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index 9c59453602..275b93982b 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -76,7 +76,7 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
     const parseSpy = sinon.spy();
     const parserOptions = { ecmaFeatures: { jsx: true } };
     parseStubParser.parse = parseSpy;
-    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, parserOptions })).not.to.throw(Error);
+    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: ['.js'] } }, parserPath: null, parserOptions })).not.to.throw(Error);
     expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
   });
 
@@ -123,7 +123,7 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
   it('prefers parsers specified in the settings over languageOptions.parser', () => {
     const parseSpy = sinon.spy();
     parseStubParser.parse = parseSpy;
-    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: [ '.js' ] } }, parserPath: null, languageOptions: { parser: { parse() {} } } })).not.to.throw(Error);
+    expect(parse.bind(null, path, content, { settings: { 'import/parsers': { [parseStubParserPath]: ['.js'] } }, parserPath: null, languageOptions: { parser: { parse() {} } } })).not.to.throw(Error);
     expect(parseSpy.callCount, 'custom parser to be called once').to.equal(1);
   });
 
diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js
index 6b69fb7f12..0db9b05f49 100644
--- a/tests/src/core/resolve.js
+++ b/tests/src/core/resolve.js
@@ -86,7 +86,7 @@ describe('resolve', function () {
   });
 
   it('respects import/resolver as array of strings', function () {
-    const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
+    const testContext = utils.testContext({ 'import/resolver': ['./foo-bar-resolver-v2', './foo-bar-resolver-v1'] });
 
     expect(resolve(
       '../files/foo',
@@ -104,7 +104,7 @@ describe('resolve', function () {
   });
 
   it('respects import/resolver as array of objects', function () {
-    const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
+    const testContext = utils.testContext({ 'import/resolver': [{ './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} }] });
 
     expect(resolve(
       '../files/foo',
@@ -254,7 +254,7 @@ describe('resolve', function () {
     });
 
     it('respects import/resolver as array of strings', function () {
-      const testContext = utils.testContext({ 'import/resolver': [ './foo-bar-resolver-v2', './foo-bar-resolver-v1' ] });
+      const testContext = utils.testContext({ 'import/resolver': ['./foo-bar-resolver-v2', './foo-bar-resolver-v1'] });
 
       expect(resolve(
         '../files/foo',
@@ -272,7 +272,7 @@ describe('resolve', function () {
     });
 
     it('respects import/resolver as array of objects', function () {
-      const testContext = utils.testContext({ 'import/resolver': [ { './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} } ] });
+      const testContext = utils.testContext({ 'import/resolver': [{ './foo-bar-resolver-v2': {} }, { './foo-bar-resolver-v1': {} }] });
 
       expect(resolve(
         '../files/foo',
@@ -386,7 +386,7 @@ describe('resolve', function () {
       'import/cache': { lifetime: 1 },
     });
 
-    const infiniteContexts = [ '∞', 'Infinity' ].map((inf) => [inf,
+    const infiniteContexts = ['∞', 'Infinity'].map((inf) => [inf,
       utils.testContext({
         'import/cache': { lifetime: inf },
       })]);
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 22a5fc3023..14d84eaa62 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -11,18 +11,18 @@ ruleTester.run('extensions', rule, {
     test({ code: 'import dot from "./file.with.dot"' }),
     test({
       code: 'import a from "a/index.js"',
-      options: [ 'always' ],
+      options: ['always'],
     }),
     test({
       code: 'import dot from "./file.with.dot.js"',
-      options: [ 'always' ],
+      options: ['always'],
     }),
     test({
       code: [
         'import a from "a"',
         'import packageConfig from "./package.json"',
       ].join('\n'),
-      options: [ { json: 'always', js: 'never' } ],
+      options: [{ json: 'always', js: 'never' }],
     }),
     test({
       code: [
@@ -30,8 +30,8 @@ ruleTester.run('extensions', rule, {
         'import component from "./bar.jsx"',
         'import data from "./bar.json"',
       ].join('\n'),
-      options: [ 'never' ],
-      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
+      options: ['never'],
+      settings: { 'import/resolve': { extensions: ['.js', '.jsx', '.json'] } },
     }),
 
     test({
@@ -40,8 +40,8 @@ ruleTester.run('extensions', rule, {
         'import barjson from "./bar.json"',
         'import barhbs from "./bar.hbs"',
       ].join('\n'),
-      options: [ 'always', { js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json', '.hbs' ] } },
+      options: ['always', { js: 'never', jsx: 'never' }],
+      settings: { 'import/resolve': { extensions: ['.js', '.jsx', '.json', '.hbs'] } },
     }),
 
     test({
@@ -49,16 +49,16 @@ ruleTester.run('extensions', rule, {
         'import bar from "./bar.js"',
         'import pack from "./package"',
       ].join('\n'),
-      options: [ 'never', { js: 'always', json: 'never' } ],
-      settings: { 'import/resolve': { extensions: [ '.js', '.json' ] } },
+      options: ['never', { js: 'always', json: 'never' }],
+      settings: { 'import/resolve': { extensions: ['.js', '.json'] } },
     }),
 
     // unresolved (#271/#295)
     test({ code: 'import path from "path"' }),
-    test({ code: 'import path from "path"', options: [ 'never' ] }),
-    test({ code: 'import path from "path"', options: [ 'always' ] }),
-    test({ code: 'import thing from "./fake-file.js"', options: [ 'always' ] }),
-    test({ code: 'import thing from "non-package"', options: [ 'never' ] }),
+    test({ code: 'import path from "path"', options: ['never'] }),
+    test({ code: 'import path from "path"', options: ['always'] }),
+    test({ code: 'import thing from "./fake-file.js"', options: ['always'] }),
+    test({ code: 'import thing from "non-package"', options: ['never'] }),
 
     test({
       code: `
@@ -67,7 +67,7 @@ ruleTester.run('extensions', rule, {
         import Component from './Component.jsx'
         import express from 'express'
       `,
-      options: [ 'ignorePackages' ],
+      options: ['ignorePackages'],
     }),
 
     test({
@@ -77,7 +77,7 @@ ruleTester.run('extensions', rule, {
         import Component from './Component.jsx'
         import express from 'express'
       `,
-      options: [ 'always', { ignorePackages: true } ],
+      options: ['always', { ignorePackages: true }],
     }),
 
     test({
@@ -87,16 +87,16 @@ ruleTester.run('extensions', rule, {
         import Component from './Component'
         import express from 'express'
       `,
-      options: [ 'never', { ignorePackages: true } ],
+      options: ['never', { ignorePackages: true }],
     }),
 
     test({
       code: 'import exceljs from "exceljs"',
-      options: [ 'always', { js: 'never', jsx: 'never' } ],
+      options: ['always', { js: 'never', jsx: 'never' }],
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
       settings: {
         'import/resolver': {
-          node: { extensions: [ '.js', '.jsx', '.json' ] },
+          node: { extensions: ['.js', '.jsx', '.json'] },
           webpack: { config: 'webpack.empty.config.js' },
         },
       },
@@ -108,14 +108,14 @@ ruleTester.run('extensions', rule, {
         'export { foo } from "./foo.js"',
         'let bar; export { bar }',
       ].join('\n'),
-      options: [ 'always' ],
+      options: ['always'],
     }),
     test({
       code: [
         'export { foo } from "./foo"',
         'let bar; export { bar }',
       ].join('\n'),
-      options: [ 'never' ],
+      options: ['never'],
     }),
 
     // Root packages should be ignored and they are names not files
@@ -125,17 +125,17 @@ ruleTester.run('extensions', rule, {
         'import lib2 from "pgk/package"',
         'import lib3 from "@name/pkg.js"',
       ].join('\n'),
-      options: [ 'never' ],
+      options: ['never'],
     }),
 
     // Query strings.
     test({
       code: 'import bare from "./foo?a=True.ext"',
-      options: [ 'never' ],
+      options: ['never'],
     }),
     test({
       code: 'import bare from "./foo.js?a=True"',
-      options: [ 'always' ],
+      options: ['always'],
     }),
 
     test({
@@ -144,22 +144,22 @@ ruleTester.run('extensions', rule, {
         'import lib2 from "pgk/package.js"',
         'import lib3 from "@name/pkg"',
       ].join('\n'),
-      options: [ 'always' ],
+      options: ['always'],
     }),
   ],
 
   invalid: [
     test({
       code: 'import a from "a/index.js"',
-      errors: [ {
+      errors: [{
         message: 'Unexpected use of file extension "js" for "a/index.js"',
         line: 1,
         column: 15,
-      } ],
+      }],
     }),
     test({
       code: 'import dot from "./file.with.dot"',
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension "js" for "./file.with.dot"',
@@ -173,8 +173,8 @@ ruleTester.run('extensions', rule, {
         'import a from "a/index.js"',
         'import packageConfig from "./package"',
       ].join('\n'),
-      options: [ { json: 'always', js: 'never' } ],
-      settings: { 'import/resolve': { extensions: [ '.js', '.json' ] } },
+      options: [{ json: 'always', js: 'never' }],
+      settings: { 'import/resolve': { extensions: ['.js', '.json'] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "a/index.js"',
@@ -194,8 +194,8 @@ ruleTester.run('extensions', rule, {
         'import component from "./bar.jsx"',
         'import data from "./bar.json"',
       ].join('\n'),
-      options: [ 'never' ],
-      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
+      options: ['never'],
+      settings: { 'import/resolve': { extensions: ['.js', '.jsx', '.json'] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./bar.js"',
@@ -210,8 +210,8 @@ ruleTester.run('extensions', rule, {
         'import component from "./bar.jsx"',
         'import data from "./bar.json"',
       ].join('\n'),
-      options: [ { json: 'always', js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
+      options: [{ json: 'always', js: 'never', jsx: 'never' }],
+      settings: { 'import/resolve': { extensions: ['.js', '.jsx', '.json'] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./bar.js"',
@@ -226,8 +226,8 @@ ruleTester.run('extensions', rule, {
         'import component from "./bar.jsx"',
         'import data from "./bar.json"',
       ].join('\n'),
-      options: [ { json: 'always', js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { extensions: [ '.jsx', '.json', '.js' ] } },
+      options: [{ json: 'always', js: 'never', jsx: 'never' }],
+      settings: { 'import/resolve': { extensions: ['.jsx', '.json', '.js'] } },
       errors: [
         {
           message: 'Unexpected use of file extension "jsx" for "./bar.jsx"',
@@ -255,8 +255,8 @@ ruleTester.run('extensions', rule, {
         'import barjson from "./bar.json"',
         'import barnone from "./bar"',
       ].join('\n'),
-      options: [ 'always', { json: 'always', js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
+      options: ['always', { json: 'always', js: 'never', jsx: 'never' }],
+      settings: { 'import/resolve': { extensions: ['.js', '.jsx', '.json'] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./bar.js"',
@@ -271,7 +271,7 @@ ruleTester.run('extensions', rule, {
         'import barjs from "."',
         'import barjs2 from ".."',
       ].join('\n'),
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension "js" for "."',
@@ -292,8 +292,8 @@ ruleTester.run('extensions', rule, {
         'import barjson from "./bar.json"',
         'import barnone from "./bar"',
       ].join('\n'),
-      options: [ 'never', { json: 'always', js: 'never', jsx: 'never' } ],
-      settings: { 'import/resolve': { extensions: [ '.js', '.jsx', '.json' ] } },
+      options: ['never', { json: 'always', js: 'never', jsx: 'never' }],
+      settings: { 'import/resolve': { extensions: ['.js', '.jsx', '.json'] } },
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./bar.js"',
@@ -306,7 +306,7 @@ ruleTester.run('extensions', rule, {
     // unresolved (#271/#295)
     test({
       code: 'import thing from "./fake-file.js"',
-      options: [ 'never' ],
+      options: ['never'],
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./fake-file.js"',
@@ -317,7 +317,7 @@ ruleTester.run('extensions', rule, {
     }),
     test({
       code: 'import thing from "non-package/test"',
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension for "non-package/test"',
@@ -329,7 +329,7 @@ ruleTester.run('extensions', rule, {
 
     test({
       code: 'import thing from "@name/pkg/test"',
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension for "@name/pkg/test"',
@@ -341,7 +341,7 @@ ruleTester.run('extensions', rule, {
 
     test({
       code: 'import thing from "@name/pkg/test.js"',
-      options: [ 'never' ],
+      options: ['never'],
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "@name/pkg/test.js"',
@@ -361,7 +361,7 @@ ruleTester.run('extensions', rule, {
         import chart from '@/configs/chart'
         import express from 'express'
       `,
-      options: [ 'always', { ignorePackages: true } ],
+      options: ['always', { ignorePackages: true }],
       errors: [
         {
           message: 'Missing file extension for "./Component"',
@@ -386,7 +386,7 @@ ruleTester.run('extensions', rule, {
         import chart from '@/configs/chart'
         import express from 'express'
       `,
-      options: [ 'ignorePackages' ],
+      options: ['ignorePackages'],
       errors: [
         {
           message: 'Missing file extension for "./Component"',
@@ -419,7 +419,7 @@ ruleTester.run('extensions', rule, {
           column: 31,
         },
       ],
-      options: [ 'never', { ignorePackages: true } ],
+      options: ['never', { ignorePackages: true }],
     }),
 
     test({
@@ -435,7 +435,7 @@ ruleTester.run('extensions', rule, {
           column: 31,
         },
       ],
-      options: [ 'always', { pattern: { jsx: 'never' } } ],
+      options: ['always', { pattern: { jsx: 'never' } }],
     }),
 
     // export (#964)
@@ -444,7 +444,7 @@ ruleTester.run('extensions', rule, {
         'export { foo } from "./foo"',
         'let bar; export { bar }',
       ].join('\n'),
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension for "./foo"',
@@ -458,7 +458,7 @@ ruleTester.run('extensions', rule, {
         'export { foo } from "./foo.js"',
         'let bar; export { bar }',
       ].join('\n'),
-      options: [ 'never' ],
+      options: ['never'],
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./foo.js"',
@@ -471,7 +471,7 @@ ruleTester.run('extensions', rule, {
     // Query strings.
     test({
       code: 'import withExtension from "./foo.js?a=True"',
-      options: [ 'never' ],
+      options: ['never'],
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./foo.js?a=True"',
@@ -482,7 +482,7 @@ ruleTester.run('extensions', rule, {
     }),
     test({
       code: 'import withoutExtension from "./foo?a=True.ext"',
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension for "./foo?a=True.ext"',
@@ -497,7 +497,7 @@ ruleTester.run('extensions', rule, {
         'const { foo } = require("./foo")',
         'export { foo }',
       ].join('\n'),
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension for "./foo"',
@@ -511,7 +511,7 @@ ruleTester.run('extensions', rule, {
         'const { foo } = require("./foo.js")',
         'export { foo }',
       ].join('\n'),
-      options: [ 'never' ],
+      options: ['never'],
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./foo.js"',
@@ -524,7 +524,7 @@ ruleTester.run('extensions', rule, {
     // export { } from
     test({
       code: 'export { foo } from "./foo"',
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension for "./foo"',
@@ -552,7 +552,7 @@ ruleTester.run('extensions', rule, {
     }),
     test({
       code: 'export { foo } from "./foo.js"',
-      options: [ 'never' ],
+      options: ['never'],
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./foo.js"',
@@ -565,7 +565,7 @@ ruleTester.run('extensions', rule, {
     // export * from
     test({
       code: 'export * from "./foo"',
-      options: [ 'always' ],
+      options: ['always'],
       errors: [
         {
           message: 'Missing file extension for "./foo"',
@@ -576,7 +576,7 @@ ruleTester.run('extensions', rule, {
     }),
     test({
       code: 'export * from "./foo.js"',
-      options: [ 'never' ],
+      options: ['never'],
       errors: [
         {
           message: 'Unexpected use of file extension "js" for "./foo.js"',
@@ -621,7 +621,7 @@ ruleTester.run('extensions', rule, {
         'import * as test from "."',
       ].join('\n'),
       filename: testFilePath('./internal-modules/test.js'),
-      options: [ 'ignorePackages' ],
+      options: ['ignorePackages'],
       errors: [
         {
           message: 'Missing file extension for "."',
@@ -635,7 +635,7 @@ ruleTester.run('extensions', rule, {
         'import * as test from ".."',
       ].join('\n'),
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ 'ignorePackages' ],
+      options: ['ignorePackages'],
       errors: [
         {
           message: 'Missing file extension for ".."',
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 110cfff52a..227bffc80d 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -208,7 +208,7 @@ ruleTester.run('named', rule, {
 
   invalid: [].concat(
     test({ code: 'import { somethingElse } from "./test-module"',
-      errors: [ error('somethingElse', './test-module') ] }),
+      errors: [error('somethingElse', './test-module')] }),
 
     test({ code: 'import { baz } from "./bar"',
       errors: [error('baz', './bar')] }),
@@ -330,7 +330,7 @@ ruleTester.run('named', rule, {
     // es2022: Arbitrary module namespace identifier names
     testVersion('>= 8.7', () => ({
       code: 'import { "somethingElse" as somethingElse } from "./test-module"',
-      errors: [ error('somethingElse', './test-module', 'Literal') ],
+      errors: [error('somethingElse', './test-module', 'Literal')],
       parserOptions: { ecmaVersion: 2022 },
     })),
     testVersion('>= 8.7', () => ({
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index d368fd3fe9..1475ae9b7d 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -284,7 +284,7 @@ const invalid = [].concat(
 
   test({
     code: "import b from './deep/default'; console.log(b.e)",
-    errors: [ "'e' not found in imported namespace 'b'." ],
+    errors: ["'e' not found in imported namespace 'b'."],
   }),
 
   // respect hoisting
@@ -317,12 +317,12 @@ const invalid = [].concat(
   // es2022: Arbitrary module namespace identifier names
   testVersion('>= 8.7', () => ({
     code: `import { "b" as b } from "./deep/a"; console.log(b.e)`,
-    errors: [ "'e' not found in imported namespace 'b'." ],
+    errors: ["'e' not found in imported namespace 'b'."],
     parserOptions: { ecmaVersion: 2022 },
   })),
   testVersion('>= 8.7', () => ({
     code: `import { "b" as b } from "./deep/a"; console.log(b.c.e)`,
-    errors: [ "'e' not found in deeply imported namespace 'b.c'." ],
+    errors: ["'e' not found in deeply imported namespace 'b.c'."],
     parserOptions: { ecmaVersion: 2022 },
   })),
 );
@@ -345,32 +345,32 @@ const invalid = [].concat(
     test({
       parser,
       code: `import * as a from "./${folder}/a"; console.log(a.b.e)`,
-      errors: [ "'e' not found in deeply imported namespace 'a.b'." ],
+      errors: ["'e' not found in deeply imported namespace 'a.b'."],
     }),
     test({
       parser,
       code: `import { b } from "./${folder}/a"; console.log(b.e)`,
-      errors: [ "'e' not found in imported namespace 'b'." ],
+      errors: ["'e' not found in imported namespace 'b'."],
     }),
     test({
       parser,
       code: `import * as a from "./${folder}/a"; console.log(a.b.c.e)`,
-      errors: [ "'e' not found in deeply imported namespace 'a.b.c'." ],
+      errors: ["'e' not found in deeply imported namespace 'a.b.c'."],
     }),
     test({
       parser,
       code: `import { b } from "./${folder}/a"; console.log(b.c.e)`,
-      errors: [ "'e' not found in deeply imported namespace 'b.c'." ],
+      errors: ["'e' not found in deeply imported namespace 'b.c'."],
     }),
     test({
       parser,
       code: `import * as a from "./${folder}/a"; var {b:{ e }} = a`,
-      errors: [ "'e' not found in deeply imported namespace 'a.b'." ],
+      errors: ["'e' not found in deeply imported namespace 'a.b'."],
     }),
     test({
       parser,
       code: `import * as a from "./${folder}/a"; var {b:{c:{ e }}} = a`,
-      errors: [ "'e' not found in deeply imported namespace 'a.b.c'." ],
+      errors: ["'e' not found in deeply imported namespace 'a.b.c'."],
     }));
 });
 
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 9ec6eb757b..8f3338eee8 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -346,11 +346,11 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         // some comment
         var foo = 'bar';
       `,
-      errors: [ {
+      errors: [{
         line: 3,
         column: 1,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ considerComments: true }],
     },
@@ -373,11 +373,11 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         **/
         var bar = 42;
       `,
-      errors: [ {
+      errors: [{
         line: 3,
         column: 9,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ considerComments: true }],
     },
@@ -394,54 +394,54 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         // Some random single line comment
         var bar = 42;
       `,
-      errors: [ {
+      errors: [{
         line: 3,
         column: 9,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ considerComments: true, count: 1 }],
     },
     {
       code: `import foo from 'foo';\nexport default function() {};`,
       output: `import foo from 'foo';\n\nexport default function() {};`,
-      errors: [ {
+      errors: [{
         line: 1,
         column: 1,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
       code: `import foo from 'foo';\n\nexport default function() {};`,
       output: `import foo from 'foo';\n\n\nexport default function() {};`,
       options: [{ count: 2 }],
-      errors: [ {
+      errors: [{
         line: 1,
         column: 1,
         message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
       code: `var foo = require('foo-module');\nvar something = 123;`,
       output: `var foo = require('foo-module');\n\nvar something = 123;`,
-      errors: [ {
+      errors: [{
         line: 1,
         column: 1,
         message: REQUIRE_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
       code: `import foo from 'foo';\nexport default function() {};`,
       output: `import foo from 'foo';\n\nexport default function() {};`,
       options: [{ count: 1 }],
-      errors: [ {
+      errors: [{
         line: 1,
         column: 1,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
@@ -495,20 +495,20 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
     {
       code: `var path = require('path');\nvar foo = require('foo');\nvar bar = 42;`,
       output: `var path = require('path');\nvar foo = require('foo');\n\nvar bar = 42;`,
-      errors: [ {
+      errors: [{
         line: 2,
         column: 1,
         message: REQUIRE_ERROR_MESSAGE,
-      } ],
+      }],
     },
     {
       code: `var assign = Object.assign || require('object-assign');\nvar foo = require('foo');\nvar bar = 42;`,
       output: `var assign = Object.assign || require('object-assign');\nvar foo = require('foo');\n\nvar bar = 42;`,
-      errors: [ {
+      errors: [{
         line: 2,
         column: 1,
         message: REQUIRE_ERROR_MESSAGE,
-      } ],
+      }],
     },
     {
       code: `require('a');\nfoo(require('b'), require('c'), require('d'));\nrequire('d');\nvar foo = 'bar';`,
@@ -535,64 +535,64 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
     {
       code: `import path from 'path';\nimport foo from 'foo';\nvar bar = 42;`,
       output: `import path from 'path';\nimport foo from 'foo';\n\nvar bar = 42;`,
-      errors: [ {
+      errors: [{
         line: 2,
         column: 1,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
       code: `import path from 'path';import foo from 'foo';var bar = 42;`,
       output: `import path from 'path';import foo from 'foo';\n\nvar bar = 42;`,
-      errors: [ {
+      errors: [{
         line: 1,
         column: 25,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
     {
       code: `import foo from 'foo';\n@SomeDecorator(foo)\nclass Foo {}`,
       output: `import foo from 'foo';\n\n@SomeDecorator(foo)\nclass Foo {}`,
-      errors: [ {
+      errors: [{
         line: 1,
         column: 1,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       parser: parsers.BABEL_OLD,
     },
     {
       code: `var foo = require('foo');\n@SomeDecorator(foo)\nclass Foo {}`,
       output: `var foo = require('foo');\n\n@SomeDecorator(foo)\nclass Foo {}`,
-      errors: [ {
+      errors: [{
         line: 1,
         column: 1,
         message: REQUIRE_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       parser: parsers.BABEL_OLD,
     },
     {
       code: `// issue 10042\nimport foo from 'foo';\n@SomeDecorator(foo)\nexport default class Test {}`,
       output: `// issue 10042\nimport foo from 'foo';\n\n@SomeDecorator(foo)\nexport default class Test {}`,
-      errors: [ {
+      errors: [{
         line: 2,
         column: 1,
         message: IMPORT_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { sourceType: 'module' },
       parser: parsers.BABEL_OLD,
     },
     {
       code: `// issue 1004\nconst foo = require('foo');\n@SomeDecorator(foo)\nexport default class Test {}`,
       output: `// issue 1004\nconst foo = require('foo');\n\n@SomeDecorator(foo)\nexport default class Test {}`,
-      errors: [ {
+      errors: [{
         line: 2,
         column: 1,
         message: REQUIRE_ERROR_MESSAGE,
-      } ],
+      }],
       parserOptions: { sourceType: 'module' },
       parser: parsers.BABEL_OLD,
     },
diff --git a/tests/src/rules/no-amd.js b/tests/src/rules/no-amd.js
index 91e29234c8..5317aa8fde 100644
--- a/tests/src/rules/no-amd.js
+++ b/tests/src/rules/no-amd.js
@@ -28,10 +28,10 @@ ruleTester.run('no-amd', require('rules/no-amd'), {
   ],
 
   invalid: semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
-    { code: 'define([], function() {})', errors: [ { message: 'Expected imports instead of AMD define().' }] },
-    { code: 'define(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD define().' }] },
+    { code: 'define([], function() {})', errors: [{ message: 'Expected imports instead of AMD define().' }] },
+    { code: 'define(["a"], function(a) { console.log(a); })', errors: [{ message: 'Expected imports instead of AMD define().' }] },
 
-    { code: 'require([], function() {})', errors: [ { message: 'Expected imports instead of AMD require().' }] },
-    { code: 'require(["a"], function(a) { console.log(a); })', errors: [ { message: 'Expected imports instead of AMD require().' }] },
+    { code: 'require([], function() {})', errors: [{ message: 'Expected imports instead of AMD require().' }] },
+    { code: 'require(["a"], function(a) { console.log(a); })', errors: [{ message: 'Expected imports instead of AMD require().' }] },
   ],
 });
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index baa3b907f6..b7c0aa803f 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -69,47 +69,47 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
 
     // imports
     ...semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
-      { code: 'var x = require("x")', output: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
-      { code: 'x = require("x")', output: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] },
-      { code: 'require("x")', output: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] },
+      { code: 'var x = require("x")', output: 'var x = require("x")', errors: [{ message: IMPORT_MESSAGE }] },
+      { code: 'x = require("x")', output: 'x = require("x")', errors: [{ message: IMPORT_MESSAGE }] },
+      { code: 'require("x")', output: 'require("x")', errors: [{ message: IMPORT_MESSAGE }] },
       { code: 'require(`x`)',
         parserOptions: { ecmaVersion: 2015 },
         output: 'require(`x`)',
-        errors: [ { message: IMPORT_MESSAGE }],
+        errors: [{ message: IMPORT_MESSAGE }],
       },
 
       { code: 'if (typeof window !== "undefined") require("x")',
         options: [{ allowConditionalRequire: false }],
         output: 'if (typeof window !== "undefined") require("x")',
-        errors: [ { message: IMPORT_MESSAGE }],
+        errors: [{ message: IMPORT_MESSAGE }],
       },
       { code: 'if (typeof window !== "undefined") { require("x") }',
         options: [{ allowConditionalRequire: false }],
         output: 'if (typeof window !== "undefined") { require("x") }',
-        errors: [ { message: IMPORT_MESSAGE }],
+        errors: [{ message: IMPORT_MESSAGE }],
       },
       { code: 'try { require("x") } catch (error) {}',
         options: [{ allowConditionalRequire: false }],
         output: 'try { require("x") } catch (error) {}',
-        errors: [ { message: IMPORT_MESSAGE }],
+        errors: [{ message: IMPORT_MESSAGE }],
       },
     ],
 
     // exports
-    { code: 'exports.face = "palm"', output: 'exports.face = "palm"', errors: [ { message: EXPORT_MESSAGE }] },
-    { code: 'module.exports.face = "palm"', output: 'module.exports.face = "palm"', errors: [ { message: EXPORT_MESSAGE }] },
-    { code: 'module.exports = face', output: 'module.exports = face', errors: [ { message: EXPORT_MESSAGE }] },
-    { code: 'exports = module.exports = {}', output: 'exports = module.exports = {}', errors: [ { message: EXPORT_MESSAGE }] },
-    { code: 'var x = module.exports = {}', output: 'var x = module.exports = {}', errors: [ { message: EXPORT_MESSAGE }] },
+    { code: 'exports.face = "palm"', output: 'exports.face = "palm"', errors: [{ message: EXPORT_MESSAGE }] },
+    { code: 'module.exports.face = "palm"', output: 'module.exports.face = "palm"', errors: [{ message: EXPORT_MESSAGE }] },
+    { code: 'module.exports = face', output: 'module.exports = face', errors: [{ message: EXPORT_MESSAGE }] },
+    { code: 'exports = module.exports = {}', output: 'exports = module.exports = {}', errors: [{ message: EXPORT_MESSAGE }] },
+    { code: 'var x = module.exports = {}', output: 'var x = module.exports = {}', errors: [{ message: EXPORT_MESSAGE }] },
     { code: 'module.exports = {}',
       options: ['allow-primitive-modules'],
       output: 'module.exports = {}',
-      errors: [ { message: EXPORT_MESSAGE }],
+      errors: [{ message: EXPORT_MESSAGE }],
     },
     { code: 'var x = module.exports',
       options: ['allow-primitive-modules'],
       output: 'var x = module.exports',
-      errors: [ { message: EXPORT_MESSAGE }],
+      errors: [{ message: EXPORT_MESSAGE }],
     },
   ],
 });
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 6f4e710f9d..21561615c6 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -57,7 +57,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     // 'project' type
     test({
       code: 'import "importType"',
-      settings: { 'import/resolver': { node: { paths: [ path.join(__dirname, '../../files') ] } } },
+      settings: { 'import/resolver': { node: { paths: [path.join(__dirname, '../../files')] } } },
     }),
     test({
       code: 'import chai from "chai"',
@@ -396,7 +396,7 @@ ruleTester.run('no-extraneous-dependencies', rule, {
     test({
       code: 'import "not-a-dependency"',
       settings: {
-        'import/resolver': { node: { paths: [ path.join(__dirname, '../../files') ] } },
+        'import/resolver': { node: { paths: [path.join(__dirname, '../../files')] } },
         'import/internal-regex': '^not-a-dependency.*',
       },
       options: [{ includeInternal: true }],
diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js
index 4a733d142a..c1c3015453 100644
--- a/tests/src/rules/no-internal-modules.js
+++ b/tests/src/rules/no-internal-modules.js
@@ -41,51 +41,51 @@ ruleTester.run('no-internal-modules', rule, {
     test({
       code: 'import b from "../../api/service"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        allow: [ '**/api/*' ],
-      } ],
+      options: [{
+        allow: ['**/api/*'],
+      }],
     }),
     test({
       code: 'import "jquery/dist/jquery"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        allow: [ 'jquery/dist/*' ],
-      } ],
+      options: [{
+        allow: ['jquery/dist/*'],
+      }],
     }),
     test({
       code: 'import "./app/index.js";\nimport "./app/index"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        allow: [ '**/index{.js,}' ],
-      } ],
+      options: [{
+        allow: ['**/index{.js,}'],
+      }],
     }),
     test({
       code: 'import a from "./plugin2/thing"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ {
-        forbid: [ '**/api/*' ],
-      } ],
+      options: [{
+        forbid: ['**/api/*'],
+      }],
     }),
     test({
       code: 'const a = require("./plugin2/thing")',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ {
-        forbid: [ '**/api/*' ],
-      } ],
+      options: [{
+        forbid: ['**/api/*'],
+      }],
     }),
     test({
       code: 'import b from "app/a"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ 'app/**/**' ],
-      } ],
+      options: [{
+        forbid: ['app/**/**'],
+      }],
     }),
     test({
       code: 'import b from "@org/package"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ '@org/package/*' ],
-      } ],
+      options: [{
+        forbid: ['@org/package/*'],
+      }],
     }),
     // exports
     test({
@@ -103,23 +103,23 @@ ruleTester.run('no-internal-modules', rule, {
     test({
       code: 'export {b} from "../../api/service"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        allow: [ '**/api/*' ],
-      } ],
+      options: [{
+        allow: ['**/api/*'],
+      }],
     }),
     test({
       code: 'export * from "jquery/dist/jquery"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        allow: [ 'jquery/dist/*' ],
-      } ],
+      options: [{
+        allow: ['jquery/dist/*'],
+      }],
     }),
     test({
       code: 'export * from "./app/index.js";\nexport * from "./app/index"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        allow: [ '**/index{.js,}' ],
-      } ],
+      options: [{
+        allow: ['**/index{.js,}'],
+      }],
     }),
     test({
       code: `
@@ -145,30 +145,30 @@ ruleTester.run('no-internal-modules', rule, {
     test({
       code: 'export * from "./plugin2/thing"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ {
-        forbid: [ '**/api/*' ],
-      } ],
+      options: [{
+        forbid: ['**/api/*'],
+      }],
     }),
     test({
       code: 'export * from "app/a"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ 'app/**/**' ],
-      } ],
+      options: [{
+        forbid: ['app/**/**'],
+      }],
     }),
     test({
       code: 'export { b } from "@org/package"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ '@org/package/*' ],
-      } ],
+      options: [{
+        forbid: ['@org/package/*'],
+      }],
     }),
     test({
       code: 'export * from "./app/index.js";\nexport * from "./app/index"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ '**/index.ts' ],
-      } ],
+      options: [{
+        forbid: ['**/index.ts'],
+      }],
     }),
   ],
 
@@ -177,39 +177,39 @@ ruleTester.run('no-internal-modules', rule, {
     test({
       code: 'import "./plugin2/index.js";\nimport "./plugin2/app/index"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ {
-        allow: [ '*/index.js' ],
-      } ],
-      errors: [ {
+      options: [{
+        allow: ['*/index.js'],
+      }],
+      errors: [{
         message: 'Reaching to "./plugin2/app/index" is not allowed.',
         line: 2,
         column: 8,
-      } ],
+      }],
     }),
     test({
       code: 'import "./app/index.js"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      errors: [ {
+      errors: [{
         message: 'Reaching to "./app/index.js" is not allowed.',
         line: 1,
         column: 8,
-      } ],
+      }],
     }),
     test({
       code: 'import b from "./plugin2/internal"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      errors: [ {
+      errors: [{
         message: 'Reaching to "./plugin2/internal" is not allowed.',
         line: 1,
         column: 15,
-      } ],
+      }],
     }),
     test({
       code: 'import a from "../api/service/index"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ {
-        allow: [ '**/internal-modules/*' ],
-      } ],
+      options: [{
+        allow: ['**/internal-modules/*'],
+      }],
       errors: [
         {
           message: 'Reaching to "../api/service/index" is not allowed.',
@@ -243,58 +243,58 @@ ruleTester.run('no-internal-modules', rule, {
     test({
       code: 'import "./app/index.js"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ '*/app/*' ],
-      } ],
-      errors: [ {
+      options: [{
+        forbid: ['*/app/*'],
+      }],
+      errors: [{
         message: 'Reaching to "./app/index.js" is not allowed.',
         line: 1,
         column: 8,
-      } ],
+      }],
     }),
     test({
       code: 'import b from "@org/package"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ '@org/**' ],
-      } ],
-      errors: [ {
+      options: [{
+        forbid: ['@org/**'],
+      }],
+      errors: [{
         message: 'Reaching to "@org/package" is not allowed.',
         line: 1,
         column: 15,
-      } ],
+      }],
     }),
     test({
       code: 'import b from "app/a/b"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ 'app/**/**' ],
-      } ],
-      errors: [ {
+      options: [{
+        forbid: ['app/**/**'],
+      }],
+      errors: [{
         message: 'Reaching to "app/a/b" is not allowed.',
         line: 1,
         column: 15,
-      } ],
+      }],
     }),
     test({
       code: 'import get from "lodash.get"',
       filename: testFilePath('./internal-modules/plugins/plugin2/index.js'),
-      options: [ {
-        forbid: [ 'lodash.*' ],
-      } ],
-      errors: [ {
+      options: [{
+        forbid: ['lodash.*'],
+      }],
+      errors: [{
         message: 'Reaching to "lodash.get" is not allowed.',
         line: 1,
         column: 17,
-      } ],
+      }],
     }),
     test({
       code: 'import "./app/index.js";\nimport "./app/index"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ '**/index{.js,}' ],
-      } ],
-      errors: [ {
+      options: [{
+        forbid: ['**/index{.js,}'],
+      }],
+      errors: [{
         message: 'Reaching to "./app/index.js" is not allowed.',
         line: 1,
         column: 8,
@@ -302,18 +302,18 @@ ruleTester.run('no-internal-modules', rule, {
         message: 'Reaching to "./app/index" is not allowed.',
         line: 2,
         column: 8,
-      } ],
+      }],
     }),
     test({
       code: 'import "@/api/service";',
-      options: [ {
-        forbid: [ '**/api/*' ],
-      } ],
-      errors: [ {
+      options: [{
+        forbid: ['**/api/*'],
+      }],
+      errors: [{
         message: 'Reaching to "@/api/service" is not allowed.',
         line: 1,
         column: 8,
-      } ],
+      }],
       settings: {
         'import/resolver': {
           webpack: {
@@ -332,39 +332,39 @@ ruleTester.run('no-internal-modules', rule, {
     test({
       code: 'export * from "./plugin2/index.js";\nexport * from "./plugin2/app/index"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ {
-        allow: [ '*/index.js' ],
-      } ],
-      errors: [ {
+      options: [{
+        allow: ['*/index.js'],
+      }],
+      errors: [{
         message: 'Reaching to "./plugin2/app/index" is not allowed.',
         line: 2,
         column: 15,
-      } ],
+      }],
     }),
     test({
       code: 'export * from "./app/index.js"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      errors: [ {
+      errors: [{
         message: 'Reaching to "./app/index.js" is not allowed.',
         line: 1,
         column: 15,
-      } ],
+      }],
     }),
     test({
       code: 'export {b} from "./plugin2/internal"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      errors: [ {
+      errors: [{
         message: 'Reaching to "./plugin2/internal" is not allowed.',
         line: 1,
         column: 17,
-      } ],
+      }],
     }),
     test({
       code: 'export {a} from "../api/service/index"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ {
-        allow: [ '**/internal-modules/*' ],
-      } ],
+      options: [{
+        allow: ['**/internal-modules/*'],
+      }],
       errors: [
         {
           message: 'Reaching to "../api/service/index" is not allowed.',
@@ -398,9 +398,9 @@ ruleTester.run('no-internal-modules', rule, {
     test({
       code: 'export * from "./plugin2/thing"',
       filename: testFilePath('./internal-modules/plugins/plugin.js'),
-      options: [ {
-        forbid: [ '**/plugin2/*' ],
-      } ],
+      options: [{
+        forbid: ['**/plugin2/*'],
+      }],
       errors: [
         {
           message: 'Reaching to "./plugin2/thing" is not allowed.',
@@ -412,9 +412,9 @@ ruleTester.run('no-internal-modules', rule, {
     test({
       code: 'export * from "app/a"',
       filename: testFilePath('./internal-modules/plugins/plugin2/internal.js'),
-      options: [ {
-        forbid: [ '**' ],
-      } ],
+      options: [{
+        forbid: ['**'],
+      }],
       errors: [
         {
           message: 'Reaching to "app/a" is not allowed.',
diff --git a/tests/src/rules/no-named-as-default.js b/tests/src/rules/no-named-as-default.js
index 04ec28e615..c6646a4f0d 100644
--- a/tests/src/rules/no-named-as-default.js
+++ b/tests/src/rules/no-named-as-default.js
@@ -33,28 +33,28 @@ ruleTester.run('no-named-as-default', rule, {
   invalid: [].concat(
     test({
       code: 'import foo from "./bar";',
-      errors: [ {
+      errors: [{
         message: 'Using exported name \'foo\' as identifier for default export.',
-        type: 'ImportDefaultSpecifier' } ] }),
+        type: 'ImportDefaultSpecifier' }] }),
     test({
       code: 'import foo, { foo as bar } from "./bar";',
-      errors: [ {
+      errors: [{
         message: 'Using exported name \'foo\' as identifier for default export.',
-        type: 'ImportDefaultSpecifier' } ] }),
+        type: 'ImportDefaultSpecifier' }] }),
 
     // es7
     test({
       code: 'export foo from "./bar";',
       parser: parsers.BABEL_OLD,
-      errors: [ {
+      errors: [{
         message: 'Using exported name \'foo\' as identifier for default export.',
-        type: 'ExportDefaultSpecifier' } ] }),
+        type: 'ExportDefaultSpecifier' }] }),
     test({
       code: 'export foo, { foo as bar } from "./bar";',
       parser: parsers.BABEL_OLD,
-      errors: [ {
+      errors: [{
         message: 'Using exported name \'foo\' as identifier for default export.',
-        type: 'ExportDefaultSpecifier' } ] }),
+        type: 'ExportDefaultSpecifier' }] }),
 
     test({
       code: 'import foo from "./malformed.js"',
diff --git a/tests/src/rules/no-namespace.js b/tests/src/rules/no-namespace.js
index d75928c1d8..03a23e3dd7 100644
--- a/tests/src/rules/no-namespace.js
+++ b/tests/src/rules/no-namespace.js
@@ -20,7 +20,7 @@ const FIX_TESTS = semver.satisfies(eslintPkg.version, '>5.0.0') ? [
       florp(bar);
       florp(baz);
     `.trim(),
-    errors: [ {
+    errors: [{
       line: 1,
       column: 8,
       message: ERROR_MESSAGE,
@@ -43,7 +43,7 @@ const FIX_TESTS = semver.satisfies(eslintPkg.version, '>5.0.0') ? [
       florp(foo_bar);
       florp(foo_baz_1);
     `.trim(),
-    errors: [ {
+    errors: [{
       line: 1,
       column: 8,
       message: ERROR_MESSAGE,
@@ -64,7 +64,7 @@ const FIX_TESTS = semver.satisfies(eslintPkg.version, '>5.0.0') ? [
         florp(foo_arg);
       }
     `.trim(),
-    errors: [ {
+    errors: [{
       line: 1,
       column: 8,
       message: ERROR_MESSAGE,
@@ -85,29 +85,29 @@ ruleTester.run('no-namespace', require('rules/no-namespace'), {
     test({
       code: 'import * as foo from \'foo\';',
       output: 'import * as foo from \'foo\';',
-      errors: [ {
+      errors: [{
         line: 1,
         column: 8,
         message: ERROR_MESSAGE,
-      } ],
+      }],
     }),
     test({
       code: 'import defaultExport, * as foo from \'foo\';',
       output: 'import defaultExport, * as foo from \'foo\';',
-      errors: [ {
+      errors: [{
         line: 1,
         column: 23,
         message: ERROR_MESSAGE,
-      } ],
+      }],
     }),
     test({
       code: 'import * as foo from \'./foo\';',
       output: 'import * as foo from \'./foo\';',
-      errors: [ {
+      errors: [{
         line: 1,
         column: 8,
         message: ERROR_MESSAGE,
-      } ],
+      }],
     }),
     ...FIX_TESTS,
   ],
diff --git a/tests/src/rules/no-relative-packages.js b/tests/src/rules/no-relative-packages.js
index 2d27bcc91e..6104aeb9ca 100644
--- a/tests/src/rules/no-relative-packages.js
+++ b/tests/src/rules/no-relative-packages.js
@@ -42,41 +42,41 @@ ruleTester.run('no-relative-packages', rule, {
     test({
       code: 'import foo from "./package-named"',
       filename: testFilePath('./bar.js'),
-      errors: [ {
+      errors: [{
         message: 'Relative import from another package is not allowed. Use `package-named` instead of `./package-named`',
         line: 1,
         column: 17,
-      } ],
+      }],
       output: 'import foo from "package-named"',
     }),
     test({
       code: 'import foo from "../package-named"',
       filename: testFilePath('./package/index.js'),
-      errors: [ {
+      errors: [{
         message: 'Relative import from another package is not allowed. Use `package-named` instead of `../package-named`',
         line: 1,
         column: 17,
-      } ],
+      }],
       output: 'import foo from "package-named"',
     }),
     test({
       code: 'import foo from "../package-scoped"',
       filename: testFilePath('./package/index.js'),
-      errors: [ {
+      errors: [{
         message: `Relative import from another package is not allowed. Use \`${normalize('@scope/package-named')}\` instead of \`../package-scoped\``,
         line: 1,
         column: 17,
-      } ],
+      }],
       output: `import foo from "@scope/package-named"`,
     }),
     test({
       code: 'import bar from "../bar"',
       filename: testFilePath('./package-named/index.js'),
-      errors: [ {
+      errors: [{
         message: `Relative import from another package is not allowed. Use \`${normalize('eslint-plugin-import/tests/files/bar')}\` instead of \`../bar\``,
         line: 1,
         column: 17,
-      } ],
+      }],
       output: `import bar from "eslint-plugin-import/tests/files/bar"`,
     }),
   ],
diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js
index bfd4e16bcd..1af9b8cf8d 100644
--- a/tests/src/rules/no-relative-parent-imports.js
+++ b/tests/src/rules/no-relative-parent-imports.js
@@ -55,32 +55,32 @@ ruleTester.run('no-relative-parent-imports', rule, {
   invalid: [
     test({
       code: 'import foo from "../plugin.js"',
-      errors: [ {
+      errors: [{
         message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `../plugin.js` or consider making `../plugin.js` a package.',
         line: 1,
         column: 17,
-      } ],
+      }],
     }),
     test({
       code: 'require("../plugin.js")',
       options: [{ commonjs: true }],
-      errors: [ {
+      errors: [{
         message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `../plugin.js` or consider making `../plugin.js` a package.',
         line: 1,
         column: 9,
-      } ],
+      }],
     }),
     test({
       code: 'import("../plugin.js")',
-      errors: [ {
+      errors: [{
         message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `../plugin.js` or consider making `../plugin.js` a package.',
         line: 1,
         column: 8,
-      } ],
+      }],
     }),
     test({
       code: 'import foo from "./../plugin.js"',
-      errors: [ {
+      errors: [{
         message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `./../plugin.js` or consider making `./../plugin.js` a package.',
         line: 1,
         column: 17,
@@ -88,7 +88,7 @@ ruleTester.run('no-relative-parent-imports', rule, {
     }),
     test({
       code: 'import foo from "../../api/service"',
-      errors: [ {
+      errors: [{
         message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `../../api/service` or consider making `../../api/service` a package.',
         line: 1,
         column: 17,
@@ -96,7 +96,7 @@ ruleTester.run('no-relative-parent-imports', rule, {
     }),
     test({
       code: 'import("../../api/service")',
-      errors: [ {
+      errors: [{
         message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `../../api/service` or consider making `../../api/service` a package.',
         line: 1,
         column: 8,
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 109099c389..04a53d887b 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -387,7 +387,7 @@ ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
   invalid: [
     test({
       code: 'import * as foo from "jsx-module/foo"',
-      errors: [ "Unable to resolve path to module 'jsx-module/foo'." ],
+      errors: ["Unable to resolve path to module 'jsx-module/foo'."],
     }),
   ],
 });
@@ -536,12 +536,12 @@ context('TypeScript', () => {
       invalid: [
         test({
           code: 'import { JSONSchema7Type } from "@types/json-schema";',
-          errors: [ "Unable to resolve path to module '@types/json-schema'." ],
+          errors: ["Unable to resolve path to module '@types/json-schema'."],
           parser,
         }),
         test({
           code: 'export { JSONSchema7Type } from "@types/json-schema";',
-          errors: [ "Unable to resolve path to module '@types/json-schema'." ],
+          errors: ["Unable to resolve path to module '@types/json-schema'."],
           parser,
         }),
       ],
diff --git a/tests/src/rules/no-useless-path-segments.js b/tests/src/rules/no-useless-path-segments.js
index f960953503..d6d0395dea 100644
--- a/tests/src/rules/no-useless-path-segments.js
+++ b/tests/src/rules/no-useless-path-segments.js
@@ -42,49 +42,49 @@ function runResolverTests(resolver) {
         code: 'require("./../files/malformed.js")',
         output: 'require("../files/malformed.js")',
         options: [{ commonjs: true }],
-        errors: [ 'Useless path segments for "./../files/malformed.js", should be "../files/malformed.js"'],
+        errors: ['Useless path segments for "./../files/malformed.js", should be "../files/malformed.js"'],
       }),
       test({
         code: 'require("./../files/malformed")',
         output: 'require("../files/malformed")',
         options: [{ commonjs: true }],
-        errors: [ 'Useless path segments for "./../files/malformed", should be "../files/malformed"'],
+        errors: ['Useless path segments for "./../files/malformed", should be "../files/malformed"'],
       }),
       test({
         code: 'require("../files/malformed.js")',
         output: 'require("./malformed.js")',
         options: [{ commonjs: true }],
-        errors: [ 'Useless path segments for "../files/malformed.js", should be "./malformed.js"'],
+        errors: ['Useless path segments for "../files/malformed.js", should be "./malformed.js"'],
       }),
       test({
         code: 'require("../files/malformed")',
         output: 'require("./malformed")',
         options: [{ commonjs: true }],
-        errors: [ 'Useless path segments for "../files/malformed", should be "./malformed"'],
+        errors: ['Useless path segments for "../files/malformed", should be "./malformed"'],
       }),
       test({
         code: 'require("./test-module/")',
         output: 'require("./test-module")',
         options: [{ commonjs: true }],
-        errors: [ 'Useless path segments for "./test-module/", should be "./test-module"'],
+        errors: ['Useless path segments for "./test-module/", should be "./test-module"'],
       }),
       test({
         code: 'require("./")',
         output: 'require(".")',
         options: [{ commonjs: true }],
-        errors: [ 'Useless path segments for "./", should be "."'],
+        errors: ['Useless path segments for "./", should be "."'],
       }),
       test({
         code: 'require("../")',
         output: 'require("..")',
         options: [{ commonjs: true }],
-        errors: [ 'Useless path segments for "../", should be ".."'],
+        errors: ['Useless path segments for "../", should be ".."'],
       }),
       test({
         code: 'require("./deep//a")',
         output: 'require("./deep/a")',
         options: [{ commonjs: true }],
-        errors: [ 'Useless path segments for "./deep//a", should be "./deep/a"'],
+        errors: ['Useless path segments for "./deep//a", should be "./deep/a"'],
       }),
 
       // CommonJS modules + noUselessIndex
@@ -141,42 +141,42 @@ function runResolverTests(resolver) {
       test({
         code: 'import "./../files/malformed.js"',
         output: 'import "../files/malformed.js"',
-        errors: [ 'Useless path segments for "./../files/malformed.js", should be "../files/malformed.js"'],
+        errors: ['Useless path segments for "./../files/malformed.js", should be "../files/malformed.js"'],
       }),
       test({
         code: 'import "./../files/malformed"',
         output: 'import "../files/malformed"',
-        errors: [ 'Useless path segments for "./../files/malformed", should be "../files/malformed"'],
+        errors: ['Useless path segments for "./../files/malformed", should be "../files/malformed"'],
       }),
       test({
         code: 'import "../files/malformed.js"',
         output: 'import "./malformed.js"',
-        errors: [ 'Useless path segments for "../files/malformed.js", should be "./malformed.js"'],
+        errors: ['Useless path segments for "../files/malformed.js", should be "./malformed.js"'],
       }),
       test({
         code: 'import "../files/malformed"',
         output: 'import "./malformed"',
-        errors: [ 'Useless path segments for "../files/malformed", should be "./malformed"'],
+        errors: ['Useless path segments for "../files/malformed", should be "./malformed"'],
       }),
       test({
         code: 'import "./test-module/"',
         output: 'import "./test-module"',
-        errors: [ 'Useless path segments for "./test-module/", should be "./test-module"'],
+        errors: ['Useless path segments for "./test-module/", should be "./test-module"'],
       }),
       test({
         code: 'import "./"',
         output: 'import "."',
-        errors: [ 'Useless path segments for "./", should be "."'],
+        errors: ['Useless path segments for "./", should be "."'],
       }),
       test({
         code: 'import "../"',
         output: 'import ".."',
-        errors: [ 'Useless path segments for "../", should be ".."'],
+        errors: ['Useless path segments for "../", should be ".."'],
       }),
       test({
         code: 'import "./deep//a"',
         output: 'import "./deep/a"',
-        errors: [ 'Useless path segments for "./deep//a", should be "./deep/a"'],
+        errors: ['Useless path segments for "./deep//a", should be "./deep/a"'],
       }),
 
       // ES modules + noUselessIndex
@@ -231,19 +231,19 @@ function runResolverTests(resolver) {
       test({
         code: 'import("./")',
         output: 'import(".")',
-        errors: [ 'Useless path segments for "./", should be "."'],
+        errors: ['Useless path segments for "./", should be "."'],
         parser: parsers.BABEL_OLD,
       }),
       test({
         code: 'import("../")',
         output: 'import("..")',
-        errors: [ 'Useless path segments for "../", should be ".."'],
+        errors: ['Useless path segments for "../", should be ".."'],
         parser: parsers.BABEL_OLD,
       }),
       test({
         code: 'import("./deep//a")',
         output: 'import("./deep/a")',
-        errors: [ 'Useless path segments for "./deep//a", should be "./deep/a"'],
+        errors: ['Useless path segments for "./deep//a", should be "./deep/a"'],
         parser: parsers.BABEL_OLD,
       }),
     ],
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 84b341e1b0..db6aec4fcf 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -236,7 +236,7 @@ ruleTester.run('order', rule, {
         import fs from 'fs';
         import { add } from './helper';`,
       options: [{
-        groups: [ 'unknown', 'builtin', 'external', 'parent', 'sibling', 'index' ],
+        groups: ['unknown', 'builtin', 'external', 'parent', 'sibling', 'index'],
       }],
     }),
     // Using unknown import types (e.g. using a resolver alias via babel)
diff --git a/utils/ignore.js b/utils/ignore.js
index e41d1e5a50..960538e706 100644
--- a/utils/ignore.js
+++ b/utils/ignore.js
@@ -20,7 +20,7 @@ function validExtensions(context) {
 
 function makeValidExtensionSet(settings) {
   // start with explicit JS-parsed extensions
-  const exts = new Set(settings['import/extensions'] || [ '.js' ]);
+  const exts = new Set(settings['import/extensions'] || ['.js']);
 
   // all alternate parser extensions are also valid
   if ('import/parsers' in settings) {

From a6de522d1afb734becb6c478766e6c2ed6c873c6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 10:10:02 -0700
Subject: [PATCH 601/767] [Tests] `no-unused-modules`: properly skip in mocha 3

---
 tests/src/rules/no-unused-modules.js | 30 +++++++++++++++-------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 936123ab71..219d996b3a 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -1374,19 +1374,21 @@ describe('parser ignores prefixes like BOM and hashbang', () => {
   });
 });
 
-describe('supports flat eslint', { skip: !FlatRuleTester }, () => {
-  const flatRuleTester = new FlatRuleTester();
-  flatRuleTester.run('no-unused-modules', rule, {
-    valid: [{
-      options: unusedExportsOptions,
-      code: 'import { o2 } from "./file-o"; export default () => 12',
-      filename: testFilePath('./no-unused-modules/file-a.js'),
-    }],
-    invalid: [{
-      options: unusedExportsOptions,
-      code: 'export default () => 13',
-      filename: testFilePath('./no-unused-modules/file-f.js'),
-      errors: [error(`exported declaration 'default' not used within other modules`)],
-    }],
+(FlatRuleTester ? describe : describe.skip)('supports flat eslint', () => {
+  it('passes', () => {
+    const flatRuleTester = new FlatRuleTester();
+    flatRuleTester.run('no-unused-modules', rule, {
+      valid: [{
+        options: unusedExportsOptions,
+        code: 'import { o2 } from "./file-o"; export default () => 12',
+        filename: testFilePath('./no-unused-modules/file-a.js'),
+      }],
+      invalid: [{
+        options: unusedExportsOptions,
+        code: 'export default () => 13',
+        filename: testFilePath('./no-unused-modules/file-f.js'),
+        errors: [error(`exported declaration 'default' not used within other modules`)],
+      }],
+    });
   });
 });

From 3e1dd0b7b5af7dc2e5f54fc25534b8a944fd49c2 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 10:47:14 -0700
Subject: [PATCH 602/767] [Fix] `no-unused-modules`: improve schema

 - allow empty arrays in `src` and `ignoreExports`
 - enforce uniqueness in `src` and `ignoreExport` lists
 - allow false/true combo on missingExports/unusedExports
---
 CHANGELOG.md                    |  1 +
 docs/rules/no-unused-modules.md |  2 +-
 src/rules/no-unused-modules.js  | 39 ++++++++++-----------------------
 3 files changed, 14 insertions(+), 28 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7febb37111..c85317cca1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: partial fix for [#2687] (thanks [@ljharb])
 - [`no-duplicates`]: Detect across type and regular imports ([#2835], thanks [@benkrejci])
 - [`extensions`]: handle `.` and `..` properly ([#2778], thanks [@benasher44])
+ - [`no-unused-modules`]: improve schema (thanks [@ljharb])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index 5cd24bef41..a8e1a3c182 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -12,7 +12,7 @@ Reports:
 
 ### Usage
 
-In order for this plugin to work, one of the options `missingExports` or `unusedExports` must be enabled (see "Options" section below). In the future, these options will be enabled by default (see https://github.com/import-js/eslint-plugin-import/issues/1324)
+In order for this plugin to work, at least one of the options `missingExports` or `unusedExports` must be enabled (see "Options" section below). In the future, these options will be enabled by default (see https://github.com/import-js/eslint-plugin-import/issues/1324)
 
 Example:
 ```
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index a2b6f4ea27..f3d56e4291 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -416,17 +416,16 @@ module.exports = {
         src: {
           description: 'files/paths to be analyzed (only for unused exports)',
           type: 'array',
-          minItems: 1,
+          uniqueItems: true,
           items: {
             type: 'string',
             minLength: 1,
           },
         },
         ignoreExports: {
-          description:
-            'files/paths for which unused exports will not be reported (e.g module entry points)',
+          description: 'files/paths for which unused exports will not be reported (e.g module entry points)',
           type: 'array',
-          minItems: 1,
+          uniqueItems: true,
           items: {
             type: 'string',
             minLength: 1,
@@ -441,37 +440,23 @@ module.exports = {
           type: 'boolean',
         },
       },
-      not: {
-        properties: {
-          unusedExports: { enum: [false] },
-          missingExports: { enum: [false] },
-        },
-      },
-      anyOf: [{
-        not: {
+      anyOf: [
+        {
           properties: {
             unusedExports: { enum: [true] },
+            src: {
+              minItems: 1,
+            },
           },
+          required: ['unusedExports'],
         },
-        required: ['missingExports'],
-      }, {
-        not: {
+        {
           properties: {
             missingExports: { enum: [true] },
           },
+          required: ['missingExports'],
         },
-        required: ['unusedExports'],
-      }, {
-        properties: {
-          unusedExports: { enum: [true] },
-        },
-        required: ['unusedExports'],
-      }, {
-        properties: {
-          missingExports: { enum: [true] },
-        },
-        required: ['missingExports'],
-      }],
+      ],
     }],
   },
 

From d3aa4780e349a8af6466f13524c258544dac3d36 Mon Sep 17 00:00:00 2001
From: Jemi Salo <jemi.salo@gmail.com>
Date: Wed, 26 Jul 2023 16:37:16 +0300
Subject: [PATCH 603/767] [Tests] `no-unused-modules`: document error reported
 on entire `export` statement

---
 tests/src/rules/no-unused-modules.js | 46 ++++++++++++++++++----------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 219d996b3a..80f0fee730 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -164,24 +164,38 @@ ruleTester.run('no-unused-modules', rule, {
   invalid: [
     test({
       options: unusedExportsOptions,
-      code: `import eslint from 'eslint'
-           import fileA from './file-a'
-           import { b } from './file-b'
-           import { c1, c2 } from './file-c'
-           import { d } from './file-d'
-           import { e } from './file-e'
-           import { e2 } from './file-e'
-           import { h2 } from './file-h'
-           import * as l from './file-l'
-           export * from './file-n'
-           export { default, o0, o3 } from './file-o'
-           export { p } from './file-p'
-           import s from './file-s'`,
+      code: `
+        import eslint from 'eslint'
+        import fileA from './file-a'
+        import { b } from './file-b'
+        import { c1, c2 } from './file-c'
+        import { d } from './file-d'
+        import { e } from './file-e'
+        import { e2 } from './file-e'
+        import { h2 } from './file-h'
+        import * as l from './file-l'
+        export * from './file-n'
+        export { default, o0, o3 } from './file-o'
+        export { p } from './file-p'
+        import s from './file-s'
+      `,
       filename: testFilePath('./no-unused-modules/file-0.js'),
       errors: [
-        error(`exported declaration 'default' not used within other modules`),
-        error(`exported declaration 'o0' not used within other modules`),
-        error(`exported declaration 'o3' not used within other modules`),
+        {
+          message: `exported declaration 'default' not used within other modules`,
+          line: 12,
+          column: 9,
+        },
+        {
+          message: `exported declaration 'o0' not used within other modules`,
+          line: 12,
+          column: 9,
+        },
+        {
+          message: `exported declaration 'o3' not used within other modules`,
+          line: 12,
+          column: 9,
+        },
         error(`exported declaration 'p' not used within other modules`),
       ],
     }),

From 90e2dfa8c8f2ebdef8dc5d19873b3134c8a916e0 Mon Sep 17 00:00:00 2001
From: Jemi Salo <jemi.salo@gmail.com>
Date: Wed, 26 Jul 2023 16:38:09 +0300
Subject: [PATCH 604/767] [Fix] `no-unused-modules`: report error on binding
 instead of parent export

---
 CHANGELOG.md                         | 5 ++++-
 src/rules/no-unused-modules.js       | 2 +-
 tests/src/rules/no-unused-modules.js | 6 +++---
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c85317cca1..2f9e67189c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,7 +15,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: partial fix for [#2687] (thanks [@ljharb])
 - [`no-duplicates`]: Detect across type and regular imports ([#2835], thanks [@benkrejci])
 - [`extensions`]: handle `.` and `..` properly ([#2778], thanks [@benasher44])
- - [`no-unused-modules`]: improve schema (thanks [@ljharb])
+- [`no-unused-modules`]: improve schema (thanks [@ljharb])
+- [`no-unused-modules`]: report error on binding instead of parent export ([#2842], thanks [@Chamion])
 
 ### Changed
 - [Docs] [`no-duplicates`]: fix example schema ([#2684], thanks [@simmo])
@@ -1076,6 +1077,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2842]: https://github.com/import-js/eslint-plugin-import/pull/2842
 [#2835]: https://github.com/import-js/eslint-plugin-import/pull/2835
 [#2832]: https://github.com/import-js/eslint-plugin-import/pull/2832
 [#2778]: https://github.com/import-js/eslint-plugin-import/pull/2778
@@ -1666,6 +1668,7 @@ for info on changes for earlier releases.
 [@bradzacher]: https://github.com/bradzacher
 [@brendo]: https://github.com/brendo
 [@brettz9]: https://github.com/brettz9
+[@Chamion]: https://github.com/Chamion
 [@charlessuh]: https://github.com/charlessuh
 [@charpeni]: https://github.com/charpeni
 [@cherryblossom000]: https://github.com/cherryblossom000
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index f3d56e4291..c8a20f8c0e 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -931,7 +931,7 @@ module.exports = {
       },
       ExportNamedDeclaration(node) {
         node.specifiers.forEach((specifier) => {
-          checkUsage(node, specifier.exported.name || specifier.exported.value);
+          checkUsage(specifier, specifier.exported.name || specifier.exported.value);
         });
         forEachDeclarationIdentifier(node.declaration, (name) => {
           checkUsage(node, name);
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 80f0fee730..77fb608ccb 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -184,17 +184,17 @@ ruleTester.run('no-unused-modules', rule, {
         {
           message: `exported declaration 'default' not used within other modules`,
           line: 12,
-          column: 9,
+          column: 18,
         },
         {
           message: `exported declaration 'o0' not used within other modules`,
           line: 12,
-          column: 9,
+          column: 27,
         },
         {
           message: `exported declaration 'o3' not used within other modules`,
           line: 12,
-          column: 9,
+          column: 31,
         },
         error(`exported declaration 'p' not used within other modules`),
       ],

From 70f24f1fefcf3da0f804d273fa3347e9471fbb77 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 20:25:17 -0700
Subject: [PATCH 605/767] [Tests] allow WSL builds to fail, for now

---
 appveyor.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/appveyor.yml b/appveyor.yml
index dbeb0132d6..e50ab87d2a 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -26,6 +26,7 @@ matrix:
 
   allow_failures:
     - nodejs_version: "4" # for eslint 5
+    - configuration: WSL
 
 platform:
   - x86

From 703e9f9395ed8fe03c6c8c3c4cc04360d7df3d7e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 20:38:59 -0700
Subject: [PATCH 606/767] [Refactor] `no-duplicates`, `no-unused-modules`: use
 `flatMap` instead of `map` + `filter`

---
 src/rules/no-default-export.js   | 18 ++++++++++--------
 src/rules/no-duplicates.js       | 11 +++++------
 src/rules/no-restricted-paths.js | 11 ++++++-----
 src/rules/no-unused-modules.js   |  6 ++----
 tests/src/package.js             |  3 +--
 tests/src/rules/order.js         |  2 +-
 6 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index 6e5a537485..dabbae543a 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -27,14 +27,16 @@ module.exports = {
       },
 
       ExportNamedDeclaration(node) {
-        node.specifiers.filter((specifier) => (specifier.exported.name || specifier.exported.value) === 'default').forEach((specifier) => {
-          const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {};
-          if (specifier.type === 'ExportDefaultSpecifier') {
-            context.report({ node, message: preferNamed, loc });
-          } else if (specifier.type === 'ExportSpecifier') {
-            context.report({ node, message: noAliasDefault(specifier), loc  });
-          }
-        });
+        node.specifiers
+          .filter((specifier) => (specifier.exported.name || specifier.exported.value) === 'default')
+          .forEach((specifier) => {
+            const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {};
+            if (specifier.type === 'ExportDefaultSpecifier') {
+              context.report({ node, message: preferNamed, loc });
+            } else if (specifier.type === 'ExportSpecifier') {
+              context.report({ node, message: noAliasDefault(specifier), loc  });
+            }
+          });
       },
     };
   },
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 2373202cb6..6b4f4d559e 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -1,6 +1,8 @@
 import resolve from 'eslint-module-utils/resolve';
-import docsUrl from '../docsUrl';
 import semver from 'semver';
+import flatMap from 'array.prototype.flatmap';
+
+import docsUrl from '../docsUrl';
 
 let typescriptPkg;
 try {
@@ -51,7 +53,7 @@ function getFix(first, rest, sourceCode, context) {
   }
 
   const defaultImportNames = new Set(
-    [first, ...rest].map(getDefaultImportName).filter(Boolean),
+    flatMap([].concat(first, rest || []), (x) => getDefaultImportName(x) || []),
   );
 
   // Bail if there are multiple different default import names – it's up to the
@@ -62,10 +64,7 @@ function getFix(first, rest, sourceCode, context) {
 
   // Leave it to the user to handle comments. Also skip `import * as ns from
   // './foo'` imports, since they cannot be merged into another import.
-  const restWithoutComments = rest.filter((node) => !(
-    hasProblematicComments(node, sourceCode)
-    || hasNamespace(node)
-  ));
+  const restWithoutComments = rest.filter((node) => !hasProblematicComments(node, sourceCode) && !hasNamespace(node));
 
   const specifiers = restWithoutComments
     .map((node) => {
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index bce9fd1a03..cd680a1946 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -77,9 +77,11 @@ module.exports = {
     const restrictedPaths = options.zones || [];
     const basePath = options.basePath || process.cwd();
     const currentFilename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
-    const matchingZones = restrictedPaths.filter((zone) => [].concat(zone.target)
-      .map((target) => path.resolve(basePath, target))
-      .some((targetPath) => isMatchingTargetPath(currentFilename, targetPath)));
+    const matchingZones = restrictedPaths.filter(
+      (zone) => [].concat(zone.target)
+        .map((target) => path.resolve(basePath, target))
+        .some((targetPath) => isMatchingTargetPath(currentFilename, targetPath)),
+    );
 
     function isMatchingTargetPath(filename, targetPath) {
       if (isGlob(targetPath)) {
@@ -231,8 +233,7 @@ module.exports = {
         reportInvalidExceptions(validatorsWithInvalidExceptions, node);
 
         const applicableValidatorsForImportPathExcludingExceptions = applicableValidatorsForImportPath
-          .filter((validator) => validator.hasValidExceptions)
-          .filter((validator) => !validator.isPathException(absoluteImportPath));
+          .filter((validator) => validator.hasValidExceptions && !validator.isPathException(absoluteImportPath));
         reportImportsInRestrictedZone(applicableValidatorsForImportPathExcludingExceptions, node, importPath, zone.message);
       });
     }
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index c8a20f8c0e..ecba3a19ce 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -177,7 +177,7 @@ const resolveFiles = (src, ignoreExports, context) => {
   // prepare list of source files, don't consider files from node_modules
 
   return new Set(
-    srcFileList.filter(({ filename }) => !isNodeModule(filename)).map(({ filename }) => filename),
+    flatMap(srcFileList, ({ filename }) => isNodeModule(filename) ? [] : filename),
   );
 };
 
@@ -359,9 +359,7 @@ const fileIsInPkg = (file) => {
   };
 
   const checkPkgFieldObject = (pkgField) => {
-    const pkgFieldFiles = values(pkgField)
-      .filter((value) => typeof value !== 'boolean')
-      .map((value) => join(basePath, value));
+    const pkgFieldFiles = flatMap(values(pkgField), (value) => typeof value === 'boolean' ? [] : join(basePath, value));
 
     if (includes(pkgFieldFiles, file)) {
       return true;
diff --git a/tests/src/package.js b/tests/src/package.js
index dd55e2740b..08138084c6 100644
--- a/tests/src/package.js
+++ b/tests/src/package.js
@@ -27,8 +27,7 @@ describe('package', function () {
         expect(err).not.to.exist;
 
         files.filter(isJSFile).forEach(function (f) {
-          expect(module.rules).to.have
-            .property(path.basename(f, '.js'));
+          expect(module.rules).to.have.property(path.basename(f, '.js'));
         });
 
         done();
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index db6aec4fcf..2a44aa06aa 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2736,7 +2736,7 @@ ruleTester.run('order', rule, {
         }],
       }),
     ],
-  ].filter((t) => !!t),
+  ].filter(Boolean),
 });
 
 context('TypeScript', function () {

From 89f5d0d1b2c4200b90b45c37a588f08d59757187 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 20:40:41 -0700
Subject: [PATCH 607/767] [Refactor] `no-anonymous-default-export`: use
 `fromEntries` instead of `reduce`

---
 src/rules/no-anonymous-default-export.js | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js
index 06ea854b33..59a3cbfdac 100644
--- a/src/rules/no-anonymous-default-export.js
+++ b/src/rules/no-anonymous-default-export.js
@@ -60,16 +60,10 @@ const defs = {
   },
 };
 
-const schemaProperties = Object.keys(defs)
-  .map((key) => defs[key])
-  .reduce((acc, def) => {
-    acc[def.option] = {
-      description: def.description,
-      type: 'boolean',
-    };
-
-    return acc;
-  }, {});
+const schemaProperties = fromEntries(values(defs).map((def) => [def.option, {
+  description: def.description,
+  type: 'boolean',
+}]));
 
 const defaults = fromEntries(values(defs).map((def) => [def.option, has(def, 'default') ? def.default : false]));
 

From e7c248685eb1a74ad0e5093d5466f4de918c4cb6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 20:42:52 -0700
Subject: [PATCH 608/767] [Refactor] `no-useless-path-segments`: use `.filter`
 instead of `.reduce`

---
 src/rules/no-useless-path-segments.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index 343a4f6230..390a7546d3 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -33,7 +33,7 @@ function normalize(fn) {
 }
 
 function countRelativeParents(pathSegments) {
-  return pathSegments.reduce((sum, pathSegment) => pathSegment === '..' ? sum + 1 : sum, 0);
+  return pathSegments.filter((x) => x === '..').length;
 }
 
 module.exports = {

From be928ae19461f405d813798e49d2968982823c17 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 20:45:50 -0700
Subject: [PATCH 609/767] [Refactor] `no-internal-modules`: simplify a reduce

---
 src/rules/no-internal-modules.js | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/rules/no-internal-modules.js b/src/rules/no-internal-modules.js
index 687193f5c5..5ed4565471 100644
--- a/src/rules/no-internal-modules.js
+++ b/src/rules/no-internal-modules.js
@@ -58,16 +58,14 @@ module.exports = {
     }
 
     function toSteps(somePath) {
-      return  normalizeSep(somePath)
+      return normalizeSep(somePath)
         .split('/')
+        .filter((step) => step && step !== '.')
         .reduce((acc, step) => {
-          if (!step || step === '.') {
-            return acc;
-          } else if (step === '..') {
+          if (step === '..') {
             return acc.slice(0, -1);
-          } else {
-            return acc.concat(step);
           }
+          return acc.concat(step);
         }, []);
     }
 

From 600fcc10dba3229e5f69373f6e2b0896032ad4b9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 20:49:06 -0700
Subject: [PATCH 610/767] [Refactor] `order`: use `object.groupby`

---
 package.json       | 1 +
 src/rules/order.js | 9 ++-------
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/package.json b/package.json
index e870082e34..c214e59558 100644
--- a/package.json
+++ b/package.json
@@ -114,6 +114,7 @@
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.fromentries": "^2.0.6",
+    "object.groupby": "^1.0.0",
     "object.values": "^1.1.6",
     "resolve": "^1.22.3",
     "semver": "^6.3.1",
diff --git a/src/rules/order.js b/src/rules/order.js
index 27c3f4b0f9..6f70db263c 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -2,6 +2,7 @@
 
 import minimatch from 'minimatch';
 import includes from 'array-includes';
+import groupBy from 'object.groupby';
 
 import importType from '../core/importType';
 import isStaticRequire from '../core/staticRequire';
@@ -325,13 +326,7 @@ function getSorter(alphabetizeOptions) {
 }
 
 function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
-  const groupedByRanks = imported.reduce(function (acc, importedItem) {
-    if (!Array.isArray(acc[importedItem.rank])) {
-      acc[importedItem.rank] = [];
-    }
-    acc[importedItem.rank].push(importedItem);
-    return acc;
-  }, {});
+  const groupedByRanks = groupBy(imported, (item) => item.rank);
 
   const sorterFn = getSorter(alphabetizeOptions);
 

From a257df9fe0683289c51e3ffe7b64ec0062fd69a8 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 27 Jul 2023 21:24:51 -0700
Subject: [PATCH 611/767] Bump to 2.28.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2f9e67189c..b7af776f86 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.28.0] - 2023-07-27
+
 ### Fixed
 - [`no-duplicates`]: remove duplicate identifiers in duplicate imports ([#2577], thanks [@joe-matsec])
 - [`consistent-type-specifier-style`]: fix accidental removal of comma in certain cases ([#2754], thanks [@bradzacher])
@@ -1535,7 +1537,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.0...HEAD
+[2.28.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...v2.28.0
 [2.27.5]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.4...v2.27.5
 [2.27.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.3...v2.27.4
 [2.27.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.2...v2.27.3
diff --git a/package.json b/package.json
index c214e59558..81905b59b2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.27.5",
+  "version": "2.28.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 132a433f9cb6541a630211b7299d88935556afee Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 5 Aug 2023 15:14:03 +1200
Subject: [PATCH 612/767] [Deps] update `is-core-module`, `resolve`

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 81905b59b2..eea3d97a22 100644
--- a/package.json
+++ b/package.json
@@ -110,13 +110,13 @@
     "eslint-import-resolver-node": "^0.3.7",
     "eslint-module-utils": "^2.8.0",
     "has": "^1.0.3",
-    "is-core-module": "^2.12.1",
+    "is-core-module": "^2.13.0",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.fromentries": "^2.0.6",
     "object.groupby": "^1.0.0",
     "object.values": "^1.1.6",
-    "resolve": "^1.22.3",
+    "resolve": "^1.22.4",
     "semver": "^6.3.1",
     "tsconfig-paths": "^3.14.2"
   }

From 5209a43607a19fe8fd4e0226bebc393c892438cf Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 5 Aug 2023 15:17:45 +1200
Subject: [PATCH 613/767] [resolvers] [*] [deps] update `is-core-module`,
 `resolve`

---
 resolvers/README.md            | 4 ++--
 resolvers/node/index.js        | 8 ++++----
 resolvers/node/package.json    | 4 ++--
 resolvers/webpack/index.js     | 6 +++---
 resolvers/webpack/package.json | 4 ++--
 5 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/resolvers/README.md b/resolvers/README.md
index b664721b83..0eb18684b9 100644
--- a/resolvers/README.md
+++ b/resolvers/README.md
@@ -68,13 +68,13 @@ If the resolver cannot resolve `source` relative to `file`, it should just retur
 Here is most of the [Node resolver] at the time of this writing. It is just a wrapper around substack/Browserify's synchronous [`resolve`]:
 
 ```js
-var resolve = require('resolve');
+var resolve = require('resolve/sync');
 var isCoreModule = require('is-core-module');
 
 exports.resolve = function (source, file, config) {
   if (isCoreModule(source)) return { found: true, path: null };
   try {
-    return { found: true, path: resolve.sync(source, opts(file, config)) };
+    return { found: true, path: resolve(source, opts(file, config)) };
   } catch (err) {
     return { found: false };
   }
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index d382bca43d..212b3b16b5 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const resolve = require('resolve');
+const resolve = require('resolve/sync');
 const isCoreModule = require('is-core-module');
 const path = require('path');
 
@@ -19,7 +19,7 @@ exports.resolve = function (source, file, config) {
 
   try {
     const cachedFilter = function (pkg, dir) { return packageFilter(pkg, dir, config); };
-    resolvedPath = resolve.sync(source, opts(file, config, cachedFilter));
+    resolvedPath = resolve(source, opts(file, config, cachedFilter));
     log('Resolved to:', resolvedPath);
     return { found: true, path: resolvedPath };
   } catch (err) {
@@ -46,7 +46,7 @@ function packageFilter(pkg, dir, config) {
   const file = path.join(dir, 'dummy.js');
   if (pkg.module) {
     try {
-      resolve.sync(String(pkg.module).replace(/^(?:\.\/)?/, './'), opts(file, config, identity));
+      resolve(String(pkg.module).replace(/^(?:\.\/)?/, './'), opts(file, config, identity));
       pkg.main = pkg.module;
       found = true;
     } catch (err) {
@@ -55,7 +55,7 @@ function packageFilter(pkg, dir, config) {
   }
   if (!found && pkg['jsnext:main']) {
     try {
-      resolve.sync(String(pkg['jsnext:main']).replace(/^(?:\.\/)?/, './'), opts(file, config, identity));
+      resolve(String(pkg['jsnext:main']).replace(/^(?:\.\/)?/, './'), opts(file, config, identity));
       pkg.main = pkg['jsnext:main'];
       found = true;
     } catch (err) {
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index c63ee976b6..ac4da0d401 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -30,8 +30,8 @@
   "homepage": "https://github.com/import-js/eslint-plugin-import",
   "dependencies": {
     "debug": "^3.2.7",
-    "is-core-module": "^2.12.0",
-    "resolve": "^1.22.2"
+    "is-core-module": "^2.13.0",
+    "resolve": "^1.22.4"
   },
   "devDependencies": {
     "chai": "^3.5.0",
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 8eb2db5ad6..836d90f97a 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -8,7 +8,7 @@ const find = require('array-find');
 const interpret = require('interpret');
 const fs = require('fs');
 const isCore = require('is-core-module');
-const resolve = require('resolve');
+const resolve = require('resolve/sync');
 const semver = require('semver');
 const has = require('has');
 const isRegex = require('is-regex');
@@ -190,11 +190,11 @@ function createResolveSync(configPath, webpackConfig, cwd) {
 
   try {
     // Attempt to resolve webpack from the given `basedir`
-    const webpackFilename = resolve.sync('webpack', { basedir, preserveSymlinks: false });
+    const webpackFilename = resolve('webpack', { basedir, preserveSymlinks: false });
     const webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false };
 
     webpackRequire = function (id) {
-      return require(resolve.sync(id, webpackResolveOpts));
+      return require(resolve(id, webpackResolveOpts));
     };
   } catch (e) {
     // Something has gone wrong (or we're in a test). Use our own bundled
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index ba21801e61..8d67875778 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -36,10 +36,10 @@
     "find-root": "^1.1.0",
     "has": "^1.0.3",
     "interpret": "^1.4.0",
-    "is-core-module": "^2.12.0",
+    "is-core-module": "^2.13.0",
     "is-regex": "^1.1.4",
     "lodash": "^4.17.21",
-    "resolve": "^1.22.2",
+    "resolve": "^1.22.4",
     "semver": "^5.7.1"
   },
   "peerDependencies": {

From 4a75aaf4270f50ce7b5ddb3e3917613becd927a5 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 5 Aug 2023 15:18:19 +1200
Subject: [PATCH 614/767] [Deps] remove unused root dep

---
 package.json | 1 -
 1 file changed, 1 deletion(-)

diff --git a/package.json b/package.json
index eea3d97a22..3884ff0653 100644
--- a/package.json
+++ b/package.json
@@ -116,7 +116,6 @@
     "object.fromentries": "^2.0.6",
     "object.groupby": "^1.0.0",
     "object.values": "^1.1.6",
-    "resolve": "^1.22.4",
     "semver": "^6.3.1",
     "tsconfig-paths": "^3.14.2"
   }

From 95f9f004c63a69a0094ecfe5cd1cbeed38413c60 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 5 Aug 2023 15:19:02 +1200
Subject: [PATCH 615/767] [resolvers/webpack] [deps] update `semver`

---
 resolvers/webpack/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 8d67875778..8f066b19d0 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -40,7 +40,7 @@
     "is-regex": "^1.1.4",
     "lodash": "^4.17.21",
     "resolve": "^1.22.4",
-    "semver": "^5.7.1"
+    "semver": "^5.7.2"
   },
   "peerDependencies": {
     "eslint-plugin-import": ">=1.4.0",

From 6f6f414ee1ba9ddc8855a88b616fa9d84381e08b Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 5 Aug 2023 15:23:21 +1200
Subject: [PATCH 616/767] [resolvers/webpack] v0.13.3

---
 resolvers/webpack/CHANGELOG.md | 127 +++++++++++++++++----------------
 resolvers/webpack/package.json |   2 +-
 2 files changed, 67 insertions(+), 62 deletions(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 1626bb2720..8a0784a500 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,12 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## 0.13.3 - 2023-08-05
+ - [deps] update `is-core-module`, `resolve`, `semver`
+ - [eslint] tighten up rules
+ - [Tests] consolidate eslint config
+ - [Docs] HTTP => HTTPS ([#2287], thanks [@Schweinepriester])
+
 ## 0.13.2 - 2021-10-20
 
 ### Changed
@@ -13,35 +19,35 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## 0.13.1 - 2021-05-13
 
 ### Added
-- add support for webpack5 'externals function' ([#2023], thanks [@jet2jet])
+ - add support for webpack5 'externals function' ([#2023], thanks [@jet2jet])
 
 ### Changed
-- Add warning about async Webpack configs ([#1962], thanks [@ogonkov])
-- Replace `node-libs-browser` with `is-core-module` ([#1967], thanks [@andersk])
-- [meta] add "engines" field to document existing requirements
-- [Refactor] use `is-regex` instead of `instanceof RegExp`
-- [Refactor] use `Array.isArray` instead of `instanceof Array`
-- [deps] update `debug`, `interpret`, `is-core-module`, `lodash`, `resolve`
+ - Add warning about async Webpack configs ([#1962], thanks [@ogonkov])
+ - Replace `node-libs-browser` with `is-core-module` ([#1967], thanks [@andersk])
+ - [meta] add "engines" field to document existing requirements
+ - [Refactor] use `is-regex` instead of `instanceof RegExp`
+ - [Refactor] use `Array.isArray` instead of `instanceof Array`
+ - [deps] update `debug`, `interpret`, `is-core-module`, `lodash`, `resolve`
 
 ## 0.13.0 - 2020-09-27
 
 ### Breaking
-- [Breaking] Allow to resolve config path relative to working directory (#1276)
+ - [Breaking] Allow to resolve config path relative to working directory (#1276)
 
 ## 0.12.2 - 2020-06-16
 
 ### Fixed
-- [fix] provide config fallback ([#1705], thanks [@migueloller])
+ - [fix] provide config fallback ([#1705], thanks [@migueloller])
 
 ## 0.12.1 - 2020-01-10
 
 ### Changed
-- [meta] copy LICENSE file to all npm packages on prepublish ([#1595], thanks [@opichals])
+ - [meta] copy LICENSE file to all npm packages on prepublish ([#1595], thanks [@opichals])
 
 ## 0.12.0 - 2019-12-07
 
 ### Added
-- [New] enable passing cwd as an option to `eslint-import-resolver-webpack` ([#1503], thanks [@Aghassi])
+ - [New] enable passing cwd as an option to `eslint-import-resolver-webpack` ([#1503], thanks [@Aghassi])
 
 ## 0.11.1 - 2019-04-13
 
@@ -51,110 +57,108 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## 0.11.0 - 2018-01-22
 
 ### Added
-- support for `argv` parameter when config is a function. ([#1261], thanks [@keann])
+ - support for `argv` parameter when config is a function. ([#1261], thanks [@keann])
 
 ### Fixed
-- crash when webpack config is an array of functions ([#1219]/[#1220] by [@idudinov])
+ - crash when webpack config is an array of functions ([#1219]/[#1220] by [@idudinov])
 
 ## 0.10.1 - 2018-06-24
 ### Fixed
-- log a useful error in a module bug arises ([#768]/[#767], thanks [@mattkrick])
+ - log a useful error in a module bug arises ([#768]/[#767], thanks [@mattkrick])
 
 ## 0.10.0 - 2018-05-17
 ### Changed
-- cache webpack resolve function, for performance ([#788]/[#1091])
+ - cache webpack resolve function, for performance ([#788]/[#1091])
 
 ## 0.9.0 - 2018-03-29
 ### Breaking
-- Fix with `pnpm` by bumping `resolve` ([#968])
+ - Fix with `pnpm` by bumping `resolve` ([#968])
 
 ## 0.8.4 - 2018-01-05
 ### Changed
-- allow newer version of node-libs-browser ([#969])
+ - allow newer version of node-libs-browser ([#969])
 
 ## 0.8.3 - 2017-06-23
 ### Changed
-- `debug` bumped to match others
+ - `debug` bumped to match others
 
 ## 0.8.2 - 2017-06-22
 ### Changed
-- `webpack` peer dep updated to >= 1.11 (works fine with webpack 3 AFAICT)
+ - `webpack` peer dep updated to >= 1.11 (works fine with webpack 3 AFAICT)
 
 ## 0.8.1 - 2017-01-19
 ### Changed
-- official support for Webpack 2.2.0 (RC), thanks [@graingert]
+ - official support for Webpack 2.2.0 (RC), thanks [@graingert]
 
 ## 0.8.0 - 2016-12-15
 ### Changed
-- bumped `resolve` to fix issues with Node builtins (thanks [@SkeLLLa] and [@ljharb])
-- allow `enhanced-resolve` to be version `>= 2` (thanks [@Kovensky])
+ - bumped `resolve` to fix issues with Node builtins (thanks [@SkeLLLa] and [@ljharb])
+ - allow `enhanced-resolve` to be version `>= 2` (thanks [@Kovensky])
 
 ## 0.7.1
 ### Fixed
-- missing `has` dependency ([#681] + [#683], thanks [@benmvp] + [@ljharb])
+ - missing `has` dependency ([#681] + [#683], thanks [@benmvp] + [@ljharb])
 
 ## 0.7.0
 ### Added
-- Support for explicit Webpack config object in `.eslintrc.*`. ([#572], thanks [@jameslnewell])
-- Added `resolve.modules` to configs for webpack2 support ([#569], thanks [@toshafed])
+ - Support for explicit Webpack config object in `.eslintrc.*`. ([#572], thanks [@jameslnewell])
+ - Added `resolve.modules` to configs for webpack2 support ([#569], thanks [@toshafed])
 
 ## 0.6.0 - 2016-09-13
 ### Added
-- support for config-as-function ([#533], thanks [@grahamb])
+ - support for config-as-function ([#533], thanks [@grahamb])
 
 ## 0.5.1 - 2016-08-11
 ### Fixed
-- don't throw and die if no webpack config is found
+ - don't throw and die if no webpack config is found
 
 ## 0.5.0 - 2016-08-11
 ### Added
-- support for Webpack 2 + `module` package.json key! ([#475], thanks [@taion])
+ - support for Webpack 2 + `module` package.json key! ([#475], thanks [@taion])
 
 ### Changed
-- don't swallow errors, assume config exists ([#435], thanks [@Kovensky])
+ - don't swallow errors, assume config exists ([#435], thanks [@Kovensky])
 
 ## 0.4.0 - 2016-07-17
 ### Added
-- support for `webpack.ResolverPlugin` ([#377], thanks [@Rogeres])
+ - support for `webpack.ResolverPlugin` ([#377], thanks [@Rogeres])
 
 ### Fixed
-- provide string `context` to `externals` functions ([#411] + [#413], thanks [@Satyam])
+ - provide string `context` to `externals` functions ([#411] + [#413], thanks [@Satyam])
 
 ## 0.3.2 - 2016-06-30
 ### Added
-- shared config ([config.js](./config.js)) with barebones settings needed to use this resolver. ([#283])
+ - shared config ([config.js](./config.js)) with barebones settings needed to use this resolver. ([#283])
 
 ### Fixed
-- strip resource query ([#357], thanks [@daltones])
-- allow `externals` to be defined as a function ([#363], thanks [@kesne])
+ - strip resource query ([#357], thanks [@daltones])
+ - allow `externals` to be defined as a function ([#363], thanks [@kesne])
 
 ## 0.3.1 - 2016-06-02
 ### Added
-- debug logging. run with `DEBUG=eslint-plugin-import:*` to see log output.
+ - debug logging. run with `DEBUG=eslint-plugin-import:*` to see log output.
 
 ## 0.3.0 - 2016-06-01
 ### Changed
-- use `enhanced-resolve` to support additional plugins instead of re-implementing
-  aliases, etc.
+ - use `enhanced-resolve` to support additional plugins instead of re-implementing aliases, etc.
 
 ## 0.2.5 - 2016-05-23
 ### Added
-- Added support for multiple webpack configs ([#181], thanks [@GreenGremlin])
+ - Added support for multiple webpack configs ([#181], thanks [@GreenGremlin])
 
 ## 0.2.4 - 2016-04-29
 ### Changed
-- automatically find webpack config with `interpret`-able extensions ([#287], thanks [@taion])
+ - automatically find webpack config with `interpret`-able extensions ([#287], thanks [@taion])
 
 ## 0.2.3 - 2016-04-28
 ### Fixed
-- `interpret` dependency was declared in the wrong `package.json`.
-   Thanks [@jonboiser] for sleuthing ([#286]) and fixing ([#289]).
+ - `interpret` dependency was declared in the wrong `package.json`. Thanks [@jonboiser] for sleuthing ([#286]) and fixing ([#289]).
 
 ## 0.2.2 - 2016-04-27
 ### Added
-- `interpret` configs (such as `.babel.js`).
-  Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
+ - `interpret` configs (such as `.babel.js`). Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
+[#2287]: https://github.com/import-js/eslint-plugin-import/pull/2287
 [#2023]: https://github.com/import-js/eslint-plugin-import/pull/2023
 [#1967]: https://github.com/import-js/eslint-plugin-import/pull/1967
 [#1962]: https://github.com/import-js/eslint-plugin-import/pull/1962
@@ -192,29 +196,30 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 [#286]: https://github.com/import-js/eslint-plugin-import/issues/286
 [#283]: https://github.com/import-js/eslint-plugin-import/issues/283
 
+[@Aghassi]: https://github.com/Aghassi
+[@andersk]: https://github.com/andersk
+[@benmvp]: https://github.com/benmvp
+[@daltones]: https://github.com/daltones
+[@echenley]: https://github.com/echenley
 [@gausie]: https://github.com/gausie
-[@jquense]: https://github.com/jquense
-[@taion]: https://github.com/taion
+[@grahamb]: https://github.com/grahamb
+[@graingert]: https://github.com/graingert
 [@GreenGremlin]: https://github.com/GreenGremlin
-[@daltones]: https://github.com/daltones
+[@idudinov]: https://github.com/idudinov
+[@jameslnewell]: https://github.com/jameslnewell
+[@jet2jet]: https://github.com/jet2jet
+[@jquense]: https://github.com/jquense
+[@keann]: https://github.com/keann
 [@kesne]: https://github.com/kesne
-[@Satyam]: https://github.com/Satyam
-[@Rogeres]: https://github.com/Rogeres
 [@Kovensky]: https://github.com/Kovensky
-[@grahamb]: https://github.com/grahamb
-[@jameslnewell]: https://github.com/jameslnewell
-[@toshafed]: https://github.com/toshafed
-[@benmvp]: https://github.com/benmvp
 [@ljharb]: https://github.com/ljharb
-[@SkeLLLa]: https://github.com/SkeLLLa
-[@graingert]: https://github.com/graingert
 [@mattkrick]: https://github.com/mattkrick
-[@idudinov]: https://github.com/idudinov
-[@keann]: https://github.com/keann
-[@echenley]: https://github.com/echenley
-[@Aghassi]: https://github.com/Aghassi
 [@migueloller]: https://github.com/migueloller
-[@opichals]: https://github.com/opichals
-[@andersk]: https://github.com/andersk
 [@ogonkov]: https://github.com/ogonkov
-[@jet2jet]: https://github.com/jet2jet
+[@opichals]: https://github.com/opichals
+[@Rogeres]: https://github.com/Rogeres
+[@Satyam]: https://github.com/Satyam
+[@Schweinepriester]: https://github.com/Schweinepriester
+[@SkeLLLa]: https://github.com/SkeLLLa
+[@taion]: https://github.com/taion
+[@toshafed]: https://github.com/toshafed
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 8f066b19d0..f1592a5d61 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.2",
+  "version": "0.13.3",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 7f7a9a6d03b480bfa7453fdb58c84191f2724f97 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 5 Aug 2023 15:44:12 +1200
Subject: [PATCH 617/767] [resolvers/node] v0.3.8

---
 resolvers/node/CHANGELOG.md | 41 ++++++++++++++++++-------------------
 resolvers/node/package.json |  2 +-
 2 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index f00006fbd3..1335cbedee 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -5,60 +5,59 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v0.3.8 - 2023-08-05
+ - [deps] update `is-core-module`, `resolve`
+ - [eslint] tighten up rules
+
 ## v0.3.7 - 2023-01-11
 ### Changed
-- [Refactor] use `is-core-module` directly
+ - [Refactor] use `is-core-module` directly
 
 ## v0.3.6 - 2021-08-15
 ### Fixed
-- when "module" does not exist, fall back to "main" ([#2186], thanks [@ljharb])
+ - when "module" does not exist, fall back to "main" ([#2186], thanks [@ljharb])
 
 ## v0.3.5 - 2021-08-08
 ### Added
-- use "module" in the same spot as "jsnext:main" ([#2166], thanks [@MustafaHaddara])
+ - use "module" in the same spot as "jsnext:main" ([#2166], thanks [@MustafaHaddara])
 
 ## v0.3.4 - 2020-06-16
 ### Added
-- add `.node` extension ([#1663])
+ - add `.node` extension ([#1663])
 
 ## v0.3.3 - 2020-01-10
 ### Changed
-- [meta] copy LICENSE file to all npm packages on prepublish ([#1595], thanks [@opichals])
+ - [meta] copy LICENSE file to all npm packages on prepublish ([#1595], thanks [@opichals])
 
 ## v0.3.2 - 2018-01-05
 ### Added
-- `.mjs` extension detected by default to support `experimental-modules` ([#939])
+ - `.mjs` extension detected by default to support `experimental-modules` ([#939])
 
 ### Deps
-- update `debug`, `resolve`
+ - update `debug`, `resolve`
 
 ## v0.3.1 - 2017-06-23
 ### Changed
-- bumped `debug` dep to match other packages
+ - bumped `debug` dep to match other packages
 
 ## v0.3.0 - 2016-12-15
 ### Changed
-- bumped `resolve` to fix issues with Node builtins (thanks [@SkeLLLa] and [@ljharb])
+ - bumped `resolve` to fix issues with Node builtins (thanks [@SkeLLLa] and [@ljharb])
 
 ### Fixed
-- use `files` in `package.json` to ship only `index.js` ([#531], thanks for noticing [@lukeapage])
+ - use `files` in `package.json` to ship only `index.js` ([#531], thanks for noticing [@lukeapage])
 
 ## v0.2.3 - 2016-08-20
 ### Added
-- debug logging (use `DEBUG=eslint-plugin-import:resolver:node eslint [...]`)
+ - debug logging (use `DEBUG=eslint-plugin-import:resolver:node eslint [...]`)
 
 ## v0.2.2 - 2016-07-14
 ### Fixed
-- Node resolver no longer declares the import plugin as a `peerDependency`. See [#437]
-  for a well-articulated and thoughtful expression of why this doesn't make sense.
-  Thanks [@jasonkarns] for the issue and the PR to fix it ([#438]).
-
-  Also, apologies to the others who expressed this before, but I never understood
-  what the problem was.😅
+ - Node resolver no longer declares the import plugin as a `peerDependency`. See [#437] for a well-articulated and thoughtful expression of why this doesn't make sense. Thanks [@jasonkarns] for the issue and the PR to fix it ([#438]). Also, apologies to the others who expressed this before, but I never understood what the problem was.😅
 
 ## v0.2.1
 ### Fixed
-- find files with `.json` extensions (#333, thanks for noticing @jfmengels)
+ - find files with `.json` extensions (#333, thanks for noticing @jfmengels)
 
 [#2186]: https://github.com/import-js/eslint-plugin-import/issues/2186
 [#2166]: https://github.com/import-js/eslint-plugin-import/pull/2166
@@ -70,8 +69,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 [#437]: https://github.com/import-js/eslint-plugin-import/issues/437
 
 [@jasonkarns]: https://github.com/jasonkarns
-[@lukeapage]: https://github.com/lukeapage
-[@SkeLLLa]: https://github.com/SkeLLLa
 [@ljharb]: https://github.com/ljharb
-[@opichals]: https://github.com/opichals
+[@lukeapage]: https://github.com/lukeapage
 [@MustafaHaddara]: https://github.com/MustafaHaddara
+[@opichals]: https://github.com/opichals
+[@SkeLLLa]: https://github.com/SkeLLLa
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index ac4da0d401..33bf3b0102 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-node",
-  "version": "0.3.7",
+  "version": "0.3.8",
   "description": "Node default behavior import resolution plugin for eslint-plugin-import.",
   "main": "index.js",
   "files": [

From 0501367f48a2f74cc6d13bf120ad2fe629a96de1 Mon Sep 17 00:00:00 2001
From: Bryan Mishkin <698306+bmish@users.noreply.github.com>
Date: Sat, 5 Aug 2023 17:46:38 +0800
Subject: [PATCH 618/767] [Docs] remove duplicate fixable notices in docs

---
 CHANGELOG.md                       | 4 ++++
 docs/rules/newline-after-import.md | 3 +--
 docs/rules/no-duplicates.md        | 1 -
 docs/rules/no-namespace.md         | 3 +--
 docs/rules/no-relative-packages.md | 2 --
 docs/rules/order.md                | 1 -
 6 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7af776f86..96dbd8c107 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Changed
+- [Docs] remove duplicate fixable notices in docs ([#2850], thanks [@bmish])
+
 ## [2.28.0] - 2023-07-27
 
 ### Fixed
@@ -1079,6 +1082,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2850]: https://github.com/import-js/eslint-plugin-import/pull/2850
 [#2842]: https://github.com/import-js/eslint-plugin-import/pull/2842
 [#2835]: https://github.com/import-js/eslint-plugin-import/pull/2835
 [#2832]: https://github.com/import-js/eslint-plugin-import/pull/2832
diff --git a/docs/rules/newline-after-import.md b/docs/rules/newline-after-import.md
index ed0a5b678f..6aa75be552 100644
--- a/docs/rules/newline-after-import.md
+++ b/docs/rules/newline-after-import.md
@@ -5,11 +5,10 @@
 <!-- end auto-generated rule header -->
 
 Enforces having one or more empty lines after the last top-level import statement or require call.
-+(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule.
 
 ## Rule Details
 
-This rule supports the following options: 
+This rule supports the following options:
 - `count` which sets the number of newlines that are enforced after the last top-level import statement or require call. This option defaults to `1`.
 
 - `considerComments` which enforces the rule on comments after the last import-statement as well when set to true. This option defaults to `false`.
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index dd741c21a5..50f779b456 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -7,7 +7,6 @@
 <!-- end auto-generated rule header -->
 
 Reports if a resolved path is imported more than once.
-+(fixable) The `--fix` option on the [command line] automatically fixes some problems reported by this rule.
 
 ESLint core has a similar rule ([`no-duplicate-imports`](https://eslint.org/docs/rules/no-duplicate-imports)), but this version
 is different in two key ways:
diff --git a/docs/rules/no-namespace.md b/docs/rules/no-namespace.md
index 5545bce229..623dae049c 100644
--- a/docs/rules/no-namespace.md
+++ b/docs/rules/no-namespace.md
@@ -6,8 +6,7 @@
 
 Enforce a convention of not using namespace (a.k.a. "wildcard" `*`) imports.
 
-+(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule, provided that the namespace object is only used for direct member access, e.g. `namespace.a`.
-The `--fix` functionality for this rule requires ESLint 5 or newer.
+The rule is auto-fixable when the namespace object is only used for direct member access, e.g. `namespace.a`.
 
 ### Options
 
diff --git a/docs/rules/no-relative-packages.md b/docs/rules/no-relative-packages.md
index 4919de94e5..df21c25dd0 100644
--- a/docs/rules/no-relative-packages.md
+++ b/docs/rules/no-relative-packages.md
@@ -9,8 +9,6 @@ Use this rule to prevent importing packages through relative paths.
 It's useful in Yarn/Lerna workspaces, were it's possible to import a sibling
 package using `../package` relative path, while direct `package` is the correct one.
 
-+(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule.
-
 ### Examples
 
 Given the following folder structure:
diff --git a/docs/rules/order.md b/docs/rules/order.md
index e3deacaf24..6dc4520e8d 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -5,7 +5,6 @@
 <!-- end auto-generated rule header -->
 
 Enforce a convention in the order of `require()` / `import` statements.
-+(fixable) The `--fix` option on the [command line] automatically fixes problems reported by this rule.
 
 With the [`groups`](#groups-array) option set to `["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"]` the order is as shown in the following example:
 

From 69fce5c549a026d6efebac1233f54489a412b6e3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 8 Aug 2023 13:30:39 +1200
Subject: [PATCH 619/767] =?UTF-8?q?[Tests]=20actually=20test=20non-babel?=
 =?UTF-8?q?=E2=80=99d=20packages=20without=20babel?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Caused https://github.com/import-js/eslint-plugin-import/commit/8c155baaca39dc78c5a3a63ff1bdd53b58f343e0#r123814192
---
 .gitignore               |  4 ----
 memo-parser/.nycrc       | 19 +++++++++++++++++++
 resolvers/node/.nycrc    | 15 +++++++++++++++
 resolvers/webpack/.nycrc | 15 +++++++++++++++
 scripts/copyMetafiles.js |  1 -
 utils/.nycrc             | 15 +++++++++++++++
 6 files changed, 64 insertions(+), 5 deletions(-)
 create mode 100644 memo-parser/.nycrc
 create mode 100644 resolvers/node/.nycrc
 create mode 100644 resolvers/webpack/.nycrc
 create mode 100644 utils/.nycrc

diff --git a/.gitignore b/.gitignore
index 8e2f6da1ee..587dbd9280 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,13 +25,9 @@ resolvers/node/LICENSE
 resolvers/webpack/LICENSE
 utils/LICENSE
 memo-parser/.npmrc
-memo-parser/.nycrc
 resolvers/node/.npmrc
-resolvers/node/.nycrc
 resolvers/webpack/.npmrc
-resolvers/webpack/.nycrc
 utils/.npmrc
-utils/.nycrc
 
 # Dependency directory
 # Commenting this out is preferred by some people, see
diff --git a/memo-parser/.nycrc b/memo-parser/.nycrc
new file mode 100644
index 0000000000..5d75e2157c
--- /dev/null
+++ b/memo-parser/.nycrc
@@ -0,0 +1,19 @@
+{
+	"all": true,
+	"check-coverage": false,
+	"reporter": ["text-summary", "lcov", "text", "html", "json"],
+	"require": [
+		"babel-register"
+	],
+	"sourceMap": true,
+	"instrument": false,
+	"exclude": [
+		"coverage",
+		"test",
+		"tests",
+		"resolvers/*/test",
+		"scripts",
+		"memo-parser",
+		"lib"
+	]
+}
diff --git a/resolvers/node/.nycrc b/resolvers/node/.nycrc
new file mode 100644
index 0000000000..1084360870
--- /dev/null
+++ b/resolvers/node/.nycrc
@@ -0,0 +1,15 @@
+{
+	"all": true,
+	"check-coverage": false,
+	"reporter": ["text-summary", "lcov", "text", "html", "json"],
+	"instrument": false,
+	"exclude": [
+		"coverage",
+		"test",
+		"tests",
+		"resolvers/*/test",
+		"scripts",
+		"memo-parser",
+		"lib"
+	]
+}
diff --git a/resolvers/webpack/.nycrc b/resolvers/webpack/.nycrc
new file mode 100644
index 0000000000..1084360870
--- /dev/null
+++ b/resolvers/webpack/.nycrc
@@ -0,0 +1,15 @@
+{
+	"all": true,
+	"check-coverage": false,
+	"reporter": ["text-summary", "lcov", "text", "html", "json"],
+	"instrument": false,
+	"exclude": [
+		"coverage",
+		"test",
+		"tests",
+		"resolvers/*/test",
+		"scripts",
+		"memo-parser",
+		"lib"
+	]
+}
diff --git a/scripts/copyMetafiles.js b/scripts/copyMetafiles.js
index 6140bd2dc9..01ff4f36f2 100644
--- a/scripts/copyMetafiles.js
+++ b/scripts/copyMetafiles.js
@@ -5,7 +5,6 @@ import resolverDirectories from './resolverDirectories';
 const files = [
   'LICENSE',
   '.npmrc',
-  '.nycrc',
 ];
 
 const directories = [].concat(
diff --git a/utils/.nycrc b/utils/.nycrc
new file mode 100644
index 0000000000..1084360870
--- /dev/null
+++ b/utils/.nycrc
@@ -0,0 +1,15 @@
+{
+	"all": true,
+	"check-coverage": false,
+	"reporter": ["text-summary", "lcov", "text", "html", "json"],
+	"instrument": false,
+	"exclude": [
+		"coverage",
+		"test",
+		"tests",
+		"resolvers/*/test",
+		"scripts",
+		"memo-parser",
+		"lib"
+	]
+}

From 10913e7447956da08a5547c5b874eb1a489c549c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 8 Aug 2023 13:38:04 +1200
Subject: [PATCH 620/767] [resolvers] [*] [fix] restore node 6 compatibility

See 69fce5c5 and https://github.com/import-js/eslint-plugin-import/commit/8c155baaca39dc78c5a3a63ff1bdd53b58f343e0#r123814192
---
 .eslintrc                  | 50 +++++++++++++++++++-------------------
 resolvers/node/index.js    |  6 ++---
 resolvers/webpack/index.js |  8 +++---
 3 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 932055e8d4..3c9c658f2f 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -189,37 +189,17 @@
                 "no-console": "off",
             },
         },
-        {
-            "files": "resolvers/**",
-            "env": {
-                "es6": false,
-            },
-        },
-        {
-            "files": "resolvers/webpack/**",
-            "rules": {
-                "no-console": 1,
-                "prefer-template": 0,
-                "prefer-object-spread": 0,
-                "prefer-rest-params": 0,
-            },
-            "env": {
-                "es6": true,
-            },
-        },
         {
             "files": [
-                "resolvers/*/test/**/*",
+                "resolvers/**",
+                "utils/**",
             ],
             "env": {
-                "mocha": true,
-                "es6": false
+                "es6": false,
             },
-        },
-        {
-            "files": "utils/**",
             "parserOptions": {
-                "ecmaVersion": 6,
+                "sourceType": "module",
+                "ecmaVersion": 2016,
             },
             "rules": {
                 "comma-dangle": ["error", {
@@ -229,11 +209,31 @@
                     "exports": "always-multiline",
                     "functions": "never"
                 }],
+                "prefer-destructuring": "warn",
                 "prefer-object-spread": "off",
+                "prefer-rest-params": "off",
+                "prefer-spread": "warn",
                 "prefer-template": "off",
+            }
+        },
+        {
+            "files": [
+                "resolvers/webpack/**",
+                "utils/**",
+            ],
+            "rules": {
                 "no-console": 1,
             },
         },
+        {
+            "files": [
+                "resolvers/*/test/**/*",
+            ],
+            "env": {
+                "mocha": true,
+                "es6": false
+            },
+        },
         {
             "files": "tests/**",
             "env": {
diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index 212b3b16b5..7f207fbf31 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -29,14 +29,14 @@ exports.resolve = function (source, file, config) {
 };
 
 function opts(file, config, packageFilter) {
-  return { // more closely matches Node (#333)
+  return Object.assign({ // more closely matches Node (#333)
     // plus 'mjs' for native modules! (#939)
     extensions: ['.mjs', '.js', '.json', '.node'],
-    ...config,
+  }, config, {
     // path.resolve will handle paths relative to CWD
     basedir: path.dirname(path.resolve(file)),
     packageFilter,
-  };
+  });
 }
 
 function identity(x) { return x; }
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 836d90f97a..a9fc003813 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -270,18 +270,18 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
     makeRootPlugin(ModulesInRootPlugin, 'module', resolveConfig.root),
     new ModulesInDirectoriesPlugin(
       'module',
-      resolveConfig.modulesDirectories || resolveConfig.modules || ['web_modules', 'node_modules'],
+      resolveConfig.modulesDirectories || resolveConfig.modules || ['web_modules', 'node_modules']
     ),
     makeRootPlugin(ModulesInRootPlugin, 'module', resolveConfig.fallback),
     new ModuleAsFilePlugin('module'),
     new ModuleAsDirectoryPlugin('module'),
     new DirectoryDescriptionFilePlugin(
       'package.json',
-      ['module', 'jsnext:main'].concat(resolveConfig.packageMains || webpack1DefaultMains),
+      ['module', 'jsnext:main'].concat(resolveConfig.packageMains || webpack1DefaultMains)
     ),
     new DirectoryDefaultFilePlugin(['index']),
     new FileAppendPlugin(resolveConfig.extensions || ['', '.webpack.js', '.web.js', '.js']),
-    new ResultSymlinkPlugin(),
+    new ResultSymlinkPlugin()
   );
 
   const resolvePlugins = [];
@@ -419,7 +419,7 @@ function findConfigPath(configPath, packageDir) {
       }
 
       const maybePath = path.resolve(
-        path.join(packageDir, 'webpack.config' + maybeExtension),
+        path.join(packageDir, 'webpack.config' + maybeExtension)
       );
       if (fs.existsSync(maybePath)) {
         configPath = maybePath;

From 559480d4571c7fde70177bbe2de0a57090a1facb Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 8 Aug 2023 15:48:41 +1200
Subject: [PATCH 621/767] [resolvers/webpack] v0.13.4

---
 resolvers/webpack/CHANGELOG.md | 3 +++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 8a0784a500..d5723757f8 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## 0.13.4 - 2023-08-08
+ - [fix] restore node 6 compatibility
+
 ## 0.13.3 - 2023-08-05
  - [deps] update `is-core-module`, `resolve`, `semver`
  - [eslint] tighten up rules
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index f1592a5d61..0ae63cfdd4 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.3",
+  "version": "0.13.4",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From c7042539bc0faf9af57be4baee1e1f17fad17fdb Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 8 Aug 2023 15:49:58 +1200
Subject: [PATCH 622/767] [resolvers/node] v0.3.9

---
 resolvers/node/CHANGELOG.md | 3 +++
 resolvers/node/package.json | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/resolvers/node/CHANGELOG.md b/resolvers/node/CHANGELOG.md
index 1335cbedee..8e11359a92 100644
--- a/resolvers/node/CHANGELOG.md
+++ b/resolvers/node/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v0.3.9 - 2023-08-08
+ - [fix] restore node 6 compatibility
+
 ## v0.3.8 - 2023-08-05
  - [deps] update `is-core-module`, `resolve`
  - [eslint] tighten up rules
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index 33bf3b0102..bfaab40413 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-node",
-  "version": "0.3.8",
+  "version": "0.3.9",
   "description": "Node default behavior import resolution plugin for eslint-plugin-import.",
   "main": "index.js",
   "files": [

From 26ea4f865bbfa162c533e82171379b73249003b0 Mon Sep 17 00:00:00 2001
From: Bryan Mishkin <698306+bmish@users.noreply.github.com>
Date: Tue, 8 Aug 2023 10:11:09 +0800
Subject: [PATCH 623/767] [Docs] Add markdownlint

---
 .markdownlint.json                            | 10 +++
 .markdownlintignore                           |  2 +
 CONTRIBUTING.md                               | 20 +++---
 README.md                                     | 16 ++---
 docs/rules/consistent-type-specifier-style.md |  4 +-
 docs/rules/default.md                         |  9 +--
 docs/rules/dynamic-import-chunkname.md        |  5 ++
 docs/rules/export.md                          |  3 +-
 docs/rules/exports-last.md                    |  3 +-
 docs/rules/extensions.md                      | 10 +--
 docs/rules/first.md                           |  5 +-
 docs/rules/group-exports.md                   |  1 -
 docs/rules/max-dependencies.md                |  2 +
 docs/rules/named.md                           |  8 +--
 docs/rules/namespace.md                       |  9 ++-
 docs/rules/newline-after-import.md            |  7 ++-
 docs/rules/no-absolute-path.md                |  6 +-
 docs/rules/no-amd.md                          |  4 +-
 docs/rules/no-anonymous-default-export.md     |  2 +
 docs/rules/no-commonjs.md                     |  5 +-
 docs/rules/no-cycle.md                        |  7 +--
 docs/rules/no-deprecated.md                   | 19 +++---
 docs/rules/no-duplicates.md                   |  3 +
 docs/rules/no-empty-named-blocks.md           |  8 ++-
 docs/rules/no-extraneous-dependencies.md      |  6 +-
 docs/rules/no-import-module-exports.md        |  5 +-
 docs/rules/no-internal-modules.md             | 14 +++--
 docs/rules/no-mutable-exports.md              |  4 +-
 docs/rules/no-named-as-default-member.md      |  5 +-
 docs/rules/no-named-as-default.md             | 11 ++--
 docs/rules/no-named-default.md                |  3 +
 docs/rules/no-namespace.md                    |  4 +-
 docs/rules/no-nodejs-modules.md               |  4 +-
 docs/rules/no-relative-packages.md            |  7 ++-
 docs/rules/no-relative-parent-imports.md      | 63 ++++++++++---------
 docs/rules/no-restricted-paths.md             | 42 ++++++-------
 docs/rules/no-unassigned-import.md            |  9 ++-
 docs/rules/no-unresolved.md                   | 10 +--
 docs/rules/no-unused-modules.md               | 36 ++++++++---
 docs/rules/no-useless-path-segments.md        |  3 +-
 docs/rules/no-webpack-loader-syntax.md        |  1 +
 docs/rules/order.md                           | 43 +++++++------
 docs/rules/prefer-default-export.md           |  5 +-
 docs/rules/unambiguous.md                     |  7 ++-
 memo-parser/README.md                         |  4 +-
 package.json                                  |  3 +-
 resolvers/README.md                           | 23 ++++---
 resolvers/webpack/README.md                   |  4 +-
 48 files changed, 274 insertions(+), 210 deletions(-)
 create mode 100644 .markdownlint.json
 create mode 100644 .markdownlintignore

diff --git a/.markdownlint.json b/.markdownlint.json
new file mode 100644
index 0000000000..d179615f45
--- /dev/null
+++ b/.markdownlint.json
@@ -0,0 +1,10 @@
+{
+  "line-length": false,
+  "ul-indent": {
+    "start_indent": 1,
+    "start_indented": true
+  },
+  "ul-style": {
+    "style": "dash"
+  }
+}
diff --git a/.markdownlintignore b/.markdownlintignore
new file mode 100644
index 0000000000..6ed5b5b6ee
--- /dev/null
+++ b/.markdownlintignore
@@ -0,0 +1,2 @@
+CHANGELOG.md
+node_modules
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2a79e7139e..871e90ad8c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -6,15 +6,15 @@ Thanks for your interest in helping out! Here are a **few** _weird_ tricks to ~~
 
 When opening an [issue](#issues):
 
-- [ ] search open/closed issues
-- [ ] discuss bug/enhancement in new or old issue
+ - [ ] search open/closed issues
+ - [ ] discuss bug/enhancement in new or old issue
 
 [PR](#prs) time:
 
-- [ ] write tests
-- [ ] implement feature/fix bug
-- [ ] update docs
-- [ ] make a note in change log
+ - [ ] write tests
+ - [ ] implement feature/fix bug
+ - [ ] update docs
+ - [ ] make a note in change log
 
 Remember, you don't need to do it all yourself; any of these are helpful! 😎
 
@@ -22,10 +22,10 @@ Remember, you don't need to do it all yourself; any of these are helpful! 😎
 
 If you are new to `eslint`, below are a few resources that will help you to familiarize yourself with the project.
 
-- Watch [this presentation](https://www.youtube.com/watch?v=2W9tUnALrLg) to learn the fundamental concept of Abstract Syntax Trees (AST) and the way `eslint` works under the hood.
-- Familiarize yourself with the [AST explorer](https://astexplorer.net/) tool. Look into rules in `docs/rules`, create patterns in the rules, then analyze its AST.
-- Explore the blog posts on how to create a custom rule. [One blog post](https://blog.yonatan.dev/writing-a-custom-eslint-rule-to-spot-undeclared-props/). [Second blog post](https://betterprogramming.pub/creating-custom-eslint-rules-cdc579694608).
-- Read the official `eslint` [developer guide](https://eslint.org/docs/latest/developer-guide/architecture/).
+ - Watch [this presentation](https://www.youtube.com/watch?v=2W9tUnALrLg) to learn the fundamental concept of Abstract Syntax Trees (AST) and the way `eslint` works under the hood.
+ - Familiarize yourself with the [AST explorer](https://astexplorer.net/) tool. Look into rules in `docs/rules`, create patterns in the rules, then analyze its AST.
+ - Explore the blog posts on how to create a custom rule. [One blog post](https://blog.yonatan.dev/writing-a-custom-eslint-rule-to-spot-undeclared-props/). [Second blog post](https://betterprogramming.pub/creating-custom-eslint-rules-cdc579694608).
+ - Read the official `eslint` [developer guide](https://eslint.org/docs/latest/developer-guide/architecture/).
 
 ## Issues
 
diff --git a/README.md b/README.md
index ca99b8fafb..1baa0069b3 100644
--- a/README.md
+++ b/README.md
@@ -131,7 +131,7 @@ rules:
   # etc...
 ```
 
-# TypeScript
+## TypeScript
 
 You may use the following snippet or assemble your own config using the granular settings described below it.
 
@@ -154,7 +154,7 @@ settings:
 [`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser
 [`eslint-import-resolver-typescript`]: https://github.com/import-js/eslint-import-resolver-typescript
 
-# Resolvers
+## Resolvers
 
 With the advent of module bundlers and the current state of modules and module
 syntax specs, it's not always obvious where `import x from 'module'` should look
@@ -175,7 +175,7 @@ resolvers are just npm packages, so [third party packages are supported](https:/
 
 You can reference resolvers in several ways (in order of precedence):
 
-- as a conventional `eslint-import-resolver` name, like `eslint-import-resolver-foo`:
+ - as a conventional `eslint-import-resolver` name, like `eslint-import-resolver-foo`:
 
 ```yaml
 # .eslintrc.yml
@@ -195,7 +195,7 @@ module.exports = {
 }
 ```
 
-- with a full npm module name, like `my-awesome-npm-module`:
+ - with a full npm module name, like `my-awesome-npm-module`:
 
 ```yaml
 # .eslintrc.yml
@@ -214,7 +214,7 @@ module.exports = {
 }
 ```
 
-- with a filesystem path to resolver, defined in this example as a `computed property` name:
+ - with a filesystem path to resolver, defined in this example as a `computed property` name:
 
 ```js
 // .eslintrc.js
@@ -336,11 +336,11 @@ If you are using `yarn` PnP as your package manager, add the `.yarn` folder and
 
 Each item in this array is either a folder's name, its subpath, or its absolute prefix path:
 
-- `jspm_modules` will match any file or folder named `jspm_modules` or which has a direct or non-direct parent named `jspm_modules`, e.g. `/home/me/project/jspm_modules` or `/home/me/project/jspm_modules/some-pkg/index.js`.
+ - `jspm_modules` will match any file or folder named `jspm_modules` or which has a direct or non-direct parent named `jspm_modules`, e.g. `/home/me/project/jspm_modules` or `/home/me/project/jspm_modules/some-pkg/index.js`.
 
-- `packages/core` will match any path that contains these two segments, for example `/home/me/project/packages/core/src/utils.js`.
+ - `packages/core` will match any path that contains these two segments, for example `/home/me/project/packages/core/src/utils.js`.
 
-- `/home/me/project/packages` will only match files and directories inside this directory, and the directory itself.
+ - `/home/me/project/packages` will only match files and directories inside this directory, and the directory itself.
 
 Please note that incomplete names are not allowed here so `components` won't match `bower_components` and `packages/ui` won't match `packages/ui-utils` (but will match `packages/ui/utils`).
 
diff --git a/docs/rules/consistent-type-specifier-style.md b/docs/rules/consistent-type-specifier-style.md
index 54c09049ef..41d98e4e1f 100644
--- a/docs/rules/consistent-type-specifier-style.md
+++ b/docs/rules/consistent-type-specifier-style.md
@@ -37,8 +37,8 @@ This rule includes a fixer that will automatically convert your specifiers to th
 
 The rule accepts a single string option which may be one of:
 
-- `'prefer-inline'` - enforces that named type-only specifiers are only ever written with an inline marker; and never as part of a top-level, type-only import.
-- `'prefer-top-level'` - enforces that named type-only specifiers only ever written as part of a top-level, type-only import; and never with an inline marker.
+ - `'prefer-inline'` - enforces that named type-only specifiers are only ever written with an inline marker; and never as part of a top-level, type-only import.
+ - `'prefer-top-level'` - enforces that named type-only specifiers only ever written as part of a top-level, type-only import; and never with an inline marker.
 
 By default the rule will use the `prefer-inline` option.
 
diff --git a/docs/rules/default.md b/docs/rules/default.md
index ffbbdc166a..9f8c919bf3 100644
--- a/docs/rules/default.md
+++ b/docs/rules/default.md
@@ -19,7 +19,6 @@ A module path that is [ignored] or not [unambiguously an ES module] will not be
 [ignored]: ../README.md#importignore
 [unambiguously an ES module]: https://github.com/bmeck/UnambiguousJavaScriptGrammar
 
-
 ## Rule Details
 
 Given:
@@ -54,7 +53,6 @@ import bar from './bar' // no default export found in ./bar
 import baz from './baz' // no default export found in ./baz
 ```
 
-
 ## When Not To Use It
 
 If you are using CommonJS and/or modifying the exported namespace of any module at
@@ -65,10 +63,9 @@ either, so such a situation will be reported in the importing module.
 
 ## Further Reading
 
-- Lee Byron's [ES7] export proposal
-- [`import/ignore`] setting
-- [`jsnext:main`] (Rollup)
-
+ - Lee Byron's [ES7] export proposal
+ - [`import/ignore`] setting
+ - [`jsnext:main`] (Rollup)
 
 [ES7]: https://github.com/leebyron/ecmascript-more-export-from
 [`import/ignore`]: ../../README.md#importignore
diff --git a/docs/rules/dynamic-import-chunkname.md b/docs/rules/dynamic-import-chunkname.md
index 472a366485..35ae9df516 100644
--- a/docs/rules/dynamic-import-chunkname.md
+++ b/docs/rules/dynamic-import-chunkname.md
@@ -7,8 +7,10 @@ This rule reports any dynamic imports without a webpackChunkName specified in a
 This rule enforces naming of webpack chunks in dynamic imports. When you don't explicitly name chunks, webpack will autogenerate chunk names that are not consistent across builds, which prevents long-term browser caching.
 
 ## Rule Details
+
 This rule runs against `import()` by default, but can be configured to also run against an alternative dynamic-import function, e.g. 'dynamicImport.'
 You can also configure the regex format you'd like to accept for the webpackChunkName - for example, if we don't want the number 6 to show up in our chunk names:
+
  ```javascript
 {
   "dynamic-import-chunkname": [2, {
@@ -19,6 +21,7 @@ You can also configure the regex format you'd like to accept for the webpackChun
 ```
 
 ### invalid
+
 The following patterns are invalid:
 
 ```javascript
@@ -53,7 +56,9 @@ import(
   'someModule',
 );
 ```
+
 ### valid
+
 The following patterns are valid:
 
 ```javascript
diff --git a/docs/rules/export.md b/docs/rules/export.md
index 115d2d8b29..54a8a39cf3 100644
--- a/docs/rules/export.md
+++ b/docs/rules/export.md
@@ -17,6 +17,7 @@ export default makeClass // Multiple default exports.
 ```
 
 or
+
 ```js
 export const foo = function () { /*...*/ } // Multiple exports of name 'foo'.
 
@@ -31,6 +32,6 @@ intent to rename, etc.
 
 ## Further Reading
 
-- Lee Byron's [ES7] export proposal
+ - Lee Byron's [ES7] export proposal
 
 [ES7]: https://github.com/leebyron/ecmascript-more-export-from
diff --git a/docs/rules/exports-last.md b/docs/rules/exports-last.md
index 6b3e4bac40..56e947e94b 100644
--- a/docs/rules/exports-last.md
+++ b/docs/rules/exports-last.md
@@ -4,7 +4,6 @@
 
 This rule enforces that all exports are declared at the bottom of the file. This rule will report any export declarations that comes before any non-export statements.
 
-
 ## This will be reported
 
 ```JS
@@ -45,7 +44,7 @@ export const str = 'foo'
 
 If you don't mind exports being sprinkled throughout a file, you may not want to enable this rule.
 
-#### ES6 exports only
+### ES6 exports only
 
 The exports-last rule is currently only working on ES6 exports. You may not want to enable this rule if you're using CommonJS exports.
 
diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md
index df4f341287..946ccb7bf8 100644
--- a/docs/rules/extensions.md
+++ b/docs/rules/extensions.md
@@ -10,13 +10,13 @@ In order to provide a consistent use of file extensions across your code base, t
 
 This rule either takes one string option, one object option, or a string and an object option. If it is the string `"never"` (the default value), then the rule forbids the use for any extension. If it is the string `"always"`, then the rule enforces the use of extensions for all import statements. If it is the string `"ignorePackages"`, then the rule enforces the use of extensions for all import statements except package imports.
 
-```
+```json
 "import/extensions": [<severity>, "never" | "always" | "ignorePackages"]
 ```
 
 By providing an object you can configure each extension separately.
 
-```
+```json
 "import/extensions": [<severity>, {
   <extension>: "never" | "always" | "ignorePackages"
 }]
@@ -26,7 +26,7 @@ By providing an object you can configure each extension separately.
 
 By providing both a string and an object, the string will set the default setting for all extensions, and the object can be used to set granular overrides for specific extensions.
 
-```
+```json
 "import/extensions": [
   <severity>,
   "never" | "always" | "ignorePackages",
@@ -40,7 +40,7 @@ For example, `["error", "never", { "svg": "always" }]` would require that all ex
 
 `ignorePackages` can be set as a separate boolean option like this:
 
-```
+```json
 "import/extensions": [
   <severity>,
   "never" | "always" | "ignorePackages",
@@ -62,7 +62,7 @@ When disallowing the use of certain extensions this rule makes an exception and
 
 For example, given the following folder structure:
 
-```
+```pt
 ├── foo
 │   ├── bar.js
 │   ├── bar.json
diff --git a/docs/rules/first.md b/docs/rules/first.md
index 21904e2fa1..c765a29739 100644
--- a/docs/rules/first.md
+++ b/docs/rules/first.md
@@ -57,6 +57,7 @@ Given that, see [#255] for the reasoning.
 ### With Fixer
 
 This rule contains a fixer to reorder in-body import to top, the following criteria applied:
+
 1. Never re-order relative to each other, even if `absolute-first` is set.
 2. If an import creates an identifier, and that identifier is referenced at module level *before* the import itself, that won't be re-ordered.
 
@@ -67,8 +68,8 @@ enable this rule.
 
 ## Further Reading
 
-- [`import/order`]: a major step up from `absolute-first`
-- Issue [#255]
+ - [`import/order`]: a major step up from `absolute-first`
+ - Issue [#255]
 
 [`import/order`]: ./order.md
 [#255]: https://github.com/import-js/eslint-plugin-import/issues/255
diff --git a/docs/rules/group-exports.md b/docs/rules/group-exports.md
index 67e76de2fe..9fb212de6a 100644
--- a/docs/rules/group-exports.md
+++ b/docs/rules/group-exports.md
@@ -71,7 +71,6 @@ export {first}
 export type {firstType}
 ```
 
-
 ### Invalid
 
 ```js
diff --git a/docs/rules/max-dependencies.md b/docs/rules/max-dependencies.md
index 1da74f6818..1ecbca64d3 100644
--- a/docs/rules/max-dependencies.md
+++ b/docs/rules/max-dependencies.md
@@ -47,6 +47,7 @@ Ignores `type` imports. Type imports are a feature released in TypeScript 3.8, y
 
 Given `{"max": 2, "ignoreTypeImports": true}`:
 
+<!-- markdownlint-disable-next-line MD024 -- duplicate header -->
 ### Fail
 
 ```ts
@@ -55,6 +56,7 @@ import b from './b';
 import c from './c';
 ```
 
+<!-- markdownlint-disable-next-line MD024 -- duplicate header -->
 ### Pass
 
 ```ts
diff --git a/docs/rules/named.md b/docs/rules/named.md
index 6d376defac..44f8dc6584 100644
--- a/docs/rules/named.md
+++ b/docs/rules/named.md
@@ -18,7 +18,6 @@ A module path that is [ignored] or not [unambiguously an ES module] will not be
 [unambiguously an ES module]: https://github.com/bmeck/UnambiguousJavaScriptGrammar
 [Flow]: https://flow.org/
 
-
 ## Rule Details
 
 Given:
@@ -94,10 +93,9 @@ runtime, you will likely see false positives with this rule.
 
 ## Further Reading
 
-- [`import/ignore`] setting
-- [`jsnext:main`] deprecation
-- [`pkg.module`] (Rollup)
-
+ - [`import/ignore`] setting
+ - [`jsnext:main`] deprecation
+ - [`pkg.module`] (Rollup)
 
 [`jsnext:main`]: https://github.com/jsforum/jsforum/issues/5
 [`pkg.module`]: https://github.com/rollup/rollup/wiki/pkg.module
diff --git a/docs/rules/namespace.md b/docs/rules/namespace.md
index 5ac25b750d..1a177f5819 100644
--- a/docs/rules/namespace.md
+++ b/docs/rules/namespace.md
@@ -30,6 +30,7 @@ redefinition of the namespace in an intermediate scope. Adherence to the ESLint
 For [ES7], reports if an exported namespace would be empty (no names exported from the referenced module.)
 
 Given:
+
 ```js
 // @module ./named-exports
 export const a = 1
@@ -44,7 +45,9 @@ export class ExportedClass { }
 // ES7
 export * as deep from './deep'
 ```
+
 and:
+
 ```js
 // @module ./deep
 export const e = "MC2"
@@ -94,9 +97,9 @@ still can't be statically analyzed any further.
 
 ## Further Reading
 
-- Lee Byron's [ES7] export proposal
-- [`import/ignore`] setting
-- [`jsnext:main`](Rollup)
+ - Lee Byron's [ES7] export proposal
+ - [`import/ignore`] setting
+ - [`jsnext:main`](Rollup)
 
 [ES7]: https://github.com/leebyron/ecmascript-more-export-from
 [`import/ignore`]: ../../README.md#importignore
diff --git a/docs/rules/newline-after-import.md b/docs/rules/newline-after-import.md
index 6aa75be552..fec6b23aca 100644
--- a/docs/rules/newline-after-import.md
+++ b/docs/rules/newline-after-import.md
@@ -9,9 +9,10 @@ Enforces having one or more empty lines after the last top-level import statemen
 ## Rule Details
 
 This rule supports the following options:
-- `count` which sets the number of newlines that are enforced after the last top-level import statement or require call. This option defaults to `1`.
 
-- `considerComments` which enforces the rule on comments after the last import-statement as well when set to true. This option defaults to `false`.
+ - `count` which sets the number of newlines that are enforced after the last top-level import statement or require call. This option defaults to `1`.
+
+ - `considerComments` which enforces the rule on comments after the last import-statement as well when set to true. This option defaults to `false`.
 
 Valid:
 
@@ -103,6 +104,7 @@ const FOO = 'BAR'
 ```
 
 ## Example options usage
+
 ```json
 {
   "rules": {
@@ -111,7 +113,6 @@ const FOO = 'BAR'
 }
 ```
 
-
 ## When Not To Use It
 
 If you like to visually group module imports with its usage, you don't want to use this rule.
diff --git a/docs/rules/no-absolute-path.md b/docs/rules/no-absolute-path.md
index a796f9d574..48fb9532bd 100644
--- a/docs/rules/no-absolute-path.md
+++ b/docs/rules/no-absolute-path.md
@@ -38,9 +38,9 @@ By default, only ES6 imports and CommonJS `require` calls will have this rule en
 
 You may provide an options object providing true/false for any of
 
-- `esmodule`: defaults to `true`
-- `commonjs`: defaults to `true`
-- `amd`: defaults to `false`
+ - `esmodule`: defaults to `true`
+ - `commonjs`: defaults to `true`
+ - `amd`: defaults to `false`
 
 If `{ amd: true }` is provided, dependency paths for AMD-style `define` and `require`
 calls will be resolved:
diff --git a/docs/rules/no-amd.md b/docs/rules/no-amd.md
index 155c19b3ca..6e592ba758 100644
--- a/docs/rules/no-amd.md
+++ b/docs/rules/no-amd.md
@@ -33,5 +33,5 @@ Special thanks to @xjamundx for donating his no-define rule as a start to this.
 
 ## Further Reading
 
-- [`no-commonjs`](./no-commonjs.md): report CommonJS `require` and `exports`
-- Source: https://github.com/xjamundx/eslint-plugin-modules
+ - [`no-commonjs`](./no-commonjs.md): report CommonJS `require` and `exports`
+ - Source: <https://github.com/xjamundx/eslint-plugin-modules>
diff --git a/docs/rules/no-anonymous-default-export.md b/docs/rules/no-anonymous-default-export.md
index d3c88f94e0..70efb84501 100644
--- a/docs/rules/no-anonymous-default-export.md
+++ b/docs/rules/no-anonymous-default-export.md
@@ -28,6 +28,7 @@ The complete default configuration looks like this.
 ## Rule Details
 
 ### Fail
+
 ```js
 export default []
 
@@ -48,6 +49,7 @@ export default new Foo()
 ```
 
 ### Pass
+
 ```js
 const foo = 123
 export default foo
diff --git a/docs/rules/no-commonjs.md b/docs/rules/no-commonjs.md
index 09a6b44010..4dc9c8c5d9 100644
--- a/docs/rules/no-commonjs.md
+++ b/docs/rules/no-commonjs.md
@@ -86,12 +86,11 @@ don't want this rule.
 It is also fairly noisy if you have a larger codebase that is being transitioned
 from CommonJS to ES6 modules.
 
-
 ## Contributors
 
 Special thanks to @xjamundx for donating the module.exports and exports.* bits.
 
 ## Further Reading
 
-- [`no-amd`](./no-amd.md): report on AMD `require`, `define`
-- Source: https://github.com/xjamundx/eslint-plugin-modules
+ - [`no-amd`](./no-amd.md): report on AMD `require`, `define`
+ - Source: <https://github.com/xjamundx/eslint-plugin-modules>
diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md
index 6635ba73f0..76e96f95f2 100644
--- a/docs/rules/no-cycle.md
+++ b/docs/rules/no-cycle.md
@@ -24,7 +24,6 @@ for that, see [`no-self-import`].
 
 This rule ignores type-only imports in Flow and TypeScript syntax (`import type` and `import typeof`), which have no runtime effect.
 
-
 ## Rule Details
 
 ### Options
@@ -103,9 +102,9 @@ this rule enabled.
 
 ## Further Reading
 
-- [Original inspiring issue](https://github.com/import-js/eslint-plugin-import/issues/941)
-- Rule to detect that module imports itself: [`no-self-import`]
-- [`import/external-module-folders`] setting
+ - [Original inspiring issue](https://github.com/import-js/eslint-plugin-import/issues/941)
+ - Rule to detect that module imports itself: [`no-self-import`]
+ - [`import/external-module-folders`] setting
 
 [`no-self-import`]: ./no-self-import.md
 
diff --git a/docs/rules/no-deprecated.md b/docs/rules/no-deprecated.md
index 641fc1a8f4..a647d77ad5 100644
--- a/docs/rules/no-deprecated.md
+++ b/docs/rules/no-deprecated.md
@@ -3,7 +3,7 @@
 <!-- end auto-generated rule header -->
 
 Reports use of a deprecated name, as indicated by a JSDoc block with a `@deprecated`
-tag or TomDoc `Deprecated: ` comment.
+tag or TomDoc `Deprecated:` comment.
 
 using a JSDoc `@deprecated` tag:
 
@@ -45,19 +45,18 @@ export function multiply(six, nine) {
 Only JSDoc is enabled by default. Other documentation styles can be enabled with
 the `import/docstyle` setting.
 
-
 ```yaml
 # .eslintrc.yml
 settings:
   import/docstyle: ['jsdoc', 'tomdoc']
 ```
 
-### Worklist
+## Worklist
 
-- [x] report explicit imports on the import node
-- [x] support namespaces
-  - [x] should bubble up through deep namespaces (#157)
-- [x] report explicit imports at reference time (at the identifier) similar to namespace
-- [x] mark module deprecated if file JSDoc has a @deprecated tag?
-- [ ] don't flag redeclaration of imported, deprecated names
-- [ ] flag destructuring
+ - [x] report explicit imports on the import node
+ - [x] support namespaces
+   - [x] should bubble up through deep namespaces (#157)
+ - [x] report explicit imports at reference time (at the identifier) similar to namespace
+ - [x] mark module deprecated if file JSDoc has a @deprecated tag?
+ - [ ] don't flag redeclaration of imported, deprecated names
+ - [ ] flag destructuring
diff --git a/docs/rules/no-duplicates.md b/docs/rules/no-duplicates.md
index 50f779b456..29c16f15d1 100644
--- a/docs/rules/no-duplicates.md
+++ b/docs/rules/no-duplicates.md
@@ -17,6 +17,7 @@ is different in two key ways:
 ## Rule Details
 
 Valid:
+
 ```js
 import SomeDefaultClass, * as names from './mod'
 // Flow `type` import from same module is fine
@@ -52,6 +53,7 @@ Config:
 ```
 
 And then the following code becomes valid:
+
 ```js
 import minifiedMod from './mod?minify'
 import noCommentsMod from './mod?comments=0'
@@ -59,6 +61,7 @@ import originalMod from './mod'
 ```
 
 It will still catch duplicates when using the same module and the exact same query string:
+
 ```js
 import SomeDefaultClass from './mod?minify'
 
diff --git a/docs/rules/no-empty-named-blocks.md b/docs/rules/no-empty-named-blocks.md
index 7bf4d695cf..85821d8afe 100644
--- a/docs/rules/no-empty-named-blocks.md
+++ b/docs/rules/no-empty-named-blocks.md
@@ -9,35 +9,41 @@ Reports the use of empty named import blocks.
 ## Rule Details
 
 ### Valid
+
 ```js
 import { mod } from 'mod'
 import Default, { mod } from 'mod'
 ```
 
 When using typescript
+
 ```js
 import type { mod } from 'mod'
 ```
 
 When using flow
+
 ```js
 import typeof { mod } from 'mod'
 ```
 
 ### Invalid
+
 ```js
 import {} from 'mod'
 import Default, {} from 'mod'
 ```
 
 When using typescript
+
 ```js
 import type Default, {} from 'mod'
 import type {} from 'mod'
 ```
 
 When using flow
+
 ```js
 import typeof {} from 'mod'
 import typeof Default, {} from 'mod'
-```
\ No newline at end of file
+```
diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index 660875d1da..547e5c2e57 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -7,7 +7,7 @@ The closest parent `package.json` will be used. If no `package.json` is found, t
 
 Modules have to be installed for this rule to work.
 
-### Options
+## Options
 
 This rule supports the following options:
 
@@ -60,6 +60,7 @@ folder layouts:
 ## Rule Details
 
 Given the following `package.json`:
+
 ```json
 {
   "name": "my-project",
@@ -88,7 +89,6 @@ Given the following `package.json`:
 }
 ```
 
-
 ## Fail
 
 ```js
@@ -117,7 +117,6 @@ var foo = require('./foo');
 import type { MyType } from 'foo';
 ```
 
-
 ## Pass
 
 ```js
@@ -135,7 +134,6 @@ import type { MyType } from 'foo';
 import react from 'react';
 ```
 
-
 ## When Not To Use It
 
 If you do not have a `package.json` file in your project.
diff --git a/docs/rules/no-import-module-exports.md b/docs/rules/no-import-module-exports.md
index 08aacfcc34..1c57226495 100644
--- a/docs/rules/no-import-module-exports.md
+++ b/docs/rules/no-import-module-exports.md
@@ -12,7 +12,8 @@ If you have multiple entry points or are using `js:next` this rule includes an
 
 ## Options
 
-#### `exceptions`
+### `exceptions`
+
  - An array of globs. The rule will be omitted from any file that matches a glob
    in the options array. For example, the following setting will omit the rule
    in the `some-file.js` file.
@@ -43,6 +44,7 @@ console.log(baz)
 ```
 
 ### Pass
+
 Given the following package.json:
 
 ```json
@@ -75,4 +77,5 @@ module.exports = foo;
 ```
 
 ### Further Reading
+
  - [webpack issue #4039](https://github.com/webpack/webpack/issues/4039)
diff --git a/docs/rules/no-internal-modules.md b/docs/rules/no-internal-modules.md
index 47f7490da6..433b55140d 100644
--- a/docs/rules/no-internal-modules.md
+++ b/docs/rules/no-internal-modules.md
@@ -8,14 +8,14 @@ Use this rule to prevent importing the submodules of other modules.
 
 This rule has two mutally exclusive options that are arrays of [minimatch/glob patterns](https://github.com/isaacs/node-glob#glob-primer) patterns:
 
-- `allow` that include paths and import statements that can be imported with reaching.
-- `forbid` that exclude paths and import statements that can be imported with reaching.
+ - `allow` that include paths and import statements that can be imported with reaching.
+ - `forbid` that exclude paths and import statements that can be imported with reaching.
 
 ### Examples
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 ├── actions
 │   └── getUser.js
@@ -33,7 +33,8 @@ my-project
 ```
 
 And the .eslintrc file:
-```
+
+```json
 {
   ...
   "rules": {
@@ -76,7 +77,7 @@ export { settings } from '../app';
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 ├── actions
 │   └── getUser.js
@@ -94,7 +95,8 @@ my-project
 ```
 
 And the .eslintrc file:
-```
+
+```json
 {
   ...
   "rules": {
diff --git a/docs/rules/no-mutable-exports.md b/docs/rules/no-mutable-exports.md
index f0a6251c19..ce51627858 100644
--- a/docs/rules/no-mutable-exports.md
+++ b/docs/rules/no-mutable-exports.md
@@ -43,8 +43,8 @@ export function getCount() {} // reported here: exported function is reassigned
 To prevent general reassignment of these identifiers, exported or not, you may
 want to enable the following core ESLint rules:
 
-- [no-func-assign]
-- [no-class-assign]
+ - [no-func-assign]
+ - [no-class-assign]
 
 [no-func-assign]: https://eslint.org/docs/rules/no-func-assign
 [no-class-assign]: https://eslint.org/docs/rules/no-class-assign
diff --git a/docs/rules/no-named-as-default-member.md b/docs/rules/no-named-as-default-member.md
index 5e0f5069e9..e8935fb7df 100644
--- a/docs/rules/no-named-as-default-member.md
+++ b/docs/rules/no-named-as-default-member.md
@@ -17,13 +17,12 @@ Furthermore, [in Babel 5 this is actually how things worked][blog]. This was
 fixed in Babel 6. Before upgrading an existing codebase to Babel 6, it can be
 useful to run this lint rule.
 
-
 [blog]: https://kentcdodds.com/blog/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution
 
-
 ## Rule Details
 
 Given:
+
 ```js
 // foo.js
 export default 'foo';
@@ -31,11 +30,13 @@ export const bar = 'baz';
 ```
 
 ...this would be valid:
+
 ```js
 import foo, {bar} from './foo.js';
 ```
 
 ...and the following would be reported:
+
 ```js
 // Caution: `foo` also has a named export `bar`.
 // Check if you meant to write `import {bar} from './foo.js'` instead.
diff --git a/docs/rules/no-named-as-default.md b/docs/rules/no-named-as-default.md
index b3715e6c44..043d699424 100644
--- a/docs/rules/no-named-as-default.md
+++ b/docs/rules/no-named-as-default.md
@@ -8,12 +8,13 @@ Reports use of an exported name as the locally imported name of a default export
 
 Rationale: using an exported name as the name of the default export is likely...
 
-- *misleading*: others familiar with `foo.js` probably expect the name to be `foo`
-- *a mistake*: only needed to import `bar` and forgot the brackets (the case that is prompting this)
+ - _misleading_: others familiar with `foo.js` probably expect the name to be `foo`
+ - _a mistake_: only needed to import `bar` and forgot the brackets (the case that is prompting this)
 
 ## Rule Details
 
 Given:
+
 ```js
 // foo.js
 export default 'foo';
@@ -21,11 +22,13 @@ export const bar = 'baz';
 ```
 
 ...this would be valid:
+
 ```js
 import foo from './foo.js';
 ```
 
 ...and this would be reported:
+
 ```js
 // message: Using exported name 'bar' as identifier for default export.
 import bar from './foo.js';
@@ -43,8 +46,8 @@ export bar from './foo.js';
 
 ## Further Reading
 
-- ECMAScript Proposal: [export ns from]
-- ECMAScript Proposal: [export default from]
+ - ECMAScript Proposal: [export ns from]
+ - ECMAScript Proposal: [export default from]
 
 [export ns from]: https://github.com/leebyron/ecmascript-export-ns-from
 [export default from]: https://github.com/leebyron/ecmascript-export-default-from
diff --git a/docs/rules/no-named-default.md b/docs/rules/no-named-default.md
index 2f3d54b807..05860cde1e 100644
--- a/docs/rules/no-named-default.md
+++ b/docs/rules/no-named-default.md
@@ -13,6 +13,7 @@ Note that type imports, as used by [Flow], are always ignored.
 ## Rule Details
 
 Given:
+
 ```js
 // foo.js
 export default 'foo';
@@ -20,12 +21,14 @@ export const bar = 'baz';
 ```
 
 ...these would be valid:
+
 ```js
 import foo from './foo.js';
 import foo, { bar } from './foo.js';
 ```
 
 ...and these would be reported:
+
 ```js
 // message: Using exported name 'bar' as identifier for default export.
 import { default as foo } from './foo.js';
diff --git a/docs/rules/no-namespace.md b/docs/rules/no-namespace.md
index 623dae049c..c7346515a5 100644
--- a/docs/rules/no-namespace.md
+++ b/docs/rules/no-namespace.md
@@ -8,11 +8,11 @@ Enforce a convention of not using namespace (a.k.a. "wildcard" `*`) imports.
 
 The rule is auto-fixable when the namespace object is only used for direct member access, e.g. `namespace.a`.
 
-### Options
+## Options
 
 This rule supports the following options:
 
-- `ignore`: array of glob strings for modules that should be ignored by the rule.
+ - `ignore`: array of glob strings for modules that should be ignored by the rule.
 
 ## Rule Details
 
diff --git a/docs/rules/no-nodejs-modules.md b/docs/rules/no-nodejs-modules.md
index 624c27e059..5cbc907286 100644
--- a/docs/rules/no-nodejs-modules.md
+++ b/docs/rules/no-nodejs-modules.md
@@ -4,11 +4,11 @@
 
 Forbid the use of Node.js builtin modules. Can be useful for client-side web projects that do not have access to those modules.
 
-### Options
+## Options
 
 This rule supports the following options:
 
-- `allow`: Array of names of allowed modules. Defaults to an empty array.
+ - `allow`: Array of names of allowed modules. Defaults to an empty array.
 
 ## Rule Details
 
diff --git a/docs/rules/no-relative-packages.md b/docs/rules/no-relative-packages.md
index df21c25dd0..4014ed9859 100644
--- a/docs/rules/no-relative-packages.md
+++ b/docs/rules/no-relative-packages.md
@@ -9,11 +9,11 @@ Use this rule to prevent importing packages through relative paths.
 It's useful in Yarn/Lerna workspaces, were it's possible to import a sibling
 package using `../package` relative path, while direct `package` is the correct one.
 
-### Examples
+## Examples
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 ├── packages
 │   ├── foo
@@ -26,7 +26,8 @@ my-project
 ```
 
 And the .eslintrc file:
-```
+
+```json
 {
   ...
   "rules": {
diff --git a/docs/rules/no-relative-parent-imports.md b/docs/rules/no-relative-parent-imports.md
index e5684eb1cf..c1f9784871 100644
--- a/docs/rules/no-relative-parent-imports.md
+++ b/docs/rules/no-relative-parent-imports.md
@@ -8,7 +8,7 @@ This rule is useful for enforcing tree-like folder structures instead of complex
 
 To fix violations of this rule there are three general strategies. Given this example:
 
-```
+```pt
 numbers
 └── three.js
 add.js
@@ -32,51 +32,51 @@ You can,
 
 1. Move the file to be in a sibling folder (or higher) of the dependency.
 
-`three.js` could be be in the same folder as `add.js`:
+   `three.js` could be be in the same folder as `add.js`:
 
-```
-three.js
-add.js
-```
+   ```pt
+   three.js
+   add.js
+   ```
 
-or since `add` doesn't have any imports, it could be in it's own directory (namespace):
+   or since `add` doesn't have any imports, it could be in it's own directory (namespace):
 
-```
-math
-└── add.js
-three.js
-```
+   ```pt
+   math
+   └── add.js
+   three.js
+   ```
 
 2. Pass the dependency as an argument at runtime (dependency injection)
 
-```js
-// three.js
-export default function three(add) {
-  return add([1, 2]);
-}
+   ```js
+   // three.js
+   export default function three(add) {
+     return add([1, 2]);
+   }
 
-// somewhere else when you use `three.js`:
-import add from './add';
-import three from './numbers/three';
-console.log(three(add));
-```
+   // somewhere else when you use `three.js`:
+   import add from './add';
+   import three from './numbers/three';
+   console.log(three(add));
+   ```
 
 3. Make the dependency a package so it's globally available to all files in your project:
 
-```js
-import add from 'add'; // from https://www.npmjs.com/package/add
-export default function three() {
-  return add([1,2]);
-}
-```
+   ```js
+   import add from 'add'; // from https://www.npmjs.com/package/add
+   export default function three() {
+     return add([1,2]);
+   }
+   ```
 
 These are (respectively) static, dynamic & global solutions to graph-like dependency resolution.
 
-### Examples
+## Examples
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 ├── lib
 │   ├── a.js
@@ -85,7 +85,8 @@ my-project
 ```
 
 And the .eslintrc file:
-```
+
+```json
 {
   ...
   "rules": {
diff --git a/docs/rules/no-restricted-paths.md b/docs/rules/no-restricted-paths.md
index 344c33bb67..293f3ba009 100644
--- a/docs/rules/no-restricted-paths.md
+++ b/docs/rules/no-restricted-paths.md
@@ -13,25 +13,26 @@ This rule has one option. The option is an object containing the definition of a
 The default value for `basePath` is the current working directory.
 
 Each zone consists of the `target` paths, a `from` paths, and an optional `except` and `message` attribute.
-- `target` contains the paths where the restricted imports should be applied. It can be expressed by
-    - directory string path that matches all its containing files
-    - glob pattern matching all the targeted files
-    - an array of multiple of the two types above
-- `from` paths define the folders that are not allowed to be used in an import. It can be expressed by
-    - directory string path that matches all its containing files
-    - glob pattern matching all the files restricted to be imported
-    - an array of multiple directory string path
-    - an array of multiple glob patterns
-- `except` may be defined for a zone, allowing exception paths that would otherwise violate the related `from`. Note that it does not alter the behaviour of `target` in any way.
-    - in case `from` contains only glob patterns, `except` must be an array of glob patterns as well
-    - in case `from` contains only directory path, `except` is relative to `from` and cannot backtrack to a parent directory
-- `message` - will be displayed in case of the rule violation.
+
+ - `target` contains the paths where the restricted imports should be applied. It can be expressed by
+   - directory string path that matches all its containing files
+   - glob pattern matching all the targeted files
+   - an array of multiple of the two types above
+ - `from` paths define the folders that are not allowed to be used in an import. It can be expressed by
+   - directory string path that matches all its containing files
+   - glob pattern matching all the files restricted to be imported
+   - an array of multiple directory string path
+   - an array of multiple glob patterns
+ - `except` may be defined for a zone, allowing exception paths that would otherwise violate the related `from`. Note that it does not alter the behaviour of `target` in any way.
+   - in case `from` contains only glob patterns, `except` must be an array of glob patterns as well
+   - in case `from` contains only directory path, `except` is relative to `from` and cannot backtrack to a parent directory
+ - `message` - will be displayed in case of the rule violation.
 
 ### Examples
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 ├── client
 │   └── foo.js
@@ -58,7 +59,7 @@ import baz from '../client/baz';
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 ├── client
 │   └── foo.js
@@ -74,7 +75,7 @@ and the current file being linted is `my-project/server/one/a.js`.
 
 and the current configuration is set to:
 
-```
+```json
 { "zones": [ {
     "target": "./tests/files/restricted-paths/server/one",
     "from": "./tests/files/restricted-paths/server",
@@ -99,7 +100,7 @@ import b from './b'
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 ├── client
     └── foo.js
@@ -111,7 +112,7 @@ my-project
 
 and the current configuration is set to:
 
-```
+```json
 { "zones": [ {
     "target": "./tests/files/restricted-paths/client/!(sub-module)/**/*",
     "from": "./tests/files/restricted-paths/client/sub-module/**/*",
@@ -134,7 +135,7 @@ import b from './baz'
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 └── one
    └── a.js
@@ -149,7 +150,7 @@ my-project
 
 and the current configuration is set to:
 
-```
+```json
 {
   "zones": [
     {
@@ -195,4 +196,3 @@ import a from '../one/a'
 ```js
 import a from './a'
 ```
-
diff --git a/docs/rules/no-unassigned-import.md b/docs/rules/no-unassigned-import.md
index 6f763e9737..617395e2c3 100644
--- a/docs/rules/no-unassigned-import.md
+++ b/docs/rules/no-unassigned-import.md
@@ -3,12 +3,13 @@
 <!-- end auto-generated rule header -->
 
 With both CommonJS' `require` and the ES6 modules' `import` syntax, it is possible to import a module but not to use its result. This can be done explicitly by not assigning the module to as variable. Doing so can mean either of the following things:
-- The module is imported but not used
-- The module has side-effects (like [`should`](https://www.npmjs.com/package/should)). Having side-effects, makes it hard to know whether the module is actually used or can be removed. It can also make it harder to test or mock parts of your application.
+
+ - The module is imported but not used
+ - The module has side-effects (like [`should`](https://www.npmjs.com/package/should)). Having side-effects, makes it hard to know whether the module is actually used or can be removed. It can also make it harder to test or mock parts of your application.
 
 This rule aims to remove modules with side-effects by reporting when a module is imported but not assigned.
 
-### Options
+## Options
 
 This rule supports the following option:
 
@@ -16,7 +17,6 @@ This rule supports the following option:
 
 Note that the globs start from the where the linter is executed (usually project root), but not from each file that includes the source. Learn more in both the pass and fail examples below.
 
-
 ## Fail
 
 ```js
@@ -28,7 +28,6 @@ import '../styles/app.css'
 // {"allow": ["styles/*.css"]}
 ```
 
-
 ## Pass
 
 ```js
diff --git a/docs/rules/no-unresolved.md b/docs/rules/no-unresolved.md
index 13f7928877..ca1da39c00 100644
--- a/docs/rules/no-unresolved.md
+++ b/docs/rules/no-unresolved.md
@@ -50,6 +50,7 @@ const { default: x } = require('./foo') // ignored
 ```
 
 Both may be provided, too:
+
 ```js
 /*eslint import/no-unresolved: [2, { commonjs: true, amd: true }]*/
 const { default: x } = require('./foo') // reported if './foo' is not found
@@ -84,7 +85,6 @@ const { default: x } = require('./foo') // reported if './foo' is actually './Fo
 
 The `caseSensitive` option does not detect case for the current working directory. The `caseSensitiveStrict` option allows checking `cwd` in resolved path. By default, the option is disabled.
 
-
 ```js
 /*eslint import/no-unresolved: [2, { caseSensitiveStrict: true }]*/
 
@@ -102,9 +102,9 @@ If you're using a module bundler other than Node or Webpack, you may end up with
 
 ## Further Reading
 
-- [Resolver plugins](../../README.md#resolvers)
-- [Node resolver](https://npmjs.com/package/eslint-import-resolver-node) (default)
-- [Webpack resolver](https://npmjs.com/package/eslint-import-resolver-webpack)
-- [`import/ignore`] global setting
+ - [Resolver plugins](../../README.md#resolvers)
+ - [Node resolver](https://npmjs.com/package/eslint-import-resolver-node) (default)
+ - [Webpack resolver](https://npmjs.com/package/eslint-import-resolver-webpack)
+ - [`import/ignore`] global setting
 
 [`import/ignore`]: ../../README.md#importignore
diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index a8e1a3c182..53c2479272 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -3,19 +3,20 @@
 <!-- end auto-generated rule header -->
 
 Reports:
-  - modules without any exports
-  - individual exports not being statically `import`ed or `require`ed from other modules in the same project
-  - dynamic imports are supported if argument is a literal string
 
+ - modules without any exports
+ - individual exports not being statically `import`ed or `require`ed from other modules in the same project
+ - dynamic imports are supported if argument is a literal string
 
 ## Rule Details
 
 ### Usage
 
-In order for this plugin to work, at least one of the options `missingExports` or `unusedExports` must be enabled (see "Options" section below). In the future, these options will be enabled by default (see https://github.com/import-js/eslint-plugin-import/issues/1324)
+In order for this plugin to work, at least one of the options `missingExports` or `unusedExports` must be enabled (see "Options" section below). In the future, these options will be enabled by default (see <https://github.com/import-js/eslint-plugin-import/issues/1324>)
 
 Example:
-```
+
+```json
 "rules: {
   ...otherRules,
   "import/no-unused-modules": [1, {"unusedExports": true}]
@@ -26,14 +27,15 @@ Example:
 
 This rule takes the following option:
 
-- **`missingExports`**: if `true`, files without any exports are reported (defaults to `false`)
-- **`unusedExports`**: if `true`, exports without any static usage within other modules are reported (defaults to `false`)
-- `src`: an array with files/paths to be analyzed. It only applies to unused exports. Defaults to `process.cwd()`, if not provided
-- `ignoreExports`: an array with files/paths for which unused exports will not be reported (e.g module entry points in a published package)
-
+ - **`missingExports`**: if `true`, files without any exports are reported (defaults to `false`)
+ - **`unusedExports`**: if `true`, exports without any static usage within other modules are reported (defaults to `false`)
+ - `src`: an array with files/paths to be analyzed. It only applies to unused exports. Defaults to `process.cwd()`, if not provided
+ - `ignoreExports`: an array with files/paths for which unused exports will not be reported (e.g module entry points in a published package)
 
 ### Example for missing exports
+
 #### The following will be reported
+
 ```js
 const class MyClass { /*...*/ }
 
@@ -45,18 +47,23 @@ function makeClass() { return new MyClass(...arguments) }
 ```js
 export default function () { /*...*/ }
 ```
+
 ```js
 export const foo = function () { /*...*/ }
 ```
+
 ```js
 export { foo, bar }
 ```
+
 ```js
 export { foo as bar }
 ```
 
 ### Example for unused exports
+
 given file-f:
+
 ```js
 import { e } from 'file-a'
 import { f } from 'file-b'
@@ -65,24 +72,32 @@ export { default, i0 } from 'file-d' // both will be reported
 
 export const j = 99 // will be reported
 ```
+
 and file-d:
+
 ```js
 export const i0 = 9 // will not be reported
 export const i1 = 9 // will be reported
 export default () => {} // will not be reported
 ```
+
 and file-c:
+
 ```js
 export const h = 8 // will not be reported
 export default () => {} // will be reported, as export * only considers named exports and ignores default exports
 ```
+
 and file-b:
+
 ```js
 import two, { b, c, doAnything } from 'file-a'
 
 export const f = 6 // will not be reported
 ```
+
 and file-a:
+
 ```js
 const b = 2
 const c = 3
@@ -102,6 +117,7 @@ export default 5 // will not be reported
 ```
 
 #### Important Note
+
 Exports from files listed as a main file (`main`, `browser`, or `bin` fields in `package.json`) will be ignored by default. This only applies if the `package.json` is not set to `private: true`
 
 ## When not to use
diff --git a/docs/rules/no-useless-path-segments.md b/docs/rules/no-useless-path-segments.md
index c8dc67727a..22c4bf965b 100644
--- a/docs/rules/no-useless-path-segments.md
+++ b/docs/rules/no-useless-path-segments.md
@@ -10,7 +10,7 @@ Use this rule to prevent unnecessary path segments in import and require stateme
 
 Given the following folder structure:
 
-```
+```pt
 my-project
 ├── app.js
 ├── footer.js
@@ -62,6 +62,7 @@ import fs from "fs";
 ### noUselessIndex
 
 If you want to detect unnecessary `/index` or `/index.js` (depending on the specified file extensions, see below) imports in your paths, you can enable the option `noUselessIndex`. By default it is set to `false`:
+
 ```js
 "import/no-useless-path-segments": ["error", {
   noUselessIndex: true,
diff --git a/docs/rules/no-webpack-loader-syntax.md b/docs/rules/no-webpack-loader-syntax.md
index e1b7a4bd9d..291b1c058a 100644
--- a/docs/rules/no-webpack-loader-syntax.md
+++ b/docs/rules/no-webpack-loader-syntax.md
@@ -5,6 +5,7 @@
 Forbid Webpack loader syntax in imports.
 
 [Webpack](https://webpack.js.org) allows specifying the [loaders](https://webpack.js.org/concepts/loaders/) to use in the import source string using a special syntax like this:
+
 ```js
 var moduleWithOneLoader = require("my-loader!./my-awesome-module");
 ```
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 6dc4520e8d..2335699e6c 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -36,7 +36,6 @@ Unassigned imports are ignored, as the order they are imported in may be importa
 
 Statements using the ES6 `import` syntax must appear before any `require()` statements.
 
-
 ## Fail
 
 ```ts
@@ -54,7 +53,6 @@ var path = require('path');
 import foo from './foo'; // `import` statements must be before `require` statement
 ```
 
-
 ## Pass
 
 ```ts
@@ -83,11 +81,12 @@ var path = require('path');
 
 This rule supports the following options:
 
-### `groups: [array]`:
+### `groups: [array]`
 
 How groups are defined, and the order to respect. `groups` must be an array of `string` or [`string`]. The only allowed `string`s are:
 `"builtin"`, `"external"`, `"internal"`, `"unknown"`, `"parent"`, `"sibling"`, `"index"`, `"object"`, `"type"`.
 The enforced order is the same as the order of each element in a group. Omitted types are implicitly grouped together as the last element. Example:
+
 ```ts
 [
   'builtin', // Built-in types are first
@@ -97,6 +96,7 @@ The enforced order is the same as the order of each element in a group. Omitted
   // Then the rest: internal and external type
 ]
 ```
+
 The default value is `["builtin", "external", "parent", "sibling", "index"]`.
 
 You can set the options like this:
@@ -119,7 +119,7 @@ You can set the options like this:
 ]
 ```
 
-### `pathGroups: [array of objects]`:
+### `pathGroups: [array of objects]`
 
 To be able to group by paths mostly needed with aliases pathGroups can be defined.
 
@@ -145,7 +145,7 @@ Properties of the objects
 }
 ```
 
-### `distinctGroup: [boolean]`:
+### `distinctGroup: [boolean]`
 
 This changes how `pathGroups[].position` affects grouping. The property is most useful when `newlines-between` is set to `always` and at least 1 `pathGroups` entry has a `position` property set.
 
@@ -154,6 +154,7 @@ By default, in the context of a particular `pathGroup` entry, when setting `posi
 Note that currently, `distinctGroup` defaults to `true`. However, in a later update, the default will change to `false`
 
 Example:
+
 ```json
 {
   "import/order": ["error", {
@@ -170,12 +171,13 @@ Example:
 }
 ```
 
-### `pathGroupsExcludedImportTypes: [array]`:
+### `pathGroupsExcludedImportTypes: [array]`
 
 This defines import types that are not handled by configured pathGroups.
 This is mostly needed when you want to handle path groups that look like external imports.
 
 Example:
+
 ```json
 {
   "import/order": ["error", {
@@ -194,6 +196,7 @@ Example:
 You can also use `patterns`(e.g., `react`, `react-router-dom`, etc).
 
 Example:
+
 ```json
 {
   "import/order": [
@@ -211,16 +214,17 @@ Example:
   ]
 }
 ```
+
 The default value is `["builtin", "external", "object"]`.
 
-### `newlines-between: [ignore|always|always-and-inside-groups|never]`:
+### `newlines-between: [ignore|always|always-and-inside-groups|never]`
 
 Enforces or forbids new lines between import groups:
 
-- If set to `ignore`, no errors related to new lines between import groups will be reported.
-- If set to `always`, at least one new line between each group will be enforced, and new lines inside a group will be forbidden. To prevent multiple lines between imports, core `no-multiple-empty-lines` rule can be used.
-- If set to `always-and-inside-groups`, it will act like `always` except newlines are allowed inside import groups.
-- If set to `never`, no new lines are allowed in the entire import section.
+ - If set to `ignore`, no errors related to new lines between import groups will be reported.
+ - If set to `always`, at least one new line between each group will be enforced, and new lines inside a group will be forbidden. To prevent multiple lines between imports, core `no-multiple-empty-lines` rule can be used.
+ - If set to `always-and-inside-groups`, it will act like `always` except newlines are allowed inside import groups.
+ - If set to `never`, no new lines are allowed in the entire import section.
 
 The default value is `"ignore"`.
 
@@ -284,15 +288,16 @@ import index from './';
 import sibling from './foo';
 ```
 
-### `alphabetize: {order: asc|desc|ignore, orderImportKind: asc|desc|ignore, caseInsensitive: true|false}`:
+### `alphabetize: {order: asc|desc|ignore, orderImportKind: asc|desc|ignore, caseInsensitive: true|false}`
 
 Sort the order within each group in alphabetical manner based on **import path**:
 
-- `order`: use `asc` to sort in ascending order, and `desc` to sort in descending order (default: `ignore`).
-- `orderImportKind`: use `asc` to sort in ascending order various import kinds, e.g. imports prefixed with `type` or `typeof`, with same import path. Use `desc` to sort in descending order (default: `ignore`).
-- `caseInsensitive`: use `true` to ignore case, and `false` to consider case (default: `false`).
+ - `order`: use `asc` to sort in ascending order, and `desc` to sort in descending order (default: `ignore`).
+ - `orderImportKind`: use `asc` to sort in ascending order various import kinds, e.g. imports prefixed with `type` or `typeof`, with same import path. Use `desc` to sort in descending order (default: `ignore`).
+ - `caseInsensitive`: use `true` to ignore case, and `false` to consider case (default: `false`).
 
 Example setting:
+
 ```ts
 alphabetize: {
   order: 'asc', /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */
@@ -322,9 +327,9 @@ import React, { PureComponent } from 'react';
 import { compose, apply } from 'xcompose';
 ```
 
-### `warnOnUnassignedImports: true|false`:
+### `warnOnUnassignedImports: true|false`
 
-* default: `false`
+ - default: `false`
 
 Warns when unassigned imports are out of order.  These warning will not be fixed
 with `--fix` because unassigned imports are used for side-effects and changing the
@@ -351,9 +356,9 @@ import './styles.css';
 
 ## Related
 
-- [`import/external-module-folders`] setting
+ - [`import/external-module-folders`] setting
 
-- [`import/internal-regex`] setting
+ - [`import/internal-regex`] setting
 
 [`import/external-module-folders`]: ../../README.md#importexternal-module-folders
 
diff --git a/docs/rules/prefer-default-export.md b/docs/rules/prefer-default-export.md
index 5d335f4c12..e2a7bacd73 100644
--- a/docs/rules/prefer-default-export.md
+++ b/docs/rules/prefer-default-export.md
@@ -6,12 +6,12 @@ In exporting files, this rule checks if there is default export or not.
 
 ## Rule Details
 
-##### rule schema:
+### rule schema
 
 ```javascript
 "import/prefer-default-export": [
     ( "off" | "warn" | "error" ),
-	{ "target": "single" | "any" } // default is "single"
+    { "target": "single" | "any" } // default is "single"
 ]
 ```
 
@@ -109,7 +109,6 @@ How to setup config file for this rule:
 }
 ```
 
-
 The following patterns are *not* considered warnings:
 
 ```javascript
diff --git a/docs/rules/unambiguous.md b/docs/rules/unambiguous.md
index da77a7453f..e9e5bf73da 100644
--- a/docs/rules/unambiguous.md
+++ b/docs/rules/unambiguous.md
@@ -32,6 +32,7 @@ export {} // simple way to mark side-effects-only file as 'module' without any i
 ```
 
 ...whereas the following file would be reported:
+
 ```js
 (function x() { return 42 })()
 ```
@@ -48,9 +49,9 @@ a `module`.
 
 ## Further Reading
 
-- [Unambiguous JavaScript Grammar]
-- [`parserOptions.sourceType`]
-- [node-eps#13](https://github.com/nodejs/node-eps/issues/13)
+ - [Unambiguous JavaScript Grammar]
+ - [`parserOptions.sourceType`]
+ - [node-eps#13](https://github.com/nodejs/node-eps/issues/13)
 
 [`parserOptions.sourceType`]: https://eslint.org/docs/user-guide/configuring#specifying-parser-options
 [Unambiguous JavaScript Grammar]: https://github.com/nodejs/node-eps/blob/HEAD/002-es-modules.md#32-determining-if-source-is-an-es-module
diff --git a/memo-parser/README.md b/memo-parser/README.md
index 8a2a3cb5cd..741e0ed4d0 100644
--- a/memo-parser/README.md
+++ b/memo-parser/README.md
@@ -1,13 +1,11 @@
 # eslint-plugin-import/memo-parser
 
-
-## NOTE!
+## NOTE
 
 This used to improve performance, but as of ESLint 5 and v2 of this plugin, it seems to just consume a bunch of memory and slightly increase lint times.
 
 **Not recommended for use at this time!**
 
-
 This parser is just a memoizing wrapper around some actual parser.
 
 To configure, just add your _actual_ parser to the `parserOptions`, like so:
diff --git a/package.json b/package.json
index 3884ff0653..bd45d8fa5c 100644
--- a/package.json
+++ b/package.json
@@ -24,7 +24,7 @@
     "copy-metafiles": "node --require babel-register ./scripts/copyMetafiles",
     "watch": "npm run tests-only -- -- --watch",
     "pretest": "linklocal",
-    "posttest": "eslint . && npm run update:eslint-docs -- --check",
+    "posttest": "eslint . && npm run update:eslint-docs -- --check && markdownlint \"**/*.md\"",
     "mocha": "cross-env BABEL_ENV=test nyc mocha",
     "tests-only": "npm run mocha tests/src",
     "test": "npm run tests-only",
@@ -87,6 +87,7 @@
     "in-publish": "^2.0.1",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",
+    "markdownlint-cli": "^0.35.0",
     "mocha": "^3.5.3",
     "npm-which": "^3.0.1",
     "nyc": "^11.9.0",
diff --git a/resolvers/README.md b/resolvers/README.md
index 0eb18684b9..e55ebb6104 100644
--- a/resolvers/README.md
+++ b/resolvers/README.md
@@ -2,14 +2,16 @@
 
 Resolvers must export two names:
 
-### `interfaceVersion => Number`
+## `interfaceVersion => Number`
 
 This document currently describes version 2 of the resolver interface. As such, a resolver implementing this version should
 
 ```js
 export const interfaceVersion = 2
 ```
+
 or
+
 ```js
 exports.interfaceVersion = 2
 ```
@@ -18,9 +20,10 @@ To the extent it is feasible, trailing versions of the resolvers will continue t
 
 Currently, version 1 is assumed if no `interfaceVersion` is available. (didn't think to define it until v2, heh. 😅)
 
-### `resolve(source, file, config) => { found: Boolean, path: String? }`
+## `resolve(source, file, config) => { found: Boolean, path: String? }`
 
 Given:
+
 ```js
 // /some/path/to/module.js
 import ... from './imported-file'
@@ -37,27 +40,29 @@ settings:
     node: { paths: [a, b, c] }
 ```
 
-#### Arguments
+### Arguments
 
 The arguments provided will be:
 
-##### `source`
+#### `source`
+
 the module identifier (`./imported-file`).
 
-##### `file`
+#### `file`
+
 the absolute path to the file making the import (`/some/path/to/module.js`)
 
-##### `config`
+#### `config`
 
 an object provided via the `import/resolver` setting. `my-cool-resolver` will get `["some", "stuff"]` as its `config`, while
   `node` will get `{ "paths": ["a", "b", "c"] }` provided as `config`.
 
-#### Return value
+### Return value
 
 The first resolver to return `{found: true}` is considered the source of truth. The returned object has:
 
-- `found`: `true` if the `source` module can be resolved relative to `file`, else `false`
-- `path`: an absolute path `String` if the module can be located on the filesystem; else, `null`.
+ - `found`: `true` if the `source` module can be resolved relative to `file`, else `false`
+ - `path`: an absolute path `String` if the module can be located on the filesystem; else, `null`.
 
 An example of a `null` path is a Node core module, such as `fs` or `crypto`. These modules can always be resolved, but the path need not be provided as the plugin will not attempt to parse core modules at this time.
 
diff --git a/resolvers/webpack/README.md b/resolvers/webpack/README.md
index cdb9222fae..06513ba141 100644
--- a/resolvers/webpack/README.md
+++ b/resolvers/webpack/README.md
@@ -13,13 +13,13 @@ changes.
 
 To use with `eslint-plugin-import`, run:
 
-```
+```sh
 npm i eslint-import-resolver-webpack -g
 ```
 
 or if you manage ESLint as a dev dependency:
 
-```
+```sh
 # inside your project's working tree
 npm install eslint-import-resolver-webpack --save-dev
 ```

From 2e7612ffdfe7721919cdb39832a78cf0b8828162 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 9 Aug 2023 23:12:59 +1200
Subject: [PATCH 624/767] [Dev Deps] pin `jackspeak` since 2.1.2+ depends on
 npm aliases, which kill the install process in npm < 6

See https://github.com/isaacs/jackspeak/issues/4
---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index bd45d8fa5c..553d9c6a95 100644
--- a/package.json
+++ b/package.json
@@ -85,6 +85,7 @@
     "fs-copy-file-sync": "^1.1.1",
     "glob": "^7.2.3",
     "in-publish": "^2.0.1",
+    "jackspeak": "=2.1.1",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",
     "markdownlint-cli": "^0.35.0",

From b9b9c86e918e268c325066af5938ad779f5f6e97 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 11 Aug 2023 09:22:27 -0700
Subject: [PATCH 625/767] [resolvers/webpack] [refactor] switch to a maintained
 array.prototype.find package

---
 resolvers/webpack/CHANGELOG.md | 1 +
 resolvers/webpack/index.js     | 2 +-
 resolvers/webpack/package.json | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index d5723757f8..914ce12732 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -4,6 +4,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
+ - [refactor] switch to a maintained array.prototype.find package
 
 ## 0.13.4 - 2023-08-08
  - [fix] restore node 6 compatibility
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index a9fc003813..b66ff38034 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -4,7 +4,7 @@ const findRoot = require('find-root');
 const path = require('path');
 const get = require('lodash/get');
 const isEqual = require('lodash/isEqual');
-const find = require('array-find');
+const find = require('array.prototype.find');
 const interpret = require('interpret');
 const fs = require('fs');
 const isCore = require('is-core-module');
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 0ae63cfdd4..3c87b2a1fa 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -30,7 +30,7 @@
   },
   "homepage": "https://github.com/import-js/eslint-plugin-import/tree/HEAD/resolvers/webpack",
   "dependencies": {
-    "array-find": "^1.0.0",
+    "array.prototype.find": "^2.2.1",
     "debug": "^3.2.7",
     "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",

From 2c18c2906dab446023afc3117d6cfdca0d2bbcec Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 15 Aug 2023 22:00:05 -0700
Subject: [PATCH 626/767] [resolvers/webpack] [refactor] remove `lodash/get`
 usage

---
 resolvers/webpack/index.js | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index b66ff38034..1eea7d7ab5 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -2,7 +2,6 @@
 
 const findRoot = require('find-root');
 const path = require('path');
-const get = require('lodash/get');
 const isEqual = require('lodash/isEqual');
 const find = require('array.prototype.find');
 const interpret = require('interpret');
@@ -51,15 +50,15 @@ exports.resolve = function (source, file, settings) {
 
   let webpackConfig;
 
-  const _configPath = get(settings, 'config');
+  const _configPath = settings && settings.config;
   /**
      * Attempt to set the current working directory.
      * If none is passed, default to the `cwd` where the config is located.
      */
-  const cwd = get(settings, 'cwd');
-  const configIndex = get(settings, 'config-index');
-  const env = get(settings, 'env');
-  const argv = get(settings, 'argv', {});
+  const cwd = settings && settings.cwd;
+  const configIndex = settings && settings['config-index'];
+  const env = settings && settings.env;
+  const argv = settings && typeof settings.argv !== 'undefined' ? settings.argv : {};
   let packageDir;
 
   let configPath = typeof _configPath === 'string' && _configPath.startsWith('.')

From 1e81734ddd7a040053d08045c922b15ea9d2045e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 15 Aug 2023 22:03:34 -0700
Subject: [PATCH 627/767] [resolvers/webpack] [refactor] replace
 `lodash/isEqual` usage with `deep-equal`

---
 resolvers/webpack/index.js     | 4 ++--
 resolvers/webpack/package.json | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 1eea7d7ab5..a19591f1a2 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -2,7 +2,7 @@
 
 const findRoot = require('find-root');
 const path = require('path');
-const isEqual = require('lodash/isEqual');
+const deepEqual = require('deep-equal');
 const find = require('array.prototype.find');
 const interpret = require('interpret');
 const fs = require('fs');
@@ -163,7 +163,7 @@ const MAX_CACHE = 10;
 const _cache = [];
 function getResolveSync(configPath, webpackConfig, cwd) {
   const cacheKey = { configPath, webpackConfig };
-  let cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
+  let cached = find(_cache, function (entry) { return deepEqual(entry.key, cacheKey, { strict: true }); });
   if (!cached) {
     cached = {
       key: cacheKey,
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 3c87b2a1fa..af20386a1e 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -32,13 +32,13 @@
   "dependencies": {
     "array.prototype.find": "^2.2.1",
     "debug": "^3.2.7",
+    "deep-equal": "^2.2.2",
     "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",
     "has": "^1.0.3",
     "interpret": "^1.4.0",
     "is-core-module": "^2.13.0",
     "is-regex": "^1.1.4",
-    "lodash": "^4.17.21",
     "resolve": "^1.22.4",
     "semver": "^5.7.2"
   },

From 22a080249074a86339ef4f30af02490e6084eb49 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 15 Aug 2023 22:06:00 -0700
Subject: [PATCH 628/767] [resolvers/webpack] [deps] update `resolve`

---
 resolvers/webpack/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index af20386a1e..29405df2ad 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -39,7 +39,7 @@
     "interpret": "^1.4.0",
     "is-core-module": "^2.13.0",
     "is-regex": "^1.1.4",
-    "resolve": "^1.22.4",
+    "resolve": "^2.0.0-next.4",
     "semver": "^5.7.2"
   },
   "peerDependencies": {

From da71746147450a5b7eeeaca77efc521125d91d41 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 15 Aug 2023 22:14:38 -0700
Subject: [PATCH 629/767] [resolvers/webpack] v0.13.5

---
 resolvers/webpack/CHANGELOG.md | 7 ++++++-
 resolvers/webpack/package.json | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 914ce12732..f7a9bc86ec 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -4,7 +4,12 @@ This project adheres to [Semantic Versioning](https://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
- - [refactor] switch to a maintained array.prototype.find package
+
+## 0.13.5 - 2023-08-15
+ - [refactor] replace `lodash/isEqual` usage with `deep-equal`
+ - [refactor] remove `lodash/get` usage
+ - [refactor] switch to a maintained `array.prototype.find` package
+ - [deps] update `resolve`
 
 ## 0.13.4 - 2023-08-08
  - [fix] restore node 6 compatibility
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 29405df2ad..74791e49c4 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.4",
+  "version": "0.13.5",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From cd1dff7544c90c79ef162e93fbe1e1e62d5e80bc Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 16 Aug 2023 11:31:56 -0700
Subject: [PATCH 630/767] Revert "[resolvers/webpack] [refactor] replace
 `lodash/isEqual` usage with `deep-equal`"

This reverts commit 1e81734ddd7a040053d08045c922b15ea9d2045e.

Fixes #2857.
---
 resolvers/webpack/index.js     | 4 ++--
 resolvers/webpack/package.json | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index a19591f1a2..1eea7d7ab5 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -2,7 +2,7 @@
 
 const findRoot = require('find-root');
 const path = require('path');
-const deepEqual = require('deep-equal');
+const isEqual = require('lodash/isEqual');
 const find = require('array.prototype.find');
 const interpret = require('interpret');
 const fs = require('fs');
@@ -163,7 +163,7 @@ const MAX_CACHE = 10;
 const _cache = [];
 function getResolveSync(configPath, webpackConfig, cwd) {
   const cacheKey = { configPath, webpackConfig };
-  let cached = find(_cache, function (entry) { return deepEqual(entry.key, cacheKey, { strict: true }); });
+  let cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
   if (!cached) {
     cached = {
       key: cacheKey,
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 74791e49c4..59aafdead6 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -32,13 +32,13 @@
   "dependencies": {
     "array.prototype.find": "^2.2.1",
     "debug": "^3.2.7",
-    "deep-equal": "^2.2.2",
     "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",
     "has": "^1.0.3",
     "interpret": "^1.4.0",
     "is-core-module": "^2.13.0",
     "is-regex": "^1.1.4",
+    "lodash": "^4.17.21",
     "resolve": "^2.0.0-next.4",
     "semver": "^5.7.2"
   },

From e9de30a9cbf8daab9f7e62131596d554884a56ac Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 16 Aug 2023 11:34:26 -0700
Subject: [PATCH 631/767] [resolvers/webpack] v0.13.6

---
 resolvers/webpack/CHANGELOG.md | 3 +++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index f7a9bc86ec..457cd36ed4 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## 0.13.6 - 2023-08-16
+ - [refactor] revert back to `lodash/isEqual`
+
 ## 0.13.5 - 2023-08-15
  - [refactor] replace `lodash/isEqual` usage with `deep-equal`
  - [refactor] remove `lodash/get` usage
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 59aafdead6..c3363611b0 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.5",
+  "version": "0.13.6",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 0847443b0a6d8273a862960e51ffcf478f636abf Mon Sep 17 00:00:00 2001
From: Ynda Jas <yndajas@gmail.com>
Date: Wed, 9 Aug 2023 12:15:50 +0100
Subject: [PATCH 632/767] Revert 1fa2971 (breaking group change in `order`)

1fa2971 changed the way groups work when there is only one, leading
to single nested groups being treated as though they were unnested.
Prior to this, if you wanted to group e.g. builtin and external
imports together at the top and everything else together as a second
group, a single nested group was the way to do it

[It appears that this change was unintentional][1], and was made to
try to fix what seems to be a misunderstanding around nested groups
([#2687]). [The docs][2] continue to suggest that nested groups
should be "mingled together" and makes no reference to a single nested
group with no other groups being an invalid option

This therefore reverts the change to how groups work when there is
only one. No documentation change should be necessary given this is
already the described behaviour

[1]: https://github.com/import-js/eslint-plugin-import/issues/2687#issuecomment-1671038558
[2]: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array
---
 CHANGELOG.md             |  5 ++++
 src/rules/order.js       |  4 ---
 tests/src/rules/order.js | 61 +++++++++++++++++-----------------------
 3 files changed, 31 insertions(+), 39 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 96dbd8c107..bc7da43bf3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- [`order`]: revert breaking change to single nested group ([#2854], thanks [@yndajas])
+
 ### Changed
 - [Docs] remove duplicate fixable notices in docs ([#2850], thanks [@bmish])
 
@@ -1082,6 +1085,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854
 [#2850]: https://github.com/import-js/eslint-plugin-import/pull/2850
 [#2842]: https://github.com/import-js/eslint-plugin-import/pull/2842
 [#2835]: https://github.com/import-js/eslint-plugin-import/pull/2835
@@ -1887,5 +1891,6 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xM8WVqaG]: https://github.com/xM8WVqaG
 [@xpl]: https://github.com/xpl
+[@yndajas]: https://github.com/yndajas
 [@yordis]: https://github.com/yordis
 [@zloirock]: https://github.com/zloirock
diff --git a/src/rules/order.js b/src/rules/order.js
index 6f70db263c..44d25be63c 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -422,10 +422,6 @@ const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling'
 // Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
 // Will throw an error if it contains a type that does not exist, or has a duplicate
 function convertGroupsToRanks(groups) {
-  if (groups.length === 1) {
-    // TODO: remove this `if` and fix the bug
-    return convertGroupsToRanks(groups[0]);
-  }
   const rankObject = groups.reduce(function (res, group, index) {
     [].concat(group).forEach(function (groupItem) {
       if (types.indexOf(groupItem) === -1) {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 2a44aa06aa..a6a8735a6f 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -2753,7 +2753,7 @@ context('TypeScript', function () {
       };
 
       ruleTester.run('order', rule, {
-        valid: [
+        valid: [].concat(
           // #1667: typescript type import support
 
           // Option alphabetize: {order: 'asc'}
@@ -2962,7 +2962,31 @@ context('TypeScript', function () {
               },
             ],
           }),
-        ],
+          isCoreModule('node:child_process') && isCoreModule('node:fs/promises') ? [
+            test({
+              code: `
+                import express from 'express';
+                import log4js from 'log4js';
+                import chpro from 'node:child_process';
+                // import fsp from 'node:fs/promises';
+              `,
+              options: [{
+                groups: [
+                  [
+                    'builtin',
+                    'external',
+                    'internal',
+                    'parent',
+                    'sibling',
+                    'index',
+                    'object',
+                    'type',
+                  ],
+                ],
+              }],
+            }),
+          ] : [],
+        ),
         invalid: [].concat(
           // Option alphabetize: {order: 'asc'}
           test({
@@ -3218,39 +3242,6 @@ context('TypeScript', function () {
                 // { message: '`node:fs/promises` import should occur before import of `express`' },
               ],
             }),
-
-            test({
-              code: `
-                import express from 'express';
-                import log4js from 'log4js';
-                import chpro from 'node:child_process';
-                // import fsp from 'node:fs/promises';
-              `,
-              output: `
-                import chpro from 'node:child_process';
-                import express from 'express';
-                import log4js from 'log4js';
-                // import fsp from 'node:fs/promises';
-              `,
-              options: [{
-                groups: [
-                  [
-                    'builtin',
-                    'external',
-                    'internal',
-                    'parent',
-                    'sibling',
-                    'index',
-                    'object',
-                    'type',
-                  ],
-                ],
-              }],
-              errors: [
-                { message: '`node:child_process` import should occur before import of `express`' },
-                // { message: '`node:fs/promises` import should occur before import of `express`' },
-              ],
-            }),
           ] : [],
         ),
       });

From cd957286efe1c4aa0423f82ac5576c75fd3be71e Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 18 Aug 2023 13:40:46 -0700
Subject: [PATCH 633/767] Bump to 2.28.1

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bc7da43bf3..4d5b23d828 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.28.1] - 2023-08-18
+
 ### Fixed
 - [`order`]: revert breaking change to single nested group ([#2854], thanks [@yndajas])
 
@@ -1545,7 +1547,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.0...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.1...HEAD
+[2.28.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.0...v2.28.1
 [2.28.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...v2.28.0
 [2.27.5]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.4...v2.27.5
 [2.27.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.3...v2.27.4
diff --git a/package.json b/package.json
index 553d9c6a95..6128a4e76b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.28.0",
+  "version": "2.28.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 4d32d68558e3cc995ddbdffc30c96d10a634f6fe Mon Sep 17 00:00:00 2001
From: James <5511220+Zamiell@users.noreply.github.com>
Date: Mon, 7 Aug 2023 15:47:59 -0400
Subject: [PATCH 634/767] [New] TypeScript config: add .cts and .mts extensions

---
 CHANGELOG.md         |  7 ++++++-
 config/typescript.js | 11 +++++++----
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d5b23d828..cd7a4380a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Added
+- TypeScript config: add .cts and .mts extensions ([#2851], thanks [@Zamiell])
+
 ## [2.28.1] - 2023-08-18
 
 ### Fixed
@@ -1088,6 +1091,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854
+[#2851]: https://github.com/import-js/eslint-plugin-import/pull/2851
 [#2850]: https://github.com/import-js/eslint-plugin-import/pull/2850
 [#2842]: https://github.com/import-js/eslint-plugin-import/pull/2842
 [#2835]: https://github.com/import-js/eslint-plugin-import/pull/2835
@@ -1896,4 +1900,5 @@ for info on changes for earlier releases.
 [@xpl]: https://github.com/xpl
 [@yndajas]: https://github.com/yndajas
 [@yordis]: https://github.com/yordis
-[@zloirock]: https://github.com/zloirock
+[@Zamiell]: https://github.com/Zamiell
+[@zloirock]: https://github.com/zloirock
\ No newline at end of file
diff --git a/config/typescript.js b/config/typescript.js
index 9fd789dbf7..ff7d0795c8 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -1,19 +1,22 @@
 /**
- * Adds `.jsx`, `.ts` and `.tsx` as an extension, and enables JSX/TSX parsing.
+ * This config:
+ * 1) adds `.jsx`, `.ts`, `.cts`, `.mts`, and `.tsx` as an extension
+ * 2) enables JSX/TSX parsing
  */
 
 // Omit `.d.ts` because 1) TypeScript compilation already confirms that
 // types are resolved, and 2) it would mask an unresolved
 // `.ts`/`.tsx`/`.js`/`.jsx` implementation.
-const allExtensions = ['.ts', '.tsx', '.js', '.jsx'];
+const typeScriptExtensions = ['.ts', '.cts', '.mts', '.tsx'];
 
-module.exports = {
+const allExtensions = [...typeScriptExtensions, '.js', '.jsx'];
 
+module.exports = {
   settings: {
     'import/extensions': allExtensions,
     'import/external-module-folders': ['node_modules', 'node_modules/@types'],
     'import/parsers': {
-      '@typescript-eslint/parser': ['.ts', '.tsx'],
+      '@typescript-eslint/parser': typeScriptExtensions,
     },
     'import/resolver': {
       node: {

From 04e68a2179c17b6b73b0c589ca8c092cdb1cb1e5 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 18 Aug 2023 16:24:35 -0700
Subject: [PATCH 635/767] [resolvers/webpack] [fix] use the `dirname` of the
 `configPath` as `basedir`

Fixes #2859
---
 resolvers/webpack/CHANGELOG.md | 2 ++
 resolvers/webpack/index.js     | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 457cd36ed4..bd567c4cb5 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -4,6 +4,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
+ - [fix] use the `dirname` of the `configPath` as `basedir` ([#2859])
 
 ## 0.13.6 - 2023-08-16
  - [refactor] revert back to `lodash/isEqual`
@@ -197,6 +198,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 [#181]: https://github.com/import-js/eslint-plugin-import/pull/181
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 
+[#2859]: https://github.com/import-js/eslint-plugin-import/issues/2859
 [#2268]: https://github.com/import-js/eslint-plugin-import/issues/2268
 [#1219]: https://github.com/import-js/eslint-plugin-import/issues/1219
 [#788]: https://github.com/import-js/eslint-plugin-import/issues/788
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 1eea7d7ab5..ebd77af1ed 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -183,7 +183,7 @@ function createResolveSync(configPath, webpackConfig, cwd) {
 
   if (typeof configPath === 'string') {
     // This can be changed via the settings passed in when defining the resolver
-    basedir = cwd || configPath;
+    basedir = cwd || path.dirname(configPath);
     log(`Attempting to load webpack path from ${basedir}`);
   }
 

From 6b95a021938139726b3f862beb37012d6e2afab2 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 19 Aug 2023 10:37:28 -0700
Subject: [PATCH 636/767] [resolvers/webpack] v0.13.7

---
 resolvers/webpack/CHANGELOG.md | 2 ++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index bd567c4cb5..99746c7706 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -4,6 +4,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
+
+## 0.13.7 - 2023-08-19
  - [fix] use the `dirname` of the `configPath` as `basedir` ([#2859])
 
 ## 0.13.6 - 2023-08-16
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index c3363611b0..28a6184f7c 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.6",
+  "version": "0.13.7",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 87051212306f8cd08cb62555b94fae259146468c Mon Sep 17 00:00:00 2001
From: Anix <anik220798@gmail.com>
Date: Tue, 27 Oct 2020 14:20:05 +0000
Subject: [PATCH 637/767] [New] `newline-after-import`: new option `exactCount`
 and docs update

Fixes #1901. Fixes #514.

Co-authored-by: Anix <anik220798@gmail.com>
Co-authored-by: reosarevok <reosarevok@metabrainz.org>
---
 CHANGELOG.md                            |   3 +-
 docs/rules/newline-after-import.md      |  91 +++++++++++++++-----
 src/rules/newline-after-import.js       |  17 +++-
 tests/src/rules/newline-after-import.js | 108 ++++++++++++++++++++++++
 4 files changed, 193 insertions(+), 26 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd7a4380a6..567ed26459 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Added
 - TypeScript config: add .cts and .mts extensions ([#2851], thanks [@Zamiell])
+- [`newline-after-import`]: new option `exactCount` and docs update ([#1933], thanks [@anikethsaha] and [@reosarevok])
 
 ## [2.28.1] - 2023-08-18
 
@@ -1901,4 +1902,4 @@ for info on changes for earlier releases.
 [@yndajas]: https://github.com/yndajas
 [@yordis]: https://github.com/yordis
 [@Zamiell]: https://github.com/Zamiell
-[@zloirock]: https://github.com/zloirock
\ No newline at end of file
+[@zloirock]: https://github.com/zloirock
diff --git a/docs/rules/newline-after-import.md b/docs/rules/newline-after-import.md
index fec6b23aca..ef5aeed767 100644
--- a/docs/rules/newline-after-import.md
+++ b/docs/rules/newline-after-import.md
@@ -12,70 +12,119 @@ This rule supports the following options:
 
  - `count` which sets the number of newlines that are enforced after the last top-level import statement or require call. This option defaults to `1`.
 
+ - `exactCount` which enforce the exact numbers of newlines that is mentioned in `count`. This option defaults to `false`.
+
  - `considerComments` which enforces the rule on comments after the last import-statement as well when set to true. This option defaults to `false`.
 
 Valid:
 
 ```js
-import defaultExport from './foo'
+import defaultExport from './foo';
 
-const FOO = 'BAR'
+const FOO = 'BAR';
 ```
 
 ```js
-import defaultExport from './foo'
-import { bar }  from 'bar-lib'
+import defaultExport from './foo';
+import { bar }  from 'bar-lib';
 
-const FOO = 'BAR'
+const FOO = 'BAR';
 ```
 
 ```js
-const FOO = require('./foo')
-const BAR = require('./bar')
+const FOO = require('./foo');
+const BAR = require('./bar');
 
-const BAZ = 1
+const BAZ = 1;
 ```
 
 Invalid:
 
 ```js
 import * as foo from 'foo'
-const FOO = 'BAR'
+const FOO = 'BAR';
 ```
 
 ```js
-import * as foo from 'foo'
-const FOO = 'BAR'
+import * as foo from 'foo';
+const FOO = 'BAR';
 
-import { bar }  from 'bar-lib'
+import { bar }  from 'bar-lib';
 ```
 
 ```js
-const FOO = require('./foo')
-const BAZ = 1
-const BAR = require('./bar')
+const FOO = require('./foo');
+const BAZ = 1;
+const BAR = require('./bar');
 ```
 
 With `count` set to `2` this will be considered valid:
 
 ```js
-import defaultExport from './foo'
+import defaultExport from './foo';
 
 
-const FOO = 'BAR'
+const FOO = 'BAR';
+```
+
+```js
+import defaultExport from './foo';
+
+
+
+const FOO = 'BAR';
 ```
 
 With `count` set to `2` these will be considered invalid:
 
 ```js
-import defaultExport from './foo'
-const FOO = 'BAR'
+import defaultExport from './foo';
+const FOO = 'BAR';
 ```
 
 ```js
-import defaultExport from './foo'
+import defaultExport from './foo';
 
-const FOO = 'BAR'
+const FOO = 'BAR';
+```
+
+With `count` set to `2` and `exactCount` set to `true` this will be considered valid:
+
+```js
+import defaultExport from './foo';
+
+
+const FOO = 'BAR';
+```
+
+With `count` set to `2` and `exactCount` set to `true` these will be considered invalid:
+
+```js
+import defaultExport from './foo';
+const FOO = 'BAR';
+```
+
+```js
+import defaultExport from './foo';
+
+const FOO = 'BAR';
+```
+
+```js
+import defaultExport from './foo';
+
+
+
+const FOO = 'BAR';
+```
+
+```js
+import defaultExport from './foo';
+
+
+
+
+const FOO = 'BAR';
 ```
 
 With `considerComments` set to `false` this will be considered valid:
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 8855e26e52..9b469110be 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -69,6 +69,7 @@ module.exports = {
             type: 'integer',
             minimum: 1,
           },
+          exactCount: { type: 'boolean' },
           considerComments: { type: 'boolean' },
         },
         additionalProperties: false,
@@ -78,7 +79,12 @@ module.exports = {
   create(context) {
     let level = 0;
     const requireCalls = [];
-    const options = { count: 1, considerComments: false, ...context.options[0] };
+    const options = {
+      count: 1,
+      exactCount: false,
+      considerComments: false,
+      ...context.options[0],
+    };
 
     function checkForNewLine(node, nextNode, type) {
       if (isExportDefaultClass(nextNode) || isExportNameClass(nextNode)) {
@@ -94,7 +100,10 @@ module.exports = {
       const lineDifference = getLineDifference(node, nextNode);
       const EXPECTED_LINE_DIFFERENCE = options.count + 1;
 
-      if (lineDifference < EXPECTED_LINE_DIFFERENCE) {
+      if (
+        lineDifference < EXPECTED_LINE_DIFFERENCE
+        || options.exactCount && lineDifference !== EXPECTED_LINE_DIFFERENCE
+      ) {
         let column = node.loc.start.column;
 
         if (node.loc.start.line !== node.loc.end.line) {
@@ -107,7 +116,7 @@ module.exports = {
             column,
           },
           message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} after ${type} statement not followed by another ${type}.`,
-          fix: (fixer) => fixer.insertTextAfter(
+          fix: options.exactCount && EXPECTED_LINE_DIFFERENCE < lineDifference ? undefined : (fixer) => fixer.insertTextAfter(
             node,
             '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference),
           ),
@@ -132,7 +141,7 @@ module.exports = {
             column,
           },
           message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} after import statement not followed by another import.`,
-          fix: (fixer) => fixer.insertTextAfter(
+          fix: options.exactCount && EXPECTED_LINE_DIFFERENCE < lineDifference ? undefined : (fixer) => fixer.insertTextAfter(
             node,
             '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference),
           ),
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 8f3338eee8..bd11da4191 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -46,6 +46,16 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { ecmaVersion: 6 },
       options: [{ considerComments: true }],
     },
+    {
+      code: `
+        const x = () => require('baz') && require('bar')
+
+        // Some random single line comment
+        var bar = 42;
+      `,
+      parserOptions: { ecmaVersion: 6 },
+      options: [{ considerComments: true, count: 1, exactCount: true }],
+    },
     {
       code: `
         const x = () => require('baz') && require('bar')
@@ -122,6 +132,21 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ count: 2 }],
     },
+    {
+      code: `import foo from 'foo';\n\n\nvar bar = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 2, exactCount: true }],
+    },
+    {
+      code: `import foo from 'foo';\n\nvar bar = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 1, exactCount: true }],
+    },
+    {
+      code: `import foo from 'foo';\n\n\nvar bar = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 1 }],
+    },
     {
       code: `import foo from 'foo';\n\n\n\n\nvar bar = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
@@ -141,6 +166,11 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ count: 4 }],
     },
+    {
+      code: `var foo = require('foo-module');\n\n\n\n\nvar foo = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 4, exactCount: true }],
+    },
     {
       code: `require('foo-module');\n\nvar foo = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
@@ -620,5 +650,83 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { sourceType: 'module' },
       parser: parsers.BABEL_OLD,
     })) || [],
+    {
+      code: `import foo from 'foo';\n\nexport default function() {};`,
+      output: `import foo from 'foo';\n\n\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `import foo from 'foo';\n\n\n\nexport default function() {};`,
+      output: `import foo from 'foo';\n\n\n\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `import foo from 'foo';\n\n\n\n\nexport default function() {};`,
+      output: `import foo from 'foo';\n\n\n\n\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `
+        import foo from 'foo';
+
+
+        // Some random single line comment
+        var bar = 42;
+      `,
+      output: `
+        import foo from 'foo';
+
+
+        // Some random single line comment
+        var bar = 42;
+      `,
+      errors: [{
+        line: 2,
+        column: 9,
+        message: IMPORT_ERROR_MESSAGE,
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ considerComments: true, count: 1, exactCount: true }],
+    },
+    {
+      code: `import foo from 'foo';export default function() {};`,
+      output: `import foo from 'foo';\n\nexport default function() {};`,
+      options: [{ count: 1, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE,
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `const foo = require('foo');\n\n\n\nconst bar = function() {};`,
+      output: `const foo = require('foo');\n\n\n\nconst bar = function() {};`,
+      options: [{ count: 2, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: 'Expected 2 empty lines after require statement not followed by another require.',
+      }],
+      parserOptions: { ecmaVersion: 2015 },
+    },
   ),
 });

From 66cb10f302a23c0b72c4a3ead26374a6729a9017 Mon Sep 17 00:00:00 2001
From: Kinland <16787581+kinland@users.noreply.github.com>
Date: Mon, 25 Sep 2023 19:16:00 -0700
Subject: [PATCH 638/767] [Fix] `newline-after-import`: fix `exactCount` with
 `considerComments` false positive, when there is a leading comment

Fixes #2882.
---
 CHANGELOG.md                            |   5 +-
 src/rules/newline-after-import.js       |   2 +-
 tests/src/rules/newline-after-import.js | 133 ++++++++++++++++++++++++
 3 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 567ed26459..6af7f748a4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
 - TypeScript config: add .cts and .mts extensions ([#2851], thanks [@Zamiell])
 - [`newline-after-import`]: new option `exactCount` and docs update ([#1933], thanks [@anikethsaha] and [@reosarevok])
+- [`newline-after-import`]: fix `exactCount` with `considerComments` false positive, when there is a leading comment ([#2884], thanks [@kinland])
 
 ## [2.28.1] - 2023-08-18
 
@@ -1091,6 +1092,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2884]: https://github.com/import-js/eslint-plugin-import/pull/2884
 [#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854
 [#2851]: https://github.com/import-js/eslint-plugin-import/pull/2851
 [#2850]: https://github.com/import-js/eslint-plugin-import/pull/2850
@@ -1769,6 +1771,7 @@ for info on changes for earlier releases.
 [@kentcdodds]: https://github.com/kentcdodds
 [@kevin940726]: https://github.com/kevin940726
 [@kgregory]: https://github.com/kgregory
+[@kinland]: https://github.com/kinland
 [@kirill-konshin]: https://github.com/kirill-konshin
 [@kiwka]: https://github.com/kiwka
 [@klimashkin]: https://github.com/klimashkin
@@ -1776,8 +1779,8 @@ for info on changes for earlier releases.
 [@knpwrs]: https://github.com/knpwrs
 [@KostyaZgara]: https://github.com/KostyaZgara
 [@kylemh]: https://github.com/kylemh
-[@laysent]: https://github.com/laysent
 [@laurens-dg]: https://github.com/laurens-dg
+[@laysent]: https://github.com/laysent
 [@le0nik]: https://github.com/le0nik
 [@leipert]: https://github.com/leipert
 [@lemonmade]: https://github.com/lemonmade
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index 9b469110be..a33bb615b9 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -169,7 +169,7 @@ module.exports = {
       let nextComment;
 
       if (typeof parent.comments !== 'undefined' && options.considerComments) {
-        nextComment = parent.comments.find((o) => o.loc.start.line === endLine + 1);
+        nextComment = parent.comments.find((o) => o.loc.start.line >= endLine && o.loc.start.line <= endLine + options.count + 1);
       }
 
       // skip "export import"s
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index bd11da4191..6a8fb83e40 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -142,6 +142,31 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ count: 1, exactCount: true }],
     },
+    {
+      code: `import foo from 'foo';\n\n// Some random comment\nvar bar = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 2, exactCount: true }],
+    },
+    {
+      code: `import foo from 'foo';\n// Some random comment\nvar bar = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 1, exactCount: true }],
+    },
+    {
+      code: `import foo from 'foo';\n\n\n// Some random comment\nvar bar = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 2, exactCount: true, considerComments: true }],
+    },
+    {
+      code: `import foo from 'foo';\n\n// Some random comment\nvar bar = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 1, exactCount: true, considerComments: true }],
+    },
+    {
+      code: `/**\n * A leading comment\n */\nimport foo from 'foo';\n\n// Some random comment\nexport {foo};`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 2, exactCount: true }],
+    },
     {
       code: `import foo from 'foo';\n\n\nvar bar = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
@@ -171,6 +196,16 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ count: 4, exactCount: true }],
     },
+    {
+      code: `var foo = require('foo-module');\n\n// Some random comment\n\n\nvar foo = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 4, exactCount: true }],
+    },
+    {
+      code: `var foo = require('foo-module');\n\n\n\n// Some random comment\nvar foo = 'bar';`,
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ count: 4, exactCount: true, considerComments: true }],
+    },
     {
       code: `require('foo-module');\n\nvar foo = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
@@ -683,6 +718,72 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
+    {
+      code: `import foo from 'foo';\n// some random comment\nexport default function() {};`,
+      output: `import foo from 'foo';\n\n// some random comment\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `import foo from 'foo';\n// some random comment\n\n\nexport default function() {};`,
+      output: `import foo from 'foo';\n// some random comment\n\n\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `import foo from 'foo';\n// some random comment\n\n\n\nexport default function() {};`,
+      output: `import foo from 'foo';\n// some random comment\n\n\n\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `import foo from 'foo';\n// some random comment\nexport default function() {};`,
+      output: `import foo from 'foo';\n\n\n// some random comment\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true, considerComments: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `import foo from 'foo';\n\n// some random comment\nexport default function() {};`,
+      output: `import foo from 'foo';\n\n\n// some random comment\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true, considerComments: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
+    {
+      code: `import foo from 'foo';\n\n\n\n// some random comment\nexport default function() {};`,
+      output: `import foo from 'foo';\n\n\n\n// some random comment\nexport default function() {};`,
+      options: [{ count: 2, exactCount: true, considerComments: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+    },
     {
       code: `
         import foo from 'foo';
@@ -728,5 +829,37 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       }],
       parserOptions: { ecmaVersion: 2015 },
     },
+    {
+      code: `const foo = require('foo');\n\n\n\n// some random comment\nconst bar = function() {};`,
+      output: `const foo = require('foo');\n\n\n\n// some random comment\nconst bar = function() {};`,
+      options: [{ count: 2, exactCount: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: 'Expected 2 empty lines after require statement not followed by another require.',
+      }],
+      parserOptions: { ecmaVersion: 2015 },
+    },
+    {
+      code: `import foo from 'foo';// some random comment\nexport default function() {};`,
+      output: `import foo from 'foo';\n\n// some random comment\nexport default function() {};`,
+      options: [{ count: 1, exactCount: true, considerComments: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: IMPORT_ERROR_MESSAGE,
+      }],
+      parserOptions: { ecmaVersion: 2015, considerComments: true, sourceType: 'module' },
+    },
+    {
+      code: `const foo = require('foo');\n\n\n// some random comment\nconst bar = function() {};`,
+      options: [{ count: 2, exactCount: true, considerComments: true }],
+      errors: [{
+        line: 1,
+        column: 1,
+        message: 'Expected 2 empty lines after require statement not followed by another require.',
+      }],
+      parserOptions: { ecmaVersion: 2015 },
+    },
   ),
 });

From 2c281d15d06dc54c90cfa5c28b276b189ecd8f3f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 22 Oct 2023 22:25:32 -0700
Subject: [PATCH 639/767] [resolvers/webpack] [refactor] use `hasown` instead
 of `has`

---
 resolvers/webpack/index.js     | 4 ++--
 resolvers/webpack/package.json | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index ebd77af1ed..3ca2874dd8 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -9,7 +9,7 @@ const fs = require('fs');
 const isCore = require('is-core-module');
 const resolve = require('resolve/sync');
 const semver = require('semver');
-const has = require('has');
+const hasOwn = require('hasown');
 const isRegex = require('is-regex');
 
 const log = require('debug')('eslint-plugin-import:resolver:webpack');
@@ -382,7 +382,7 @@ function findExternal(source, externals, context, resolveSync) {
 
   // else, vanilla object
   for (const key in externals) {
-    if (!has(externals, key)) { continue; }
+    if (!hasOwn(externals, key)) { continue; }
     if (source === key) { return true; }
   }
   return false;
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 28a6184f7c..0810ca70dd 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -34,7 +34,7 @@
     "debug": "^3.2.7",
     "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",
-    "has": "^1.0.3",
+    "hasown": "^2.0.0",
     "interpret": "^1.4.0",
     "is-core-module": "^2.13.0",
     "is-regex": "^1.1.4",

From 30d61b6dc45e712899a4b9184964a948251adfcf Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 22 Oct 2023 22:26:45 -0700
Subject: [PATCH 640/767] [resolvers/webpack] [deps] update
 `array.prototype.find`, `is-core-module`, `resolve`

---
 resolvers/webpack/package.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 0810ca70dd..b348b6e2bb 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -30,16 +30,16 @@
   },
   "homepage": "https://github.com/import-js/eslint-plugin-import/tree/HEAD/resolvers/webpack",
   "dependencies": {
-    "array.prototype.find": "^2.2.1",
+    "array.prototype.find": "^2.2.2",
     "debug": "^3.2.7",
     "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",
     "hasown": "^2.0.0",
     "interpret": "^1.4.0",
-    "is-core-module": "^2.13.0",
+    "is-core-module": "^2.13.1",
     "is-regex": "^1.1.4",
     "lodash": "^4.17.21",
-    "resolve": "^2.0.0-next.4",
+    "resolve": "^2.0.0-next.5",
     "semver": "^5.7.2"
   },
   "peerDependencies": {

From 6d2540f2eefc063d07a841088836e1dcee652cd9 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 22 Oct 2023 22:28:03 -0700
Subject: [PATCH 641/767] [resolvers/webpack] v0.13.8

---
 resolvers/webpack/CHANGELOG.md | 5 +++++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 99746c7706..4fed046b46 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,6 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## 0.13.8 - 2023-10-22
+ - [refactor] use `hasown` instead of `has`
+ - [deps] update `array.prototype.find`, `is-core-module`, `resolve`
+
+
 ## 0.13.7 - 2023-08-19
  - [fix] use the `dirname` of the `configPath` as `basedir` ([#2859])
 
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index b348b6e2bb..3fa47d9362 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.7",
+  "version": "0.13.8",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 78f50b852a0dc187ccbfd6b4592e4f59ba78d339 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 22 Oct 2023 23:08:13 -0700
Subject: [PATCH 642/767] [Deps] update `array-includes`,
 `array.prototype.findlastindex`, `array.prototype.flat`,
 `array.prototype.flatmap`, `eslint-import-resolver-node`, `is-core-module`,
 `object.fromentries`, `object.groupby`, `object.values`

---
 package.json | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/package.json b/package.json
index 6128a4e76b..2fdc9c4c2f 100644
--- a/package.json
+++ b/package.json
@@ -103,21 +103,21 @@
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
   },
   "dependencies": {
-    "array-includes": "^3.1.6",
-    "array.prototype.findlastindex": "^1.2.2",
-    "array.prototype.flat": "^1.3.1",
-    "array.prototype.flatmap": "^1.3.1",
+    "array-includes": "^3.1.7",
+    "array.prototype.findlastindex": "^1.2.3",
+    "array.prototype.flat": "^1.3.2",
+    "array.prototype.flatmap": "^1.3.2",
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
-    "eslint-import-resolver-node": "^0.3.7",
+    "eslint-import-resolver-node": "^0.3.9",
     "eslint-module-utils": "^2.8.0",
     "has": "^1.0.3",
-    "is-core-module": "^2.13.0",
+    "is-core-module": "^2.13.1",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
-    "object.fromentries": "^2.0.6",
-    "object.groupby": "^1.0.0",
-    "object.values": "^1.1.6",
+    "object.fromentries": "^2.0.7",
+    "object.groupby": "^1.0.1",
+    "object.values": "^1.1.7",
     "semver": "^6.3.1",
     "tsconfig-paths": "^3.14.2"
   }

From ec6a8ea3c386241daaf208fe78da151b30415357 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 22 Oct 2023 23:08:57 -0700
Subject: [PATCH 643/767] [Refactor] use `hasown` instead of `has`

---
 package.json                             | 2 +-
 src/rules/no-anonymous-default-export.js | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 2fdc9c4c2f..1d9acd4f2b 100644
--- a/package.json
+++ b/package.json
@@ -111,7 +111,7 @@
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
     "eslint-module-utils": "^2.8.0",
-    "has": "^1.0.3",
+    "hasown": "^2.0.0",
     "is-core-module": "^2.13.1",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
diff --git a/src/rules/no-anonymous-default-export.js b/src/rules/no-anonymous-default-export.js
index 59a3cbfdac..4f6947e814 100644
--- a/src/rules/no-anonymous-default-export.js
+++ b/src/rules/no-anonymous-default-export.js
@@ -3,7 +3,7 @@
  * @author Duncan Beevers
  */
 
-import has from 'has';
+import hasOwn from 'hasown';
 import values from 'object.values';
 import fromEntries from 'object.fromentries';
 
@@ -65,7 +65,7 @@ const schemaProperties = fromEntries(values(defs).map((def) => [def.option, {
   type: 'boolean',
 }]));
 
-const defaults = fromEntries(values(defs).map((def) => [def.option, has(def, 'default') ? def.default : false]));
+const defaults = fromEntries(values(defs).map((def) => [def.option, hasOwn(def, 'default') ? def.default : false]));
 
 module.exports = {
   meta: {

From 6d34c88a91a9cb7556700b7cb83c8a27731ff302 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 22 Oct 2023 23:12:22 -0700
Subject: [PATCH 644/767] Bump to 2.29.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6af7f748a4..bc3fc1918d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.29.0] - 2023-10-22
+
 ### Added
 - TypeScript config: add .cts and .mts extensions ([#2851], thanks [@Zamiell])
 - [`newline-after-import`]: new option `exactCount` and docs update ([#1933], thanks [@anikethsaha] and [@reosarevok])
@@ -1554,7 +1556,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.1...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.0...HEAD
+[2.29.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.1...v2.29.0
 [2.28.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.0...v2.28.1
 [2.28.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...v2.28.0
 [2.27.5]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.4...v2.27.5
diff --git a/package.json b/package.json
index 1d9acd4f2b..bd92f4f692 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.28.1",
+  "version": "2.29.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 12f0300100b9bb90c6a952d07c133f2d5842ad57 Mon Sep 17 00:00:00 2001
From: Noureldin Shaker <43860275+Pandemic1617@users.noreply.github.com>
Date: Tue, 7 Nov 2023 15:37:39 +0000
Subject: [PATCH 645/767] [Fix] `no-extraneous-dependencies`: ignore `export
 type { ... } from '...'` when `includeTypes` is false

---
 CHANGELOG.md                                  |  5 +++++
 src/rules/no-extraneous-dependencies.js       |  1 +
 tests/src/rules/no-extraneous-dependencies.js | 12 ++++++++++++
 3 files changed, 18 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bc3fc1918d..f902dec7f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- [`no-extraneous-dependencies`]: ignore `export type { ... } from '...'` when `includeTypes` is `false` ([#2919], thanks [@Pandemic1617])
+
 ## [2.29.0] - 2023-10-22
 
 ### Added
@@ -1094,6 +1097,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2919]: https://github.com/import-js/eslint-plugin-import/pull/2919
 [#2884]: https://github.com/import-js/eslint-plugin-import/pull/2884
 [#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854
 [#2851]: https://github.com/import-js/eslint-plugin-import/pull/2851
@@ -1830,6 +1834,7 @@ for info on changes for earlier releases.
 [@ntdb]: https://github.com/ntdb
 [@nwalters512]: https://github.com/nwalters512
 [@ombene]: https://github.com/ombene
+[@Pandemic1617]: https://github.com/Pandemic1617
 [@ota-meshi]: https://github.com/ota-meshi
 [@OutdatedVersion]: https://github.com/OutdatedVersion
 [@panrafal]: https://github.com/panrafal
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 0408e0866d..df97987901 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -177,6 +177,7 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
     && (
       node.importKind === 'type'
       || node.importKind === 'typeof'
+      || node.exportKind === 'type'
       || Array.isArray(node.specifiers) && node.specifiers.length && node.specifiers.every((specifier) => specifier.importKind === 'type' || specifier.importKind === 'typeof')
     )
   ) {
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 21561615c6..cb0398ada2 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -427,6 +427,18 @@ describe('TypeScript', () => {
             options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
             ...parserConfig,
           }),
+
+          test({
+            code: 'import type { T } from "a"; export type { T };',
+            options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            ...parserConfig,
+          }),
+
+          test({
+            code: 'export type { T } from "a";',
+            options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }],
+            ...parserConfig,
+          }),
         ],
         invalid: [
           test({

From 9fd3c42707d71987e439a847f2e213f55c84f734 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 24 Nov 2023 21:29:58 -0800
Subject: [PATCH 646/767] [Tests] `no-duplicates`: add passing test

Closes #2840
---
 tests/src/rules/no-duplicates.js | 62 ++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index d61fda86e1..f83221105a 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -482,6 +482,68 @@ import {x,y} from './foo'
       errors: ["'../constants' imported multiple times.", "'../constants' imported multiple times."],
       ...jsxConfig,
     }),
+
+    test({
+      code: `
+        import {A1,} from 'foo';
+        import {B1,} from 'foo';
+        import {C1,} from 'foo';
+
+        import {
+          A2,
+        } from 'bar';
+        import {
+          B2,
+        } from 'bar';
+        import {
+          C2,
+        } from 'bar';
+
+      `,
+      output: `
+        import {A1,B1,C1} from 'foo';
+                ${''}
+        import {
+          A2,
+        ${''}
+          B2,
+          C2} from 'bar';
+                ${''}
+      `,
+      errors: [
+        {
+          message: "'foo' imported multiple times.",
+          line: 2,
+          column: 27,
+        },
+        {
+          message: "'foo' imported multiple times.",
+          line: 3,
+          column: 27,
+        },
+        {
+          message: "'foo' imported multiple times.",
+          line: 4,
+          column: 27,
+        },
+        {
+          message: "'bar' imported multiple times.",
+          line: 8,
+          column: 16,
+        },
+        {
+          message: "'bar' imported multiple times.",
+          line: 11,
+          column: 16,
+        },
+        {
+          message: "'bar' imported multiple times.",
+          line: 14,
+          column: 16,
+        },
+      ],
+      ...jsxConfig,
+    }),
   ],
 });
 

From e67259e4c167d46e9cc5472d3afa32369fbf2eff Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 3 Dec 2023 22:32:42 -0800
Subject: [PATCH 647/767] [Fix] `no-unused-modules`: support export patterns
 with array destructuring

Fixes #2930
---
 CHANGELOG.md                         | 3 +++
 src/rules/no-unused-modules.js       | 5 +++++
 tests/src/rules/no-unused-modules.js | 9 +++++++++
 3 files changed, 17 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f902dec7f0..a56216a7a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - [`no-extraneous-dependencies`]: ignore `export type { ... } from '...'` when `includeTypes` is `false` ([#2919], thanks [@Pandemic1617])
+- [`no-unused-modules`]: support export patterns with array destructuring ([#2930], thanks [@ljharb])
 
 ## [2.29.0] - 2023-10-22
 
@@ -1435,6 +1436,8 @@ for info on changes for earlier releases.
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
+
+[#2930]: https://github.com/import-js/eslint-plugin-import/issues/2930
 [#2687]: https://github.com/import-js/eslint-plugin-import/issues/2687
 [#2684]: https://github.com/import-js/eslint-plugin-import/issues/2684
 [#2674]: https://github.com/import-js/eslint-plugin-import/issues/2674
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index ecba3a19ce..8229d880ce 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -74,6 +74,7 @@ const FUNCTION_DECLARATION = 'FunctionDeclaration';
 const CLASS_DECLARATION = 'ClassDeclaration';
 const IDENTIFIER = 'Identifier';
 const OBJECT_PATTERN = 'ObjectPattern';
+const ARRAY_PATTERN = 'ArrayPattern';
 const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration';
 const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration';
 const TS_ENUM_DECLARATION = 'TSEnumDeclaration';
@@ -97,6 +98,10 @@ function forEachDeclarationIdentifier(declaration, cb) {
               cb(pattern.name);
             }
           });
+        } else if (id.type === ARRAY_PATTERN) {
+          id.elements.forEach(({ name }) => {
+            cb(name);
+          });
         } else {
           cb(id.name);
         }
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 77fb608ccb..9aa5ce53d7 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -160,6 +160,15 @@ ruleTester.run('no-unused-modules', rule, {
       filename: testFilePath('./no-unused-modules/file-o.js'),
       parser: parsers.BABEL_OLD,
     }),
+    test({
+      options: unusedExportsOptions,
+      code: `
+        export const [o0, o2] = createLoadingAndErrorSelectors(
+          AUTH_USER
+        );
+      `,
+      filename: testFilePath('./no-unused-modules/file-o.js'),
+    }),
   ],
   invalid: [
     test({

From 8c83eafe4a709c0c275279a7bf99d92fa4e034a5 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 4 Dec 2023 08:28:05 -0800
Subject: [PATCH 648/767] [Tests] node v21.3 has a broken `fs.writeFile`

See https://github.com/nodejs/node/pull/50990 / https://github.com/nodejs/node/issues/50989
---
 tests/src/rules/no-unused-modules.js | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 9aa5ce53d7..b09d5d759c 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -732,7 +732,7 @@ describe('renameDefault', () => {
 
 describe('test behavior for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', { encoding: 'utf8' });
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', { encoding: 'utf8', flag: 'w' });
   });
 
   // add import in newly created file
@@ -840,7 +840,7 @@ describe('test behavior for new file', () => {
 
   describe('test behavior for new file', () => {
     before(() => {
-      fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', { encoding: 'utf8' });
+      fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', { encoding: 'utf8', flag: 'w' });
     });
     ruleTester.run('no-unused-modules', rule, {
       valid: [
@@ -875,7 +875,7 @@ describe('test behavior for new file', () => {
 
 describe('test behavior for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', { encoding: 'utf8' });
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', { encoding: 'utf8', flag: 'w' });
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
@@ -901,7 +901,7 @@ describe('test behavior for new file', () => {
 
 describe('test behavior for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', { encoding: 'utf8' });
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', { encoding: 'utf8', flag: 'w' });
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [
@@ -952,7 +952,7 @@ describe('test behavior for destructured exports', () => {
 
 describe('test behavior for new file', () => {
   before(() => {
-    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', { encoding: 'utf8' });
+    fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', { encoding: 'utf8', flag: 'w' });
   });
   ruleTester.run('no-unused-modules', rule, {
     valid: [

From 80aee736721397cd073636950fef30aa65e165d3 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 14 Dec 2023 10:36:00 -0800
Subject: [PATCH 649/767] [Dev Deps] update `chai`, `eslint-doc-generator`,
 `markdownlint-cli`

---
 package.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index bd92f4f692..b899f56919 100644
--- a/package.json
+++ b/package.json
@@ -69,11 +69,11 @@
     "babel-preset-flow": "^6.23.0",
     "babel-register": "^6.26.0",
     "babylon": "^6.18.0",
-    "chai": "^4.3.7",
+    "chai": "^4.3.10",
     "cross-env": "^4.0.0",
     "escope": "^3.6.0",
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8",
-    "eslint-doc-generator": "^1.4.3",
+    "eslint-doc-generator": "^1.6.1",
     "eslint-import-resolver-node": "file:./resolvers/node",
     "eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1",
     "eslint-import-resolver-webpack": "file:./resolvers/webpack",
@@ -88,7 +88,7 @@
     "jackspeak": "=2.1.1",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",
-    "markdownlint-cli": "^0.35.0",
+    "markdownlint-cli": "^0.38.0",
     "mocha": "^3.5.3",
     "npm-which": "^3.0.1",
     "nyc": "^11.9.0",

From 48fec35fbe9d20f5c859a02d0e4acef70759c875 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 14 Dec 2023 10:37:05 -0800
Subject: [PATCH 650/767] [Deps] update `tsconfig-paths`

Thanks to https://github.com/dividab/tsconfig-paths/pull/260!

Closes #2447. Fixes #2652. Fixes #2890. Fixes #2751.

May help with #2617, #2765.
---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index b899f56919..b84f57e8e4 100644
--- a/package.json
+++ b/package.json
@@ -119,6 +119,6 @@
     "object.groupby": "^1.0.1",
     "object.values": "^1.1.7",
     "semver": "^6.3.1",
-    "tsconfig-paths": "^3.14.2"
+    "tsconfig-paths": "^3.15.0"
   }
 }

From ee5fadeffff68f2300bed7f67a310496cb969d61 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 14 Dec 2023 10:54:28 -0800
Subject: [PATCH 651/767] Bump to 2.29.1

---
 CHANGELOG.md | 8 +++++++-
 package.json | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a56216a7a6..b81ad61a61 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,9 +6,12 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.29.1] - 2023-12-14
+
 ### Fixed
 - [`no-extraneous-dependencies`]: ignore `export type { ... } from '...'` when `includeTypes` is `false` ([#2919], thanks [@Pandemic1617])
 - [`no-unused-modules`]: support export patterns with array destructuring ([#2930], thanks [@ljharb])
+- [Deps] update `tsconfig-paths` ([#2447], thanks [@domdomegg])
 
 ## [2.29.0] - 2023-10-22
 
@@ -1445,6 +1448,7 @@ for info on changes for earlier releases.
 [#2666]: https://github.com/import-js/eslint-plugin-import/issues/2666
 [#2665]: https://github.com/import-js/eslint-plugin-import/issues/2665
 [#2577]: https://github.com/import-js/eslint-plugin-import/issues/2577
+[#2447]: https://github.com/import-js/eslint-plugin-import/issues/2447
 [#2444]: https://github.com/import-js/eslint-plugin-import/issues/2444
 [#2412]: https://github.com/import-js/eslint-plugin-import/issues/2412
 [#2392]: https://github.com/import-js/eslint-plugin-import/issues/2392
@@ -1563,7 +1567,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.0...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.1...HEAD
+[2.29.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.0...v2.29.1
 [2.29.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.1...v2.29.0
 [2.28.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.0...v2.28.1
 [2.28.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...v2.28.0
@@ -1715,6 +1720,7 @@ for info on changes for earlier releases.
 [@devinrhode2]: https://github.com/devinrhode2
 [@devongovett]: https://github.com/devongovett
 [@dmnd]: https://github.com/dmnd
+[@domdomegg]: https://github.com/domdomegg
 [@duncanbeevers]: https://github.com/duncanbeevers
 [@dwardu]: https://github.com/dwardu
 [@echenley]: https://github.com/echenley
diff --git a/package.json b/package.json
index b84f57e8e4..5c0af48543 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.29.0",
+  "version": "2.29.1",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 678cc943898d89270d397fe4ab363c07415d7a5e Mon Sep 17 00:00:00 2001
From: mulztob <49060581+mulztob@users.noreply.github.com>
Date: Mon, 18 Dec 2023 08:43:34 +0100
Subject: [PATCH 652/767] [Docs] `no-extraneous-dependencies`: Make glob
 pattern description more explicit

---
 CHANGELOG.md                             | 7 ++++++-
 docs/rules/no-extraneous-dependencies.md | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b81ad61a61..13a201c90b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Changed
+- [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
+
 ## [2.29.1] - 2023-12-14
 
 ### Fixed
@@ -1101,6 +1104,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2944]: https://github.com/import-js/eslint-plugin-import/pull/2944
 [#2919]: https://github.com/import-js/eslint-plugin-import/pull/2919
 [#2884]: https://github.com/import-js/eslint-plugin-import/pull/2884
 [#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854
@@ -1835,6 +1839,7 @@ for info on changes for earlier releases.
 [@mplewis]: https://github.com/mplewis
 [@mrmckeb]: https://github.com/mrmckeb
 [@msvab]: https://github.com/msvab
+[@mulztob]: https://github.com/mulztob
 [@mx-bernhard]: https://github.com/mx-bernhard
 [@Nfinished]: https://github.com/Nfinished
 [@nickofthyme]: https://github.com/nickofthyme
@@ -1843,9 +1848,9 @@ for info on changes for earlier releases.
 [@ntdb]: https://github.com/ntdb
 [@nwalters512]: https://github.com/nwalters512
 [@ombene]: https://github.com/ombene
-[@Pandemic1617]: https://github.com/Pandemic1617
 [@ota-meshi]: https://github.com/ota-meshi
 [@OutdatedVersion]: https://github.com/OutdatedVersion
+[@Pandemic1617]: https://github.com/Pandemic1617
 [@panrafal]: https://github.com/panrafal
 [@paztis]: https://github.com/paztis
 [@pcorpet]: https://github.com/pcorpet
diff --git a/docs/rules/no-extraneous-dependencies.md b/docs/rules/no-extraneous-dependencies.md
index 547e5c2e57..848d5bb0da 100644
--- a/docs/rules/no-extraneous-dependencies.md
+++ b/docs/rules/no-extraneous-dependencies.md
@@ -32,7 +32,7 @@ You can also use an array of globs instead of literal booleans:
 "import/no-extraneous-dependencies": ["error", {"devDependencies": ["**/*.test.js", "**/*.spec.js"]}]
 ```
 
-When using an array of globs, the setting will be set to `true` (no errors reported) if the name of the file being linted matches a single glob in the array, and `false` otherwise.
+When using an array of globs, the setting will be set to `true` (no errors reported) if the name of the file being linted (i.e. not the imported file/module) matches a single glob in the array, and `false` otherwise.
 
 There are 2 boolean options to opt into checking extra imports that are normally ignored: `includeInternal`, which enables the checking of internal modules, and `includeTypes`, which enables checking of type imports in TypeScript.
 

From 6f0668c937a247d27c90cb391d4255fdfdd46a0f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 18 Dec 2023 18:22:00 -0800
Subject: [PATCH 653/767] [Dev Deps] pin `markdownlint-cli` to v0.35, because
 v0.36+ depends on a `glob` that breaks CI

See https://github.com/isaacs/jackspeak/issues/4
---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 5c0af48543..dbe14f24c3 100644
--- a/package.json
+++ b/package.json
@@ -88,7 +88,7 @@
     "jackspeak": "=2.1.1",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",
-    "markdownlint-cli": "^0.38.0",
+    "markdownlint-cli": "~0.35",
     "mocha": "^3.5.3",
     "npm-which": "^3.0.1",
     "nyc": "^11.9.0",

From e9489d8f7378d7bf78a33898b963aead48efe186 Mon Sep 17 00:00:00 2001
From: JW <jiangweixian1994@gmail.com>
Date: Sun, 17 Dec 2023 13:35:24 +0800
Subject: [PATCH 654/767] [New] `dynamic-import-chunkname`: add `allowEmpty`
 option to allow empty leading comments

---
 docs/rules/dynamic-import-chunkname.md      | 35 ++++++++++++++++++++-
 src/rules/dynamic-import-chunkname.js       |  9 ++++--
 tests/src/rules/dynamic-import-chunkname.js | 30 ++++++++++++++++++
 3 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/docs/rules/dynamic-import-chunkname.md b/docs/rules/dynamic-import-chunkname.md
index 35ae9df516..dd526c8913 100644
--- a/docs/rules/dynamic-import-chunkname.md
+++ b/docs/rules/dynamic-import-chunkname.md
@@ -15,7 +15,8 @@ You can also configure the regex format you'd like to accept for the webpackChun
 {
   "dynamic-import-chunkname": [2, {
     importFunctions: ["dynamicImport"],
-    webpackChunknameFormat: "[a-zA-Z0-57-9-/_]+"
+    webpackChunknameFormat: "[a-zA-Z0-57-9-/_]+",
+    allowEmpty: false
   }]
 }
 ```
@@ -87,6 +88,38 @@ The following patterns are valid:
   );
 ```
 
+### `allowEmpty: true`
+
+If you want to allow dynamic imports without a webpackChunkName, you can set `allowEmpty: true` in the rule config. This will allow dynamic imports without a leading comment, or with a leading comment that does not contain a webpackChunkName.
+
+Given `{ "allowEmpty": true }`:
+
+<!-- markdownlint-disable-next-line MD024 -- duplicate header -->
+### valid
+
+The following patterns are valid:
+
+```javascript
+import('someModule');
+
+import(
+  /* webpackChunkName: "someModule" */
+  'someModule',
+);
+```
+<!-- markdownlint-disable-next-line MD024 -- duplicate header -->
+### invalid
+
+The following patterns are invalid:
+
+```javascript
+// incorrectly formatted comment
+import(
+  /*webpackChunkName:"someModule"*/
+  'someModule',
+);
+```
+
 ## When Not To Use It
 
 If you don't care that webpack will autogenerate chunk names and may blow up browser caches and bundle size reports.
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index 96ceff2e16..a62e5c6c12 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -19,6 +19,9 @@ module.exports = {
             type: 'string',
           },
         },
+        allowEmpty: {
+          type: 'boolean',
+        },
         webpackChunknameFormat: {
           type: 'string',
         },
@@ -28,7 +31,7 @@ module.exports = {
 
   create(context) {
     const config = context.options[0];
-    const { importFunctions = [] } = config || {};
+    const { importFunctions = [], allowEmpty = false } = config || {};
     const { webpackChunknameFormat = '([0-9a-zA-Z-_/.]|\\[(request|index)\\])+' } = config || {};
 
     const paddedCommentRegex = /^ (\S[\s\S]+\S) $/;
@@ -42,7 +45,7 @@ module.exports = {
         ? sourceCode.getCommentsBefore(arg) // This method is available in ESLint >= 4.
         : sourceCode.getComments(arg).leading; // This method is deprecated in ESLint 7.
 
-      if (!leadingComments || leadingComments.length === 0) {
+      if ((!leadingComments || leadingComments.length === 0) && !allowEmpty) {
         context.report({
           node,
           message: 'dynamic imports require a leading comment with the webpack chunkname',
@@ -94,7 +97,7 @@ module.exports = {
         }
       }
 
-      if (!isChunknamePresent) {
+      if (!isChunknamePresent && !allowEmpty) {
         context.report({
           node,
           message:
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index 73617a6f36..c710507b26 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -12,6 +12,10 @@ const pickyCommentOptions = [{
   importFunctions: ['dynamicImport'],
   webpackChunknameFormat: pickyCommentFormat,
 }];
+const allowEmptyOptions = [{
+  importFunctions: ['dynamicImport'],
+  allowEmpty: true,
+}];
 const multipleImportFunctionOptions = [{
   importFunctions: ['dynamicImport', 'definitelyNotStaticImport'],
 }];
@@ -83,6 +87,19 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
     },
+    {
+      code: `import('test')`,
+      options: allowEmptyOptions,
+      parser,
+    },
+    {
+      code: `import(
+        /* webpackMode: "lazy" */
+        'test'
+      )`,
+      options: allowEmptyOptions,
+      parser,
+    },
     {
       code: `import(
         /* webpackChunkName: "someModule" */
@@ -975,6 +992,19 @@ context('TypeScript', () => {
 
     ruleTester.run('dynamic-import-chunkname', rule, {
       valid: [
+        {
+          code: `import('test')`,
+          options: allowEmptyOptions,
+          parser: typescriptParser,
+        },
+        {
+          code: `import(
+            /* webpackMode: "lazy" */
+            'test'
+          )`,
+          options: allowEmptyOptions,
+          parser: typescriptParser,
+        },
         {
           code: `import(
             /* webpackChunkName: "someModule" */

From 7a21f7e10f18c04473faadca94928af6b8e28009 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 29 Dec 2023 09:18:33 -0800
Subject: [PATCH 655/767] [meta] add missing changelog entry from #2942

---
 CHANGELOG.md | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 13a201c90b..3330dd331f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Added
+- [`dynamic-import-chunkname`]: add `allowEmpty` option to allow empty leading comments ([#2942], thanks [@JiangWeixian])
+
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
 
@@ -1105,6 +1108,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#2944]: https://github.com/import-js/eslint-plugin-import/pull/2944
+[#2942]: https://github.com/import-js/eslint-plugin-import/pull/2942
 [#2919]: https://github.com/import-js/eslint-plugin-import/pull/2919
 [#2884]: https://github.com/import-js/eslint-plugin-import/pull/2884
 [#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854
@@ -1774,6 +1778,7 @@ for info on changes for earlier releases.
 [@jeffshaver]: https://github.com/jeffshaver
 [@jf248]: https://github.com/jf248
 [@jfmengels]: https://github.com/jfmengels
+[@JiangWeixian]: https://github.com/JiangWeixian
 [@jimbolla]: https://github.com/jimbolla
 [@jkimbo]: https://github.com/jkimbo
 [@joaovieira]: https://github.com/joaovieira

From 1dc7fc66056c2b802aa9d72941846f08e1679544 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 14 Feb 2024 09:05:18 -0800
Subject: [PATCH 656/767] [Deps] update `array.prototype.findlastindex`,
 `hasown`, `object.groupby`

---
 package.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index dbe14f24c3..7d6d63e718 100644
--- a/package.json
+++ b/package.json
@@ -104,19 +104,19 @@
   },
   "dependencies": {
     "array-includes": "^3.1.7",
-    "array.prototype.findlastindex": "^1.2.3",
+    "array.prototype.findlastindex": "^1.2.4",
     "array.prototype.flat": "^1.3.2",
     "array.prototype.flatmap": "^1.3.2",
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
     "eslint-module-utils": "^2.8.0",
-    "hasown": "^2.0.0",
+    "hasown": "^2.0.1",
     "is-core-module": "^2.13.1",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.fromentries": "^2.0.7",
-    "object.groupby": "^1.0.1",
+    "object.groupby": "^1.0.2",
     "object.values": "^1.1.7",
     "semver": "^6.3.1",
     "tsconfig-paths": "^3.15.0"

From 4d298b5ea61c359a39ac8b2c49f88b18070f4773 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 14 Feb 2024 09:10:10 -0800
Subject: [PATCH 657/767] [patch] `no-unused-modules`: add console message to
 help debug #2866

---
 CHANGELOG.md                   | 2 ++
 src/rules/no-unused-modules.js | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3330dd331f..06cdb922e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
+- [`no-unused-modules`]: add console message to help debug [#2866]
 
 ## [2.29.1] - 2023-12-14
 
@@ -1111,6 +1112,7 @@ for info on changes for earlier releases.
 [#2942]: https://github.com/import-js/eslint-plugin-import/pull/2942
 [#2919]: https://github.com/import-js/eslint-plugin-import/pull/2919
 [#2884]: https://github.com/import-js/eslint-plugin-import/pull/2884
+[#2866]: https://github.com/import-js/eslint-plugin-import/pull/2866
 [#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854
 [#2851]: https://github.com/import-js/eslint-plugin-import/pull/2851
 [#2850]: https://github.com/import-js/eslint-plugin-import/pull/2850
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 8229d880ce..ec3425dacd 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -529,6 +529,10 @@ module.exports = {
 
       exports = exportList.get(file);
 
+      if (!exports) {
+        console.error(`file \`${file}\` has no exports. Please update to the latest, and if it still happens, report this on https://github.com/import-js/eslint-plugin-import/issues/2866!`);
+      }
+
       // special case: export * from
       const exportAll = exports.get(EXPORT_ALL_DECLARATION);
       if (typeof exportAll !== 'undefined' && exportedValue !== IMPORT_DEFAULT_SPECIFIER) {

From e55d05a85105769a563631ffcb55e818363ab8b6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 14 Feb 2024 09:30:58 -0800
Subject: [PATCH 658/767] [Dev Deps] pin `jsonc-parser` due to a breaking
 change

See https://github.com/microsoft/node-jsonc-parser/issues/85
---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index 7d6d63e718..638942f97c 100644
--- a/package.json
+++ b/package.json
@@ -86,6 +86,7 @@
     "glob": "^7.2.3",
     "in-publish": "^2.0.1",
     "jackspeak": "=2.1.1",
+    "jsonc-parser": "=3.2.0",
     "linklocal": "^2.8.2",
     "lodash.isarray": "^4.0.0",
     "markdownlint-cli": "~0.35",

From 20e3f297f9dd190eddb71e8277777ae7d583e7ef Mon Sep 17 00:00:00 2001
From: Josh Goldberg <git@joshuakgoldberg.com>
Date: Sat, 10 Feb 2024 17:44:15 -0500
Subject: [PATCH 659/767] [utils] [fix] `parse`: also delete
 `parserOptions.EXPERIMENTAL_useProjectService`

---
 utils/CHANGELOG.md | 5 +++++
 utils/parse.js     | 1 +
 2 files changed, 6 insertions(+)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index ae3588a390..9067cc1ef1 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Fixed
+- `parse`: also delete `parserOptions.EXPERIMENTAL_useProjectService` ([#2963], thanks [@JoshuaKGoldberg])
+
 ## v2.8.0 - 2023-04-14
 
 ### New
@@ -131,6 +134,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#2963]: https://github.com/import-js/eslint-plugin-import/pull/2963
 [#2755]: https://github.com/import-js/eslint-plugin-import/pull/2755
 [#2714]: https://github.com/import-js/eslint-plugin-import/pull/2714
 [#2523]: https://github.com/import-js/eslint-plugin-import/pull/2523
@@ -169,6 +173,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@hulkish]: https://github.com/hulkish
 [@Hypnosphi]: https://github.com/Hypnosphi
 [@iamnapo]: https://github.com/iamnapo
+[@JoshuaKGoldberg]: https://github.com/JoshuaKGoldberg
 [@JounQin]: https://github.com/JounQin
 [@kaiyoma]: https://github.com/kaiyoma
 [@leipert]: https://github.com/leipert
diff --git a/utils/parse.js b/utils/parse.js
index 7646b3177c..bddd2d913d 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -81,6 +81,7 @@ exports.default = function parse(path, content, context) {
   // "project" or "projects" in parserOptions. Removing these options means the parser will
   // only parse one file in isolate mode, which is much, much faster.
   // https://github.com/import-js/eslint-plugin-import/issues/1408#issuecomment-509298962
+  delete parserOptions.EXPERIMENTAL_useProjectService;
   delete parserOptions.project;
   delete parserOptions.projects;
 

From 3c7f99062f57d879058f690c51e4866fbe635b8f Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Fri, 23 Feb 2024 16:43:11 -0800
Subject: [PATCH 660/767] [utils] add types

---
 .eslintrc                 |  4 +--
 utils/.attw.json          |  5 +++
 utils/.npmignore          |  1 +
 utils/CHANGELOG.md        |  3 ++
 utils/ModuleCache.d.ts    | 22 +++++++++++++
 utils/ModuleCache.js      | 38 ++++++++++++-----------
 utils/declaredScope.d.ts  |  8 +++++
 utils/declaredScope.js    |  3 +-
 utils/hash.d.ts           | 14 +++++++++
 utils/hash.js             |  8 +++--
 utils/ignore.d.ts         | 12 ++++++++
 utils/ignore.js           | 12 ++++++--
 utils/module-require.d.ts |  3 ++
 utils/module-require.js   |  5 +++
 utils/moduleVisitor.d.ts  | 26 ++++++++++++++++
 utils/moduleVisitor.js    | 51 ++++++++++++++++++------------
 utils/package.json        | 12 ++++++++
 utils/parse.d.ts          | 11 +++++++
 utils/parse.js            | 34 +++++++++++++++++---
 utils/pkgDir.d.ts         |  3 ++
 utils/pkgDir.js           |  1 +
 utils/pkgUp.d.ts          |  3 ++
 utils/pkgUp.js            |  4 +++
 utils/readPkgUp.d.ts      |  5 +++
 utils/readPkgUp.js        |  2 ++
 utils/resolve.d.ts        | 30 ++++++++++++++++++
 utils/resolve.js          | 65 +++++++++++++++++++++++++--------------
 utils/tsconfig.json       | 49 +++++++++++++++++++++++++++++
 utils/types.d.ts          |  9 ++++++
 utils/unambiguous.d.ts    |  7 +++++
 utils/unambiguous.js      |  5 ++-
 utils/visit.d.ts          |  9 ++++++
 utils/visit.js            | 13 +++++---
 33 files changed, 397 insertions(+), 80 deletions(-)
 create mode 100644 utils/.attw.json
 create mode 100644 utils/.npmignore
 create mode 100644 utils/ModuleCache.d.ts
 create mode 100644 utils/declaredScope.d.ts
 create mode 100644 utils/hash.d.ts
 create mode 100644 utils/ignore.d.ts
 create mode 100644 utils/module-require.d.ts
 create mode 100644 utils/moduleVisitor.d.ts
 create mode 100644 utils/parse.d.ts
 create mode 100644 utils/pkgDir.d.ts
 create mode 100644 utils/pkgUp.d.ts
 create mode 100644 utils/readPkgUp.d.ts
 create mode 100644 utils/resolve.d.ts
 create mode 100644 utils/tsconfig.json
 create mode 100644 utils/types.d.ts
 create mode 100644 utils/unambiguous.d.ts
 create mode 100644 utils/visit.d.ts

diff --git a/.eslintrc b/.eslintrc
index 3c9c658f2f..ddf7bc5628 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -209,10 +209,10 @@
                     "exports": "always-multiline",
                     "functions": "never"
                 }],
-                "prefer-destructuring": "warn",
+                "prefer-destructuring": "off",
                 "prefer-object-spread": "off",
                 "prefer-rest-params": "off",
-                "prefer-spread": "warn",
+                "prefer-spread": "off",
                 "prefer-template": "off",
             }
         },
diff --git a/utils/.attw.json b/utils/.attw.json
new file mode 100644
index 0000000000..45dd01e12f
--- /dev/null
+++ b/utils/.attw.json
@@ -0,0 +1,5 @@
+{
+  "ignoreRules": [
+    "cjs-only-exports-default"
+  ]
+}
diff --git a/utils/.npmignore b/utils/.npmignore
new file mode 100644
index 0000000000..366f3ebb6e
--- /dev/null
+++ b/utils/.npmignore
@@ -0,0 +1 @@
+.attw.json
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 9067cc1ef1..a0aa43da75 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -8,6 +8,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - `parse`: also delete `parserOptions.EXPERIMENTAL_useProjectService` ([#2963], thanks [@JoshuaKGoldberg])
 
+### Changed
+- add types (thanks [@ljharb])
+
 ## v2.8.0 - 2023-04-14
 
 ### New
diff --git a/utils/ModuleCache.d.ts b/utils/ModuleCache.d.ts
new file mode 100644
index 0000000000..72a72a0699
--- /dev/null
+++ b/utils/ModuleCache.d.ts
@@ -0,0 +1,22 @@
+import type { ESLintSettings } from "./types";
+
+export type CacheKey = unknown;
+export type CacheObject = {
+    result: unknown;
+    lastSeen: ReturnType<typeof process.hrtime>;
+};
+
+declare class ModuleCache {
+    map: Map<CacheKey, CacheObject>;
+
+    constructor(map?: Map<CacheKey, CacheObject>);
+
+    get<T>(cacheKey: CacheKey, settings: ESLintSettings): T | undefined;
+
+    set<T>(cacheKey: CacheKey, result: T): T;
+
+    static getSettings(settings: ESLintSettings): { lifetime: number } & Omit<ESLintSettings['import/cache'], 'lifetime'>;
+}
+export default ModuleCache;
+
+export type { ModuleCache }
diff --git a/utils/ModuleCache.js b/utils/ModuleCache.js
index 4b1edc0eff..24c76849dd 100644
--- a/utils/ModuleCache.js
+++ b/utils/ModuleCache.js
@@ -4,26 +4,26 @@ exports.__esModule = true;
 
 const log = require('debug')('eslint-module-utils:ModuleCache');
 
+/** @type {import('./ModuleCache').ModuleCache} */
 class ModuleCache {
+  /** @param {typeof import('./ModuleCache').ModuleCache.prototype.map} map */
   constructor(map) {
-    this.map = map || new Map();
+    this.map = map || /** @type {{typeof import('./ModuleCache').ModuleCache.prototype.map} */ new Map();
   }
 
-  /**
-   * returns value for returning inline
-   * @param {[type]} cacheKey [description]
-   * @param {[type]} result   [description]
-   */
+  /** @type {typeof import('./ModuleCache').ModuleCache.prototype.set} */
   set(cacheKey, result) {
     this.map.set(cacheKey, { result, lastSeen: process.hrtime() });
     log('setting entry for', cacheKey);
     return result;
   }
 
+  /** @type {typeof import('./ModuleCache').ModuleCache.prototype.get} */
   get(cacheKey, settings) {
     if (this.map.has(cacheKey)) {
       const f = this.map.get(cacheKey);
       // check freshness
+      // @ts-expect-error TS can't narrow properly from `has` and `get`
       if (process.hrtime(f.lastSeen)[0] < settings.lifetime) { return f.result; }
     } else {
       log('cache miss for', cacheKey);
@@ -32,19 +32,21 @@ class ModuleCache {
     return undefined;
   }
 
-}
-
-ModuleCache.getSettings = function (settings) {
-  const cacheSettings = Object.assign({
-    lifetime: 30,  // seconds
-  }, settings['import/cache']);
+  /** @type {typeof import('./ModuleCache').ModuleCache.getSettings} */
+  static getSettings(settings) {
+    /** @type {ReturnType<typeof ModuleCache.getSettings>} */
+    const cacheSettings = Object.assign({
+      lifetime: 30,  // seconds
+    }, settings['import/cache']);
+
+    // parse infinity
+    // @ts-expect-error the lack of type overlap is because we're abusing `cacheSettings` as a temporary object
+    if (cacheSettings.lifetime === '∞' || cacheSettings.lifetime === 'Infinity') {
+      cacheSettings.lifetime = Infinity;
+    }
 
-  // parse infinity
-  if (cacheSettings.lifetime === '∞' || cacheSettings.lifetime === 'Infinity') {
-    cacheSettings.lifetime = Infinity;
+    return cacheSettings;
   }
-
-  return cacheSettings;
-};
+}
 
 exports.default = ModuleCache;
diff --git a/utils/declaredScope.d.ts b/utils/declaredScope.d.ts
new file mode 100644
index 0000000000..e37200d870
--- /dev/null
+++ b/utils/declaredScope.d.ts
@@ -0,0 +1,8 @@
+import { Rule, Scope } from 'eslint';
+
+declare function declaredScope(
+    context: Rule.RuleContext,
+    name: string
+): Scope.Scope['type'] | undefined;
+
+export default declaredScope;
diff --git a/utils/declaredScope.js b/utils/declaredScope.js
index dd2a20149f..0f0a3d9458 100644
--- a/utils/declaredScope.js
+++ b/utils/declaredScope.js
@@ -2,9 +2,10 @@
 
 exports.__esModule = true;
 
+/** @type {import('./declaredScope').default} */
 exports.default = function declaredScope(context, name) {
   const references = context.getScope().references;
   const reference = references.find((x) => x.identifier.name === name);
-  if (!reference) { return undefined; }
+  if (!reference || !reference.resolved) { return undefined; }
   return reference.resolved.scope.type;
 };
diff --git a/utils/hash.d.ts b/utils/hash.d.ts
new file mode 100644
index 0000000000..5e4cf471bd
--- /dev/null
+++ b/utils/hash.d.ts
@@ -0,0 +1,14 @@
+import type { Hash } from 'crypto';
+
+declare function hashArray(value: Array<unknown>, hash?: Hash): Hash;
+
+declare function hashObject<T extends object>(value: T, hash?: Hash): Hash;
+
+declare function hashify(
+    value: Array<unknown> | object | unknown,
+    hash?: Hash,
+): Hash;
+
+export default hashify;
+
+export { hashArray, hashObject };
diff --git a/utils/hash.js b/utils/hash.js
index b9bff25bd9..b3ce618b54 100644
--- a/utils/hash.js
+++ b/utils/hash.js
@@ -11,6 +11,7 @@ const createHash = require('crypto').createHash;
 
 const stringify = JSON.stringify;
 
+/** @type {import('./hash').default} */
 function hashify(value, hash) {
   if (!hash) { hash = createHash('sha256'); }
 
@@ -26,6 +27,7 @@ function hashify(value, hash) {
 }
 exports.default = hashify;
 
+/** @type {import('./hash').hashArray} */
 function hashArray(array, hash) {
   if (!hash) { hash = createHash('sha256'); }
 
@@ -41,13 +43,15 @@ function hashArray(array, hash) {
 hashify.array = hashArray;
 exports.hashArray = hashArray;
 
-function hashObject(object, hash) {
-  if (!hash) { hash = createHash('sha256'); }
+/** @type {import('./hash').hashObject} */
+function hashObject(object, optionalHash) {
+  const hash = optionalHash || createHash('sha256');
 
   hash.update('{');
   Object.keys(object).sort().forEach((key) => {
     hash.update(stringify(key));
     hash.update(':');
+    // @ts-expect-error the key is guaranteed to exist on the object here
     hashify(object[key], hash);
     hash.update(',');
   });
diff --git a/utils/ignore.d.ts b/utils/ignore.d.ts
new file mode 100644
index 0000000000..53953b33e9
--- /dev/null
+++ b/utils/ignore.d.ts
@@ -0,0 +1,12 @@
+import { Rule } from 'eslint';
+import type { ESLintSettings, Extension } from './types';
+
+declare function ignore(path: string, context: Rule.RuleContext): boolean;
+
+declare function getFileExtensions(settings: ESLintSettings): Set<Extension>;
+
+declare function hasValidExtension(path: string, context: Rule.RuleContext): path is `${string}${Extension}`;
+
+export default ignore;
+
+export { getFileExtensions, hasValidExtension }
diff --git a/utils/ignore.js b/utils/ignore.js
index 960538e706..59ac821eb8 100644
--- a/utils/ignore.js
+++ b/utils/ignore.js
@@ -7,7 +7,10 @@ const extname = require('path').extname;
 const log = require('debug')('eslint-plugin-import:utils:ignore');
 
 // one-shot memoized
-let cachedSet; let lastSettings;
+/** @type {Set<import('./types').Extension>} */ let cachedSet;
+/** @type {import('./types').ESLintSettings} */ let lastSettings;
+
+/** @type {(context: import('eslint').Rule.RuleContext) => Set<import('./types').Extension>} */
 function validExtensions(context) {
   if (cachedSet && context.settings === lastSettings) {
     return cachedSet;
@@ -18,8 +21,10 @@ function validExtensions(context) {
   return cachedSet;
 }
 
+/** @type {import('./ignore').getFileExtensions} */
 function makeValidExtensionSet(settings) {
   // start with explicit JS-parsed extensions
+  /** @type {Set<import('./types').Extension>} */
   const exts = new Set(settings['import/extensions'] || ['.js']);
 
   // all alternate parser extensions are also valid
@@ -37,6 +42,7 @@ function makeValidExtensionSet(settings) {
 }
 exports.getFileExtensions = makeValidExtensionSet;
 
+/** @type {import('./ignore').default} */
 exports.default = function ignore(path, context) {
   // check extension whitelist first (cheap)
   if (!hasValidExtension(path, context)) { return true; }
@@ -55,7 +61,9 @@ exports.default = function ignore(path, context) {
   return false;
 };
 
+/** @type {import('./ignore').hasValidExtension} */
 function hasValidExtension(path, context) {
-  return validExtensions(context).has(extname(path));
+  // eslint-disable-next-line no-extra-parens
+  return validExtensions(context).has(/** @type {import('./types').Extension} */ (extname(path)));
 }
 exports.hasValidExtension = hasValidExtension;
diff --git a/utils/module-require.d.ts b/utils/module-require.d.ts
new file mode 100644
index 0000000000..91df90d616
--- /dev/null
+++ b/utils/module-require.d.ts
@@ -0,0 +1,3 @@
+declare function moduleRequire<T>(p: string): T;
+
+export default moduleRequire;
diff --git a/utils/module-require.js b/utils/module-require.js
index 96ef82ba51..14006c5dc6 100644
--- a/utils/module-require.js
+++ b/utils/module-require.js
@@ -6,23 +6,28 @@ const Module = require('module');
 const path = require('path');
 
 // borrowed from babel-eslint
+/** @type {(filename: string) => Module} */
 function createModule(filename) {
   const mod = new Module(filename);
   mod.filename = filename;
+  // @ts-expect-error _nodeModulesPaths are undocumented
   mod.paths = Module._nodeModulePaths(path.dirname(filename));
   return mod;
 }
 
+/** @type {import('./module-require').default} */
 exports.default = function moduleRequire(p) {
   try {
     // attempt to get espree relative to eslint
     const eslintPath = require.resolve('eslint');
     const eslintModule = createModule(eslintPath);
+    // @ts-expect-error _resolveFilename is undocumented
     return require(Module._resolveFilename(p, eslintModule));
   } catch (err) { /* ignore */ }
 
   try {
     // try relative to entry point
+    // @ts-expect-error TODO: figure out what this is
     return require.main.require(p);
   } catch (err) { /* ignore */ }
 
diff --git a/utils/moduleVisitor.d.ts b/utils/moduleVisitor.d.ts
new file mode 100644
index 0000000000..6f30186d71
--- /dev/null
+++ b/utils/moduleVisitor.d.ts
@@ -0,0 +1,26 @@
+import type { Rule } from 'eslint';
+import type { Node } from 'estree';
+
+type Visitor = (source: Node, importer: unknown) => any;
+
+type Options = {
+    amd?: boolean;
+    commonjs?: boolean;
+    esmodule?: boolean;
+    ignore?: string[];
+};
+
+declare function moduleVisitor(
+    visitor: Visitor,
+    options?: Options,
+): object;
+
+export default moduleVisitor;
+
+export type Schema = NonNullable<Rule.RuleModule['schema']>;
+
+declare function makeOptionsSchema(additionalProperties?: Partial<Schema>): Schema
+
+declare const optionsSchema: Schema;
+
+export { makeOptionsSchema, optionsSchema };
diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js
index c312ca2d45..acdee6774f 100644
--- a/utils/moduleVisitor.js
+++ b/utils/moduleVisitor.js
@@ -2,50 +2,58 @@
 
 exports.__esModule = true;
 
+/** @typedef {import('estree').Node} Node */
+/** @typedef {{ arguments: import('estree').CallExpression['arguments'], callee: Node }} Call */
+/** @typedef {import('estree').ImportDeclaration | import('estree').ExportNamedDeclaration | import('estree').ExportAllDeclaration} Declaration */
+
 /**
  * Returns an object of node visitors that will call
  * 'visitor' with every discovered module path.
  *
- * todo: correct function prototype for visitor
- * @param  {Function(String)} visitor [description]
- * @param  {[type]} options [description]
- * @return {object}
+ * @type {(import('./moduleVisitor').default)}
  */
 exports.default = function visitModules(visitor, options) {
+  const ignore = options && options.ignore;
+  const amd = !!(options && options.amd);
+  const commonjs = !!(options && options.commonjs);
   // if esmodule is not explicitly disabled, it is assumed to be enabled
-  options = Object.assign({ esmodule: true }, options);
+  const esmodule = !!Object.assign({ esmodule: true }, options).esmodule;
 
-  let ignoreRegExps = [];
-  if (options.ignore != null) {
-    ignoreRegExps = options.ignore.map((p) => new RegExp(p));
-  }
+  const ignoreRegExps = ignore == null ? [] : ignore.map((p) => new RegExp(p));
 
+  /** @type {(source: undefined | null | import('estree').Literal, importer: Parameters<typeof visitor>[1]) => void} */
   function checkSourceValue(source, importer) {
     if (source == null) { return; } //?
 
     // handle ignore
-    if (ignoreRegExps.some((re) => re.test(source.value))) { return; }
+    if (ignoreRegExps.some((re) => re.test(String(source.value)))) { return; }
 
     // fire visitor
     visitor(source, importer);
   }
 
   // for import-y declarations
+  /** @type {(node: Declaration) => void} */
   function checkSource(node) {
     checkSourceValue(node.source, node);
   }
 
   // for esmodule dynamic `import()` calls
+  /** @type {(node: import('estree').ImportExpression | import('estree').CallExpression) => void} */
   function checkImportCall(node) {
+    /** @type {import('estree').Expression | import('estree').Literal | import('estree').CallExpression['arguments'][0]} */
     let modulePath;
     // refs https://github.com/estree/estree/blob/HEAD/es2020.md#importexpression
     if (node.type === 'ImportExpression') {
       modulePath = node.source;
     } else if (node.type === 'CallExpression') {
+      // @ts-expect-error this structure is from an older version of eslint
       if (node.callee.type !== 'Import') { return; }
       if (node.arguments.length !== 1) { return; }
 
       modulePath = node.arguments[0];
+    } else {
+      throw new TypeError('this should be unreachable');
     }
 
     if (modulePath.type !== 'Literal') { return; }
@@ -56,6 +64,7 @@ exports.default = function visitModules(visitor, options) {
 
   // for CommonJS `require` calls
   // adapted from @mctep: https://git.io/v4rAu
+  /** @type {(call: Call) => void} */
   function checkCommon(call) {
     if (call.callee.type !== 'Identifier') { return; }
     if (call.callee.name !== 'require') { return; }
@@ -68,6 +77,7 @@ exports.default = function visitModules(visitor, options) {
     checkSourceValue(modulePath, call);
   }
 
+  /** @type {(call: Call) => void} */
   function checkAMD(call) {
     if (call.callee.type !== 'Identifier') { return; }
     if (call.callee.name !== 'require' && call.callee.name !== 'define') { return; }
@@ -77,6 +87,7 @@ exports.default = function visitModules(visitor, options) {
     if (modules.type !== 'ArrayExpression') { return; }
 
     for (const element of modules.elements) {
+      if (!element) { continue; }
       if (element.type !== 'Literal') { continue; }
       if (typeof element.value !== 'string') { continue; }
 
@@ -92,7 +103,7 @@ exports.default = function visitModules(visitor, options) {
   }
 
   const visitors = {};
-  if (options.esmodule) {
+  if (esmodule) {
     Object.assign(visitors, {
       ImportDeclaration: checkSource,
       ExportNamedDeclaration: checkSource,
@@ -102,12 +113,12 @@ exports.default = function visitModules(visitor, options) {
     });
   }
 
-  if (options.commonjs || options.amd) {
+  if (commonjs || amd) {
     const currentCallExpression = visitors.CallExpression;
-    visitors.CallExpression = function (call) {
+    visitors.CallExpression = /** @type {(call: Call) => void} */ function (call) {
       if (currentCallExpression) { currentCallExpression(call); }
-      if (options.commonjs) { checkCommon(call); }
-      if (options.amd) { checkAMD(call); }
+      if (commonjs) { checkCommon(call); }
+      if (amd) { checkAMD(call); }
     };
   }
 
@@ -115,10 +126,11 @@ exports.default = function visitModules(visitor, options) {
 };
 
 /**
- * make an options schema for the module visitor, optionally
- * adding extra fields.
+ * make an options schema for the module visitor, optionally adding extra fields.
+ * @type {import('./moduleVisitor').makeOptionsSchema}
  */
 function makeOptionsSchema(additionalProperties) {
+  /** @type {import('./moduleVisitor').Schema} */
   const base =  {
     type: 'object',
     properties: {
@@ -137,6 +149,7 @@ function makeOptionsSchema(additionalProperties) {
 
   if (additionalProperties) {
     for (const key in additionalProperties) {
+      // @ts-expect-error TS always has trouble with arbitrary object assignment/mutation
       base.properties[key] = additionalProperties[key];
     }
   }
@@ -146,8 +159,6 @@ function makeOptionsSchema(additionalProperties) {
 exports.makeOptionsSchema = makeOptionsSchema;
 
 /**
- * json schema object for options parameter. can be used to build
- * rule options schema object.
- * @type {Object}
+ * json schema object for options parameter. can be used to build rule options schema object.
  */
 exports.optionsSchema = makeOptionsSchema();
diff --git a/utils/package.json b/utils/package.json
index d56c442b1a..04c338b1a8 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -7,6 +7,7 @@
   },
   "scripts": {
     "prepublishOnly": "cp ../{LICENSE,.npmrc} ./",
+    "tsc": "tsc -p .",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "repository": {
@@ -28,9 +29,20 @@
   "dependencies": {
     "debug": "^3.2.7"
   },
+  "devDependencies": {
+    "@types/debug": "^4.1.12",
+    "@types/eslint": "^8.56.3",
+    "@types/node": "^20.11.20",
+    "typescript": "next"
+  },
   "peerDependenciesMeta": {
     "eslint": {
       "optional": true
     }
+  },
+  "publishConfig": {
+    "ignore": [
+      ".attw.json"
+    ]
   }
 }
diff --git a/utils/parse.d.ts b/utils/parse.d.ts
new file mode 100644
index 0000000000..f92ab3edc6
--- /dev/null
+++ b/utils/parse.d.ts
@@ -0,0 +1,11 @@
+import { AST, Rule } from 'eslint';
+
+
+
+declare function parse(
+    path: string,
+    content: string,
+    context: Rule.RuleContext
+): AST.Program | null | undefined;
+
+export default parse;
diff --git a/utils/parse.js b/utils/parse.js
index bddd2d913d..804186ca97 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -2,12 +2,16 @@
 
 exports.__esModule = true;
 
+/** @typedef {`.${string}`} Extension  */
+/** @typedef {NonNullable<import('eslint').Rule.RuleContext['settings']> & { 'import/extensions'?: Extension[], 'import/parsers'?: { [k: string]: Extension[] }, 'import/cache'?: { lifetime: number | '∞' | 'Infinity' } }} ESLintSettings */
+
 const moduleRequire = require('./module-require').default;
 const extname = require('path').extname;
 const fs = require('fs');
 
 const log = require('debug')('eslint-plugin-import:parse');
 
+/** @type {(parserPath: NonNullable<import('eslint').Rule.RuleContext['parserPath']>) => unknown} */
 function getBabelEslintVisitorKeys(parserPath) {
   if (parserPath.endsWith('index.js')) {
     const hypotheticalLocation = parserPath.replace('index.js', 'visitor-keys.js');
@@ -19,6 +23,7 @@ function getBabelEslintVisitorKeys(parserPath) {
   return null;
 }
 
+/** @type {(parserPath: import('eslint').Rule.RuleContext['parserPath'], parserInstance: { VisitorKeys: unknown }, parsedResult?: { visitorKeys?: unknown }) => unknown} */
 function keysFromParser(parserPath, parserInstance, parsedResult) {
   // Exposed by @typescript-eslint/parser and @babel/eslint-parser
   if (parsedResult && parsedResult.visitorKeys) {
@@ -35,22 +40,28 @@ function keysFromParser(parserPath, parserInstance, parsedResult) {
 
 // this exists to smooth over the unintentional breaking change in v2.7.
 // TODO, semver-major: avoid mutating `ast` and return a plain object instead.
+/** @type {<T extends import('eslint').AST.Program>(ast: T, visitorKeys: unknown) => T} */
 function makeParseReturn(ast, visitorKeys) {
   if (ast) {
+    // @ts-expect-error see TODO
     ast.visitorKeys = visitorKeys;
+    // @ts-expect-error see TODO
     ast.ast = ast;
   }
   return ast;
 }
 
+/** @type {(text: string) => string} */
 function stripUnicodeBOM(text) {
   return text.charCodeAt(0) === 0xFEFF ? text.slice(1) : text;
 }
 
+/** @type {(text: string) => string} */
 function transformHashbang(text) {
   return text.replace(/^#!([^\r\n]+)/u, (_, captured) => `//${captured}`);
 }
 
+/** @type {import('./parse').default} */
 exports.default = function parse(path, content, context) {
   if (context == null) { throw new Error('need context to parse properly'); }
 
@@ -97,10 +108,12 @@ exports.default = function parse(path, content, context) {
     try {
       const parserRaw = parser.parseForESLint(content, parserOptions);
       ast = parserRaw.ast;
+      // @ts-expect-error TODO: FIXME
       return makeParseReturn(ast, keysFromParser(parserOrPath, parser, parserRaw));
     } catch (e) {
       console.warn();
       console.warn('Error while parsing ' + parserOptions.filePath);
+      // @ts-expect-error e is almost certainly an Error here
       console.warn('Line ' + e.lineNumber + ', column ' + e.column + ': ' + e.message);
     }
     if (!ast || typeof ast !== 'object') {
@@ -109,34 +122,45 @@ exports.default = function parse(path, content, context) {
         '`parseForESLint` from parser `' + (typeof parserOrPath === 'string' ? parserOrPath : '`context.languageOptions.parser`') + '` is invalid and will just be ignored'
       );
     } else {
+      // @ts-expect-error TODO: FIXME
       return makeParseReturn(ast, keysFromParser(parserOrPath, parser, undefined));
     }
   }
 
   const ast = parser.parse(content, parserOptions);
+  // @ts-expect-error TODO: FIXME
   return makeParseReturn(ast, keysFromParser(parserOrPath, parser, undefined));
 };
 
+/** @type {(path: string, context: import('eslint').Rule.RuleContext) => string | null | (import('eslint').Linter.ParserModule)} */
 function getParser(path, context) {
   const parserPath = getParserPath(path, context);
   if (parserPath) {
     return parserPath;
   }
-  const isFlat = context.languageOptions
-    && context.languageOptions.parser
+  if (
+    !!context.languageOptions
+    && !!context.languageOptions.parser
     && typeof context.languageOptions.parser !== 'string'
     && (
+      // @ts-expect-error TODO: figure out a better type
       typeof context.languageOptions.parser.parse === 'function'
+      // @ts-expect-error TODO: figure out a better type
       || typeof context.languageOptions.parser.parseForESLint === 'function'
-    );
+    )
+  ) {
+    return context.languageOptions.parser;
+  }
 
-  return isFlat ? context.languageOptions.parser : null;
+  return null;
 }
 
+/** @type {(path: string, context: import('eslint').Rule.RuleContext & { settings?: ESLintSettings }) => import('eslint').Rule.RuleContext['parserPath']} */
 function getParserPath(path, context) {
   const parsers = context.settings['import/parsers'];
   if (parsers != null) {
-    const extension = extname(path);
+    // eslint-disable-next-line no-extra-parens
+    const extension = /** @type {Extension} */ (extname(path));
     for (const parserPath in parsers) {
       if (parsers[parserPath].indexOf(extension) > -1) {
         // use this alternate parser
diff --git a/utils/pkgDir.d.ts b/utils/pkgDir.d.ts
new file mode 100644
index 0000000000..af01e2e9bf
--- /dev/null
+++ b/utils/pkgDir.d.ts
@@ -0,0 +1,3 @@
+declare function pkgDir(cwd: string): string | null;
+
+export default pkgDir;
diff --git a/utils/pkgDir.js b/utils/pkgDir.js
index 34412202f1..84c334680a 100644
--- a/utils/pkgDir.js
+++ b/utils/pkgDir.js
@@ -5,6 +5,7 @@ const pkgUp = require('./pkgUp').default;
 
 exports.__esModule = true;
 
+/** @type {import('./pkgDir').default} */
 exports.default = function (cwd) {
   const fp = pkgUp({ cwd });
   return fp ? path.dirname(fp) : null;
diff --git a/utils/pkgUp.d.ts b/utils/pkgUp.d.ts
new file mode 100644
index 0000000000..6382457bec
--- /dev/null
+++ b/utils/pkgUp.d.ts
@@ -0,0 +1,3 @@
+declare function pkgUp(opts?: { cwd?: string }): string | null;
+
+export default pkgUp;
diff --git a/utils/pkgUp.js b/utils/pkgUp.js
index 889f62265f..076e59fd76 100644
--- a/utils/pkgUp.js
+++ b/utils/pkgUp.js
@@ -31,10 +31,13 @@ const path = require('path');
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+/** @type {(filename: string | string[], cwd?: string) => string | null} */
 function findUp(filename, cwd) {
   let dir = path.resolve(cwd || '');
   const root = path.parse(dir).root;
 
+  /** @type {string[]} */ // @ts-expect-error TS sucks with concat
   const filenames = [].concat(filename);
 
   // eslint-disable-next-line no-constant-condition
@@ -52,6 +55,7 @@ function findUp(filename, cwd) {
   }
 }
 
+/** @type {import('./pkgUp').default} */
 exports.default = function pkgUp(opts) {
   return findUp('package.json', opts && opts.cwd);
 };
diff --git a/utils/readPkgUp.d.ts b/utils/readPkgUp.d.ts
new file mode 100644
index 0000000000..5fc1668879
--- /dev/null
+++ b/utils/readPkgUp.d.ts
@@ -0,0 +1,5 @@
+import pkgUp from './pkgUp';
+
+declare function readPkgUp(opts?: Parameters<typeof pkgUp>[0]): {} | { pkg: string, path: string };
+
+export default readPkgUp;
diff --git a/utils/readPkgUp.js b/utils/readPkgUp.js
index d34fa6c818..08371931f2 100644
--- a/utils/readPkgUp.js
+++ b/utils/readPkgUp.js
@@ -5,6 +5,7 @@ exports.__esModule = true;
 const fs = require('fs');
 const pkgUp = require('./pkgUp').default;
 
+/** @type {(str: string) => string} */
 function stripBOM(str) {
   return str.replace(/^\uFEFF/, '');
 }
@@ -35,6 +36,7 @@ function stripBOM(str) {
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+/** @type {import('./readPkgUp').default} */
 exports.default = function readPkgUp(opts) {
   const fp = pkgUp(opts);
 
diff --git a/utils/resolve.d.ts b/utils/resolve.d.ts
new file mode 100644
index 0000000000..bb885bcfaf
--- /dev/null
+++ b/utils/resolve.d.ts
@@ -0,0 +1,30 @@
+import type { Rule } from 'eslint';
+
+import type ModuleCache from './ModuleCache';
+import type { ESLintSettings } from './types';
+
+export type ResultNotFound = { found: false, path?: undefined };
+export type ResultFound = { found: true, path: string | null };
+export type ResolvedResult = ResultNotFound | ResultFound;
+
+export type ResolverResolve = (modulePath: string, sourceFile:string, config: unknown) => ResolvedResult;
+export type ResolverResolveImport = (modulePath: string, sourceFile:string, config: unknown) => string | undefined;
+export type Resolver = { interfaceVersion?: 1 | 2, resolve: ResolverResolve, resolveImport: ResolverResolveImport };
+
+declare function resolve(
+    p: string,
+    context: Rule.RuleContext,
+): ResolvedResult['path'];
+
+export default resolve;
+
+declare function fileExistsWithCaseSync(
+    filepath: string | null,
+    cacheSettings: ESLintSettings,
+    strict: boolean
+): boolean | ReturnType<typeof ModuleCache.prototype.get>;
+
+declare function relative(modulePath: string, sourceFile: string, settings: ESLintSettings): ResolvedResult['path'];
+
+
+export { fileExistsWithCaseSync, relative };
diff --git a/utils/resolve.js b/utils/resolve.js
index 0ed5bdb0c9..05f7b35abf 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -19,16 +19,22 @@ const fileExistsCache = new ModuleCache();
 
 // Polyfill Node's `Module.createRequireFromPath` if not present (added in Node v10.12.0)
 // Use `Module.createRequire` if available (added in Node v12.2.0)
-const createRequire = Module.createRequire || Module.createRequireFromPath || function (filename) {
-  const mod = new Module(filename, null);
-  mod.filename = filename;
-  mod.paths = Module._nodeModulePaths(path.dirname(filename));
-
-  mod._compile(`module.exports = require;`, filename);
-
-  return mod.exports;
-};
-
+const createRequire = Module.createRequire
+  // @ts-expect-error this only exists in older node
+  || Module.createRequireFromPath
+  || /** @type {(filename: string) => unknown} */ function (filename) {
+    const mod = new Module(filename, void null);
+    mod.filename = filename;
+    // @ts-expect-error _nodeModulePaths is undocumented
+    mod.paths = Module._nodeModulePaths(path.dirname(filename));
+
+    // @ts-expect-error _compile is undocumented
+    mod._compile(`module.exports = require;`, filename);
+
+    return mod.exports;
+  };
+
+/** @type {<T extends string>(target: T, sourceFile?: string | null | undefined) => undefined | ReturnType<typeof require>} */
 function tryRequire(target, sourceFile) {
   let resolved;
   try {
@@ -52,6 +58,7 @@ function tryRequire(target, sourceFile) {
 }
 
 // https://stackoverflow.com/a/27382838
+/** @type {import('./resolve').fileExistsWithCaseSync} */
 exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings, strict) {
   // don't care if the FS is case-sensitive
   if (CASE_SENSITIVE_FS) { return true; }
@@ -80,12 +87,10 @@ exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cache
   return result;
 };
 
-function relative(modulePath, sourceFile, settings) {
-  return fullResolve(modulePath, sourceFile, settings).path;
-}
-
+/** @type {import('./types').ESLintSettings | null} */
 let prevSettings = null;
 let memoizedHash = '';
+/** @type {(modulePath: string, sourceFile: string, settings: import('./types').ESLintSettings) => import('./resolve').ResolvedResult} */
 function fullResolve(modulePath, sourceFile, settings) {
   // check if this is a bonus core module
   const coreSet = new Set(settings['import/core-modules']);
@@ -105,10 +110,12 @@ function fullResolve(modulePath, sourceFile, settings) {
   const cachedPath = fileExistsCache.get(cacheKey, cacheSettings);
   if (cachedPath !== undefined) { return { found: true, path: cachedPath }; }
 
+  /** @type {(resolvedPath: string | null) => void} */
   function cache(resolvedPath) {
     fileExistsCache.set(cacheKey, resolvedPath);
   }
 
+  /** @type {(resolver: import('./resolve').Resolver, config: unknown) => import('./resolve').ResolvedResult} */
   function withResolver(resolver, config) {
     if (resolver.interfaceVersion === 2) {
       return resolver.resolve(modulePath, sourceFile, config);
@@ -145,8 +152,14 @@ function fullResolve(modulePath, sourceFile, settings) {
   // cache(undefined)
   return { found: false };
 }
+
+/** @type {import('./resolve').relative} */
+function relative(modulePath, sourceFile, settings) {
+  return fullResolve(modulePath, sourceFile, settings).path;
+}
 exports.relative = relative;
 
+/** @type {<T extends Map<string, unknown>>(resolvers: string[] | string | { [k: string]: string }, map: T) => T} */
 function resolverReducer(resolvers, map) {
   if (Array.isArray(resolvers)) {
     resolvers.forEach((r) => resolverReducer(r, map));
@@ -170,9 +183,12 @@ function resolverReducer(resolvers, map) {
   throw err;
 }
 
+/** @type {(sourceFile: string) => string} */
 function getBaseDir(sourceFile) {
   return pkgDir(sourceFile) || process.cwd();
 }
+
+/** @type {(name: string, sourceFile: string) => import('./resolve').Resolver} */
 function requireResolver(name, sourceFile) {
   // Try to resolve package with conventional name
   const resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile)
@@ -193,23 +209,23 @@ function requireResolver(name, sourceFile) {
   return resolver;
 }
 
+/** @type {(resolver: object) => resolver is import('./resolve').Resolver} */
 function isResolverValid(resolver) {
-  if (resolver.interfaceVersion === 2) {
-    return resolver.resolve && typeof resolver.resolve === 'function';
-  } else {
-    return resolver.resolveImport && typeof resolver.resolveImport === 'function';
+  if ('interfaceVersion' in resolver && resolver.interfaceVersion === 2) {
+    return 'resolve' in resolver && !!resolver.resolve && typeof resolver.resolve === 'function';
   }
+  return 'resolveImport' in resolver && !!resolver.resolveImport && typeof resolver.resolveImport === 'function';
 }
 
+/** @type {Set<import('eslint').Rule.RuleContext>} */
 const erroredContexts = new Set();
 
 /**
  * Given
- * @param  {string} p - module path
- * @param  {object} context - ESLint context
- * @return {string} - the full module filesystem path;
- *                    null if package is core;
- *                    undefined if not found
+ * @param p - module path
+ * @param context - ESLint context
+ * @return - the full module filesystem path; null if package is core; undefined if not found
+ * @type {import('./resolve').default}
  */
 function resolve(p, context) {
   try {
@@ -218,8 +234,11 @@ function resolve(p, context) {
     if (!erroredContexts.has(context)) {
       // The `err.stack` string starts with `err.name` followed by colon and `err.message`.
       // We're filtering out the default `err.name` because it adds little value to the message.
+      // @ts-expect-error this might be an Error
       let errMessage = err.message;
+      // @ts-expect-error this might be an Error
       if (err.name !== ERROR_NAME && err.stack) {
+        // @ts-expect-error this might be an Error
         errMessage = err.stack.replace(/^Error: /, '');
       }
       context.report({
diff --git a/utils/tsconfig.json b/utils/tsconfig.json
new file mode 100644
index 0000000000..4d1c86efdf
--- /dev/null
+++ b/utils/tsconfig.json
@@ -0,0 +1,49 @@
+{
+  "compilerOptions": {
+    /* Visit https://aka.ms/tsconfig to read more about this file */
+
+    /* Projects */
+
+    /* Language and Environment */
+    "target": "ES2017",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
+    "useDefineForClassFields": true,                     /* Emit ECMAScript-standard-compliant class fields. */
+    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
+
+    /* Modules */
+    "module": "commonjs",                                /* Specify what module code is generated. */
+    "rootDir": "./",                                     /* Specify the root folder within your source files. */
+    "moduleResolution": "node",                          /* Specify how TypeScript looks up a file from a given module specifier. */
+    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
+    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
+    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
+    // "typeRoots": ["types"],                              /* Specify multiple folders that act like './node_modules/@types'. */
+    "resolveJsonModule": true,                           /* Enable importing .json files. */
+    // "allowArbitraryExtensions": true,                 /* Enable importing files with any extension, provided a declaration file is present. */
+
+    /* JavaScript Support */
+    "allowJs": true,                                     /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+    "checkJs": true,                                     /* Enable error reporting in type-checked JavaScript files. */
+    "maxNodeModuleJsDepth": 0,                           /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+    /* Emit */
+    "declaration": true,                                 /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+    "declarationMap": true,                              /* Create sourcemaps for d.ts files. */
+    "noEmit": true,                                      /* Disable emitting files from a compilation. */
+
+    /* Interop Constraints */
+    "allowSyntheticDefaultImports": true,                /* Allow 'import x from y' when a module doesn't have a default export. */
+    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
+    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
+
+    /* Type Checking */
+    "strict": true,                                      /* Enable all strict type-checking options. */
+
+    /* Completeness */
+    //"skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
+  },
+  "exclude": [
+    "coverage"
+  ]
+}
diff --git a/utils/types.d.ts b/utils/types.d.ts
new file mode 100644
index 0000000000..e0c4f5749d
--- /dev/null
+++ b/utils/types.d.ts
@@ -0,0 +1,9 @@
+import type { Rule } from 'eslint';
+
+export type Extension = `.${string}`;
+
+export type ESLintSettings = NonNullable<Rule.RuleContext['settings']> & {
+    'import/extensions'?: Extension[];
+    'import/parsers'?: { [k: string]: Extension[] };
+    'import/cache'?: { lifetime: number | '∞' | 'Infinity' };
+};
diff --git a/utils/unambiguous.d.ts b/utils/unambiguous.d.ts
new file mode 100644
index 0000000000..1679224189
--- /dev/null
+++ b/utils/unambiguous.d.ts
@@ -0,0 +1,7 @@
+import type { AST } from 'eslint';
+
+declare function isModule(ast: AST.Program): boolean;
+
+declare function test(content: string): boolean;
+
+export { isModule, test }
diff --git a/utils/unambiguous.js b/utils/unambiguous.js
index 24cb123157..20aabd1bd4 100644
--- a/utils/unambiguous.js
+++ b/utils/unambiguous.js
@@ -11,7 +11,7 @@ const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))|import\(/m;
  *
  * Not perfect, just a fast way to disqualify large non-ES6 modules and
  * avoid a parse.
- * @type {RegExp}
+ * @type {import('./unambiguous').test}
  */
 exports.test = function isMaybeUnambiguousModule(content) {
   return pattern.test(content);
@@ -22,8 +22,7 @@ const unambiguousNodeType = /^(?:(?:Exp|Imp)ort.*Declaration|TSExportAssignment)
 
 /**
  * Given an AST, return true if the AST unambiguously represents a module.
- * @param  {Program node}  ast
- * @return {Boolean}
+ * @type {import('./unambiguous').isModule}
  */
 exports.isModule = function isUnambiguousModule(ast) {
   return ast.body && ast.body.some((node) => unambiguousNodeType.test(node.type));
diff --git a/utils/visit.d.ts b/utils/visit.d.ts
new file mode 100644
index 0000000000..50559aaab0
--- /dev/null
+++ b/utils/visit.d.ts
@@ -0,0 +1,9 @@
+import type { Node } from 'estree';
+
+declare function visit(
+    node: Node,
+    keys: { [k in Node['type']]?: (keyof Node)[] },
+    visitorSpec: { [k in Node['type'] | `${Node['type']}:Exit`]?: Function }
+): void;
+
+export default visit;
diff --git a/utils/visit.js b/utils/visit.js
index 6178faeaa0..dd0c6248da 100644
--- a/utils/visit.js
+++ b/utils/visit.js
@@ -2,24 +2,29 @@
 
 exports.__esModule = true;
 
+/** @type {import('./visit').default} */
 exports.default = function visit(node, keys, visitorSpec) {
   if (!node || !keys) {
     return;
   }
   const type = node.type;
-  if (typeof visitorSpec[type] === 'function') {
-    visitorSpec[type](node);
+  const visitor = visitorSpec[type];
+  if (typeof visitor === 'function') {
+    visitor(node);
   }
   const childFields = keys[type];
   if (!childFields) {
     return;
   }
   childFields.forEach((fieldName) => {
+    // @ts-expect-error TS sucks with concat
     [].concat(node[fieldName]).forEach((item) => {
       visit(item, keys, visitorSpec);
     });
   });
-  if (typeof visitorSpec[`${type}:Exit`] === 'function') {
-    visitorSpec[`${type}:Exit`](node);
+
+  const exit = visitorSpec[`${type}:Exit`];
+  if (typeof exit === 'function') {
+    exit(node);
   }
 };

From df751e0d004aacc34f975477163fb221485a85f6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 26 Feb 2024 16:21:46 -0800
Subject: [PATCH 661/767] [utils] v2.8.1

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index a0aa43da75..b1344b9e0d 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.8.1 - 2024-02-26
+
 ### Fixed
 - `parse`: also delete `parserOptions.EXPERIMENTAL_useProjectService` ([#2963], thanks [@JoshuaKGoldberg])
 
diff --git a/utils/package.json b/utils/package.json
index 04c338b1a8..275e364dca 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.8.0",
+  "version": "2.8.1",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From b87746016dbb1aab7d5ec9331a39ccdabedfb1b7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 10 Mar 2024 22:50:46 -0700
Subject: [PATCH 662/767] [utils] [types] use shared config

---
 utils/CHANGELOG.md  |  3 +++
 utils/package.json  |  1 +
 utils/tsconfig.json | 56 ++++++++-------------------------------------
 3 files changed, 13 insertions(+), 47 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index b1344b9e0d..3e2f5a8997 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Changed
+- [types] use shared config (thanks [@ljharb])
+
 ## v2.8.1 - 2024-02-26
 
 ### Fixed
diff --git a/utils/package.json b/utils/package.json
index 275e364dca..df4871790b 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -30,6 +30,7 @@
     "debug": "^3.2.7"
   },
   "devDependencies": {
+    "@ljharb/tsconfig": "^0.2.0",
     "@types/debug": "^4.1.12",
     "@types/eslint": "^8.56.3",
     "@types/node": "^20.11.20",
diff --git a/utils/tsconfig.json b/utils/tsconfig.json
index 4d1c86efdf..9e6fbc5cc1 100644
--- a/utils/tsconfig.json
+++ b/utils/tsconfig.json
@@ -1,49 +1,11 @@
 {
-  "compilerOptions": {
-    /* Visit https://aka.ms/tsconfig to read more about this file */
-
-    /* Projects */
-
-    /* Language and Environment */
-    "target": "ES2017",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
-    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
-    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
-    "useDefineForClassFields": true,                     /* Emit ECMAScript-standard-compliant class fields. */
-    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
-
-    /* Modules */
-    "module": "commonjs",                                /* Specify what module code is generated. */
-    "rootDir": "./",                                     /* Specify the root folder within your source files. */
-    "moduleResolution": "node",                          /* Specify how TypeScript looks up a file from a given module specifier. */
-    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
-    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
-    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
-    // "typeRoots": ["types"],                              /* Specify multiple folders that act like './node_modules/@types'. */
-    "resolveJsonModule": true,                           /* Enable importing .json files. */
-    // "allowArbitraryExtensions": true,                 /* Enable importing files with any extension, provided a declaration file is present. */
-
-    /* JavaScript Support */
-    "allowJs": true,                                     /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
-    "checkJs": true,                                     /* Enable error reporting in type-checked JavaScript files. */
-    "maxNodeModuleJsDepth": 0,                           /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
-
-    /* Emit */
-    "declaration": true,                                 /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
-    "declarationMap": true,                              /* Create sourcemaps for d.ts files. */
-    "noEmit": true,                                      /* Disable emitting files from a compilation. */
-
-    /* Interop Constraints */
-    "allowSyntheticDefaultImports": true,                /* Allow 'import x from y' when a module doesn't have a default export. */
-    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
-    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
-
-    /* Type Checking */
-    "strict": true,                                      /* Enable all strict type-checking options. */
-
-    /* Completeness */
-    //"skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
-  },
-  "exclude": [
-    "coverage"
-  ]
+	"extends": "@ljharb/tsconfig",
+	"compilerOptions": {
+		"target": "ES2017",
+		"moduleResolution": "node",
+		"maxNodeModuleJsDepth": 0,
+	},
+	"exclude": [
+		"coverage",
+	],
 }

From d5ab2ccf4da82f6bc7a7daa586cea3fa1171d527 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 10 Mar 2024 22:56:37 -0700
Subject: [PATCH 663/767] [Docs] run `npm run update:eslint-docs

---
 README.md                           | 2 +-
 docs/rules/no-empty-named-blocks.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 1baa0069b3..d6f107d1c9 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 ⌨️ Set in the `typescript` configuration.\
 🚸 Set in the `warnings` configuration.\
 🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
-💡 Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).\
+💡 Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).\
 ❌ Deprecated.
 
 ### Helpful warnings
diff --git a/docs/rules/no-empty-named-blocks.md b/docs/rules/no-empty-named-blocks.md
index 85821d8afe..ad83c535f8 100644
--- a/docs/rules/no-empty-named-blocks.md
+++ b/docs/rules/no-empty-named-blocks.md
@@ -1,6 +1,6 @@
 # import/no-empty-named-blocks
 
-🔧💡 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) and manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
+🔧💡 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) and manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
 
 <!-- end auto-generated rule header -->
 

From 51185dd347a7c83904743433592b2f74d73e709d Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Wed, 13 Mar 2024 18:32:47 +0200
Subject: [PATCH 664/767] [Refactor] `ExportMap`: make procedures static
 instead of monkeypatching exportmap

---
 CHANGELOG.md     |   2 +
 src/ExportMap.js | 908 +++++++++++++++++++++++------------------------
 2 files changed, 456 insertions(+), 454 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 06cdb922e5..9552774dce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
 - [`no-unused-modules`]: add console message to help debug [#2866]
+- [Refactor] `ExportMap`: make procedures static instead of monkeypatching exportmap ([#2982], thanks [@soryy708])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1108,6 +1109,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2982]: https://github.com/import-js/eslint-plugin-import/pull/2982
 [#2944]: https://github.com/import-js/eslint-plugin-import/pull/2944
 [#2942]: https://github.com/import-js/eslint-plugin-import/pull/2942
 [#2919]: https://github.com/import-js/eslint-plugin-import/pull/2919
diff --git a/src/ExportMap.js b/src/ExportMap.js
index f61d3c170a..9ee65a504f 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -26,6 +26,97 @@ const log = debug('eslint-plugin-import:ExportMap');
 const exportCache = new Map();
 const tsconfigCache = new Map();
 
+/**
+ * parse docs from the first node that has leading comments
+ */
+function captureDoc(source, docStyleParsers, ...nodes) {
+  const metadata = {};
+
+  // 'some' short-circuits on first 'true'
+  nodes.some((n) => {
+    try {
+
+      let leadingComments;
+
+      // n.leadingComments is legacy `attachComments` behavior
+      if ('leadingComments' in n) {
+        leadingComments = n.leadingComments;
+      } else if (n.range) {
+        leadingComments = source.getCommentsBefore(n);
+      }
+
+      if (!leadingComments || leadingComments.length === 0) { return false; }
+
+      for (const name in docStyleParsers) {
+        const doc = docStyleParsers[name](leadingComments);
+        if (doc) {
+          metadata.doc = doc;
+        }
+      }
+
+      return true;
+    } catch (err) {
+      return false;
+    }
+  });
+
+  return metadata;
+}
+
+/**
+ * parse JSDoc from leading comments
+ * @param {object[]} comments
+ * @return {{ doc: object }}
+ */
+function captureJsDoc(comments) {
+  let doc;
+
+  // capture XSDoc
+  comments.forEach((comment) => {
+    // skip non-block comments
+    if (comment.type !== 'Block') { return; }
+    try {
+      doc = doctrine.parse(comment.value, { unwrap: true });
+    } catch (err) {
+      /* don't care, for now? maybe add to `errors?` */
+    }
+  });
+
+  return doc;
+}
+
+/**
+  * parse TomDoc section from comments
+  */
+function captureTomDoc(comments) {
+  // collect lines up to first paragraph break
+  const lines = [];
+  for (let i = 0; i < comments.length; i++) {
+    const comment = comments[i];
+    if (comment.value.match(/^\s*$/)) { break; }
+    lines.push(comment.value.trim());
+  }
+
+  // return doctrine-like object
+  const statusMatch = lines.join(' ').match(/^(Public|Internal|Deprecated):\s*(.+)/);
+  if (statusMatch) {
+    return {
+      description: statusMatch[2],
+      tags: [{
+        title: statusMatch[1].toLowerCase(),
+        description: statusMatch[2],
+      }],
+    };
+  }
+}
+
+const availableDocStyleParsers = {
+  jsdoc: captureJsDoc,
+  tomdoc: captureTomDoc,
+};
+
+const supportedImportTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
+
 export default class ExportMap {
   constructor(path) {
     this.path = path;
@@ -203,534 +294,443 @@ export default class ExportMap {
       message: `Parse errors in imported module '${declaration.source.value}': ${msg}`,
     });
   }
-}
 
-/**
- * parse docs from the first node that has leading comments
- */
-function captureDoc(source, docStyleParsers, ...nodes) {
-  const metadata = {};
+  static get(source, context) {
+    const path = resolve(source, context);
+    if (path == null) { return null; }
 
-  // 'some' short-circuits on first 'true'
-  nodes.some((n) => {
-    try {
+    return ExportMap.for(childContext(path, context));
+  }
 
-      let leadingComments;
+  static for(context) {
+    const { path } = context;
 
-      // n.leadingComments is legacy `attachComments` behavior
-      if ('leadingComments' in n) {
-        leadingComments = n.leadingComments;
-      } else if (n.range) {
-        leadingComments = source.getCommentsBefore(n);
-      }
+    const cacheKey = context.cacheKey || hashObject(context).digest('hex');
+    let exportMap = exportCache.get(cacheKey);
 
-      if (!leadingComments || leadingComments.length === 0) { return false; }
+    // return cached ignore
+    if (exportMap === null) { return null; }
 
-      for (const name in docStyleParsers) {
-        const doc = docStyleParsers[name](leadingComments);
-        if (doc) {
-          metadata.doc = doc;
-        }
+    const stats = fs.statSync(path);
+    if (exportMap != null) {
+      // date equality check
+      if (exportMap.mtime - stats.mtime === 0) {
+        return exportMap;
       }
-
-      return true;
-    } catch (err) {
-      return false;
+      // future: check content equality?
     }
-  });
-
-  return metadata;
-}
-
-const availableDocStyleParsers = {
-  jsdoc: captureJsDoc,
-  tomdoc: captureTomDoc,
-};
-
-/**
- * parse JSDoc from leading comments
- * @param {object[]} comments
- * @return {{ doc: object }}
- */
-function captureJsDoc(comments) {
-  let doc;
 
-  // capture XSDoc
-  comments.forEach((comment) => {
-    // skip non-block comments
-    if (comment.type !== 'Block') { return; }
-    try {
-      doc = doctrine.parse(comment.value, { unwrap: true });
-    } catch (err) {
-      /* don't care, for now? maybe add to `errors?` */
+    // check valid extensions first
+    if (!hasValidExtension(path, context)) {
+      exportCache.set(cacheKey, null);
+      return null;
     }
-  });
-
-  return doc;
-}
-
-/**
-  * parse TomDoc section from comments
-  */
-function captureTomDoc(comments) {
-  // collect lines up to first paragraph break
-  const lines = [];
-  for (let i = 0; i < comments.length; i++) {
-    const comment = comments[i];
-    if (comment.value.match(/^\s*$/)) { break; }
-    lines.push(comment.value.trim());
-  }
-
-  // return doctrine-like object
-  const statusMatch = lines.join(' ').match(/^(Public|Internal|Deprecated):\s*(.+)/);
-  if (statusMatch) {
-    return {
-      description: statusMatch[2],
-      tags: [{
-        title: statusMatch[1].toLowerCase(),
-        description: statusMatch[2],
-      }],
-    };
-  }
-}
-
-const supportedImportTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
-
-ExportMap.get = function (source, context) {
-  const path = resolve(source, context);
-  if (path == null) { return null; }
-
-  return ExportMap.for(childContext(path, context));
-};
-
-ExportMap.for = function (context) {
-  const { path } = context;
-
-  const cacheKey = context.cacheKey || hashObject(context).digest('hex');
-  let exportMap = exportCache.get(cacheKey);
 
-  // return cached ignore
-  if (exportMap === null) { return null; }
-
-  const stats = fs.statSync(path);
-  if (exportMap != null) {
-    // date equality check
-    if (exportMap.mtime - stats.mtime === 0) {
-      return exportMap;
+    // check for and cache ignore
+    if (isIgnored(path, context)) {
+      log('ignored path due to ignore settings:', path);
+      exportCache.set(cacheKey, null);
+      return null;
     }
-    // future: check content equality?
-  }
-
-  // check valid extensions first
-  if (!hasValidExtension(path, context)) {
-    exportCache.set(cacheKey, null);
-    return null;
-  }
 
-  // check for and cache ignore
-  if (isIgnored(path, context)) {
-    log('ignored path due to ignore settings:', path);
-    exportCache.set(cacheKey, null);
-    return null;
-  }
-
-  const content = fs.readFileSync(path, { encoding: 'utf8' });
-
-  // check for and cache unambiguous modules
-  if (!unambiguous.test(content)) {
-    log('ignored path due to unambiguous regex:', path);
-    exportCache.set(cacheKey, null);
-    return null;
-  }
+    const content = fs.readFileSync(path, { encoding: 'utf8' });
 
-  log('cache miss', cacheKey, 'for path', path);
-  exportMap = ExportMap.parse(path, content, context);
+    // check for and cache unambiguous modules
+    if (!unambiguous.test(content)) {
+      log('ignored path due to unambiguous regex:', path);
+      exportCache.set(cacheKey, null);
+      return null;
+    }
 
-  // ambiguous modules return null
-  if (exportMap == null) {
-    log('ignored path due to ambiguous parse:', path);
-    exportCache.set(cacheKey, null);
-    return null;
-  }
+    log('cache miss', cacheKey, 'for path', path);
+    exportMap = ExportMap.parse(path, content, context);
 
-  exportMap.mtime = stats.mtime;
+    // ambiguous modules return null
+    if (exportMap == null) {
+      log('ignored path due to ambiguous parse:', path);
+      exportCache.set(cacheKey, null);
+      return null;
+    }
 
-  exportCache.set(cacheKey, exportMap);
-  return exportMap;
-};
+    exportMap.mtime = stats.mtime;
 
-ExportMap.parse = function (path, content, context) {
-  const m = new ExportMap(path);
-  const isEsModuleInteropTrue = isEsModuleInterop();
-
-  let ast;
-  let visitorKeys;
-  try {
-    const result = parse(path, content, context);
-    ast = result.ast;
-    visitorKeys = result.visitorKeys;
-  } catch (err) {
-    m.errors.push(err);
-    return m; // can't continue
+    exportCache.set(cacheKey, exportMap);
+    return exportMap;
   }
 
-  m.visitorKeys = visitorKeys;
-
-  let hasDynamicImports = false;
+  static parse(path, content, context) {
+    const m = new ExportMap(path);
+    const isEsModuleInteropTrue = isEsModuleInterop();
 
-  function processDynamicImport(source) {
-    hasDynamicImports = true;
-    if (source.type !== 'Literal') {
-      return null;
-    }
-    const p = remotePath(source.value);
-    if (p == null) {
-      return null;
+    let ast;
+    let visitorKeys;
+    try {
+      const result = parse(path, content, context);
+      ast = result.ast;
+      visitorKeys = result.visitorKeys;
+    } catch (err) {
+      m.errors.push(err);
+      return m; // can't continue
     }
-    const importedSpecifiers = new Set();
-    importedSpecifiers.add('ImportNamespaceSpecifier');
-    const getter = thunkFor(p, context);
-    m.imports.set(p, {
-      getter,
-      declarations: new Set([{
-        source: {
-        // capturing actual node reference holds full AST in memory!
-          value: source.value,
-          loc: source.loc,
-        },
-        importedSpecifiers,
-        dynamic: true,
-      }]),
-    });
-  }
 
-  visit(ast, visitorKeys, {
-    ImportExpression(node) {
-      processDynamicImport(node.source);
-    },
-    CallExpression(node) {
-      if (node.callee.type === 'Import') {
-        processDynamicImport(node.arguments[0]);
-      }
-    },
-  });
+    m.visitorKeys = visitorKeys;
 
-  const unambiguouslyESM = unambiguous.isModule(ast);
-  if (!unambiguouslyESM && !hasDynamicImports) { return null; }
+    let hasDynamicImports = false;
 
-  const docstyle = context.settings && context.settings['import/docstyle'] || ['jsdoc'];
-  const docStyleParsers = {};
-  docstyle.forEach((style) => {
-    docStyleParsers[style] = availableDocStyleParsers[style];
-  });
+    function processDynamicImport(source) {
+      hasDynamicImports = true;
+      if (source.type !== 'Literal') {
+        return null;
+      }
+      const p = remotePath(source.value);
+      if (p == null) {
+        return null;
+      }
+      const importedSpecifiers = new Set();
+      importedSpecifiers.add('ImportNamespaceSpecifier');
+      const getter = thunkFor(p, context);
+      m.imports.set(p, {
+        getter,
+        declarations: new Set([{
+          source: {
+          // capturing actual node reference holds full AST in memory!
+            value: source.value,
+            loc: source.loc,
+          },
+          importedSpecifiers,
+          dynamic: true,
+        }]),
+      });
+    }
 
-  // attempt to collect module doc
-  if (ast.comments) {
-    ast.comments.some((c) => {
-      if (c.type !== 'Block') { return false; }
-      try {
-        const doc = doctrine.parse(c.value, { unwrap: true });
-        if (doc.tags.some((t) => t.title === 'module')) {
-          m.doc = doc;
-          return true;
+    visit(ast, visitorKeys, {
+      ImportExpression(node) {
+        processDynamicImport(node.source);
+      },
+      CallExpression(node) {
+        if (node.callee.type === 'Import') {
+          processDynamicImport(node.arguments[0]);
         }
-      } catch (err) { /* ignore */ }
-      return false;
+      },
     });
-  }
 
-  const namespaces = new Map();
+    const unambiguouslyESM = unambiguous.isModule(ast);
+    if (!unambiguouslyESM && !hasDynamicImports) { return null; }
 
-  function remotePath(value) {
-    return resolve.relative(value, path, context.settings);
-  }
+    const docstyle = context.settings && context.settings['import/docstyle'] || ['jsdoc'];
+    const docStyleParsers = {};
+    docstyle.forEach((style) => {
+      docStyleParsers[style] = availableDocStyleParsers[style];
+    });
 
-  function resolveImport(value) {
-    const rp = remotePath(value);
-    if (rp == null) { return null; }
-    return ExportMap.for(childContext(rp, context));
-  }
+    // attempt to collect module doc
+    if (ast.comments) {
+      ast.comments.some((c) => {
+        if (c.type !== 'Block') { return false; }
+        try {
+          const doc = doctrine.parse(c.value, { unwrap: true });
+          if (doc.tags.some((t) => t.title === 'module')) {
+            m.doc = doc;
+            return true;
+          }
+        } catch (err) { /* ignore */ }
+        return false;
+      });
+    }
 
-  function getNamespace(identifier) {
-    if (!namespaces.has(identifier.name)) { return; }
+    const namespaces = new Map();
 
-    return function () {
-      return resolveImport(namespaces.get(identifier.name));
-    };
-  }
+    function remotePath(value) {
+      return resolve.relative(value, path, context.settings);
+    }
 
-  function addNamespace(object, identifier) {
-    const nsfn = getNamespace(identifier);
-    if (nsfn) {
-      Object.defineProperty(object, 'namespace', { get: nsfn });
+    function resolveImport(value) {
+      const rp = remotePath(value);
+      if (rp == null) { return null; }
+      return ExportMap.for(childContext(rp, context));
     }
 
-    return object;
-  }
+    function getNamespace(identifier) {
+      if (!namespaces.has(identifier.name)) { return; }
 
-  function processSpecifier(s, n, m) {
-    const nsource = n.source && n.source.value;
-    const exportMeta = {};
-    let local;
-
-    switch (s.type) {
-      case 'ExportDefaultSpecifier':
-        if (!nsource) { return; }
-        local = 'default';
-        break;
-      case 'ExportNamespaceSpecifier':
-        m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
-          get() { return resolveImport(nsource); },
-        }));
-        return;
-      case 'ExportAllDeclaration':
-        m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.source.value));
-        return;
-      case 'ExportSpecifier':
-        if (!n.source) {
-          m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.local));
-          return;
-        }
-      // else falls through
-      default:
-        local = s.local.name;
-        break;
+      return function () {
+        return resolveImport(namespaces.get(identifier.name));
+      };
     }
 
-    // todo: JSDoc
-    m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) });
-  }
-
-  function captureDependencyWithSpecifiers(n) {
-    // import type { Foo } (TS and Flow); import typeof { Foo } (Flow)
-    const declarationIsType = n.importKind === 'type' || n.importKind === 'typeof';
-    // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
-    // shouldn't be considered to be just importing types
-    let specifiersOnlyImportingTypes = n.specifiers.length > 0;
-    const importedSpecifiers = new Set();
-    n.specifiers.forEach((specifier) => {
-      if (specifier.type === 'ImportSpecifier') {
-        importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
-      } else if (supportedImportTypes.has(specifier.type)) {
-        importedSpecifiers.add(specifier.type);
+    function addNamespace(object, identifier) {
+      const nsfn = getNamespace(identifier);
+      if (nsfn) {
+        Object.defineProperty(object, 'namespace', { get: nsfn });
       }
 
-      // import { type Foo } (Flow); import { typeof Foo } (Flow)
-      specifiersOnlyImportingTypes = specifiersOnlyImportingTypes
-        && (specifier.importKind === 'type' || specifier.importKind === 'typeof');
-    });
-    captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
-  }
+      return object;
+    }
 
-  function captureDependency({ source }, isOnlyImportingTypes, importedSpecifiers = new Set()) {
-    if (source == null) { return null; }
+    function processSpecifier(s, n, m) {
+      const nsource = n.source && n.source.value;
+      const exportMeta = {};
+      let local;
+
+      switch (s.type) {
+        case 'ExportDefaultSpecifier':
+          if (!nsource) { return; }
+          local = 'default';
+          break;
+        case 'ExportNamespaceSpecifier':
+          m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
+            get() { return resolveImport(nsource); },
+          }));
+          return;
+        case 'ExportAllDeclaration':
+          m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.source.value));
+          return;
+        case 'ExportSpecifier':
+          if (!n.source) {
+            m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.local));
+            return;
+          }
+        // else falls through
+        default:
+          local = s.local.name;
+          break;
+      }
 
-    const p = remotePath(source.value);
-    if (p == null) { return null; }
+      // todo: JSDoc
+      m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) });
+    }
 
-    const declarationMetadata = {
-      // capturing actual node reference holds full AST in memory!
-      source: { value: source.value, loc: source.loc },
-      isOnlyImportingTypes,
-      importedSpecifiers,
-    };
+    function captureDependencyWithSpecifiers(n) {
+      // import type { Foo } (TS and Flow); import typeof { Foo } (Flow)
+      const declarationIsType = n.importKind === 'type' || n.importKind === 'typeof';
+      // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
+      // shouldn't be considered to be just importing types
+      let specifiersOnlyImportingTypes = n.specifiers.length > 0;
+      const importedSpecifiers = new Set();
+      n.specifiers.forEach((specifier) => {
+        if (specifier.type === 'ImportSpecifier') {
+          importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
+        } else if (supportedImportTypes.has(specifier.type)) {
+          importedSpecifiers.add(specifier.type);
+        }
 
-    const existing = m.imports.get(p);
-    if (existing != null) {
-      existing.declarations.add(declarationMetadata);
-      return existing.getter;
+        // import { type Foo } (Flow); import { typeof Foo } (Flow)
+        specifiersOnlyImportingTypes = specifiersOnlyImportingTypes
+          && (specifier.importKind === 'type' || specifier.importKind === 'typeof');
+      });
+      captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
     }
 
-    const getter = thunkFor(p, context);
-    m.imports.set(p, { getter, declarations: new Set([declarationMetadata]) });
-    return getter;
-  }
+    function captureDependency({ source }, isOnlyImportingTypes, importedSpecifiers = new Set()) {
+      if (source == null) { return null; }
 
-  const source = makeSourceCode(content, ast);
+      const p = remotePath(source.value);
+      if (p == null) { return null; }
 
-  function readTsConfig(context) {
-    const tsconfigInfo = tsConfigLoader({
-      cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
-      getEnv: (key) => process.env[key],
-    });
-    try {
-      if (tsconfigInfo.tsConfigPath !== undefined) {
-        // Projects not using TypeScript won't have `typescript` installed.
-        if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
-
-        const configFile = ts.readConfigFile(tsconfigInfo.tsConfigPath, ts.sys.readFile);
-        return ts.parseJsonConfigFileContent(
-          configFile.config,
-          ts.sys,
-          dirname(tsconfigInfo.tsConfigPath),
-        );
-      }
-    } catch (e) {
-      // Catch any errors
-    }
+      const declarationMetadata = {
+        // capturing actual node reference holds full AST in memory!
+        source: { value: source.value, loc: source.loc },
+        isOnlyImportingTypes,
+        importedSpecifiers,
+      };
 
-    return null;
-  }
+      const existing = m.imports.get(p);
+      if (existing != null) {
+        existing.declarations.add(declarationMetadata);
+        return existing.getter;
+      }
 
-  function isEsModuleInterop() {
-    const cacheKey = hashObject({
-      tsconfigRootDir: context.parserOptions && context.parserOptions.tsconfigRootDir,
-    }).digest('hex');
-    let tsConfig = tsconfigCache.get(cacheKey);
-    if (typeof tsConfig === 'undefined') {
-      tsConfig = readTsConfig(context);
-      tsconfigCache.set(cacheKey, tsConfig);
+      const getter = thunkFor(p, context);
+      m.imports.set(p, { getter, declarations: new Set([declarationMetadata]) });
+      return getter;
     }
 
-    return tsConfig && tsConfig.options ? tsConfig.options.esModuleInterop : false;
-  }
+    const source = makeSourceCode(content, ast);
 
-  ast.body.forEach(function (n) {
-    if (n.type === 'ExportDefaultDeclaration') {
-      const exportMeta = captureDoc(source, docStyleParsers, n);
-      if (n.declaration.type === 'Identifier') {
-        addNamespace(exportMeta, n.declaration);
+    function readTsConfig(context) {
+      const tsconfigInfo = tsConfigLoader({
+        cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
+        getEnv: (key) => process.env[key],
+      });
+      try {
+        if (tsconfigInfo.tsConfigPath !== undefined) {
+          // Projects not using TypeScript won't have `typescript` installed.
+          if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
+
+          const configFile = ts.readConfigFile(tsconfigInfo.tsConfigPath, ts.sys.readFile);
+          return ts.parseJsonConfigFileContent(
+            configFile.config,
+            ts.sys,
+            dirname(tsconfigInfo.tsConfigPath),
+          );
+        }
+      } catch (e) {
+        // Catch any errors
       }
-      m.namespace.set('default', exportMeta);
-      return;
-    }
 
-    if (n.type === 'ExportAllDeclaration') {
-      const getter = captureDependency(n, n.exportKind === 'type');
-      if (getter) { m.dependencies.add(getter); }
-      if (n.exported) {
-        processSpecifier(n, n.exported, m);
-      }
-      return;
+      return null;
     }
 
-    // capture namespaces in case of later export
-    if (n.type === 'ImportDeclaration') {
-      captureDependencyWithSpecifiers(n);
-
-      const ns = n.specifiers.find((s) => s.type === 'ImportNamespaceSpecifier');
-      if (ns) {
-        namespaces.set(ns.local.name, n.source.value);
+    function isEsModuleInterop() {
+      const cacheKey = hashObject({
+        tsconfigRootDir: context.parserOptions && context.parserOptions.tsconfigRootDir,
+      }).digest('hex');
+      let tsConfig = tsconfigCache.get(cacheKey);
+      if (typeof tsConfig === 'undefined') {
+        tsConfig = readTsConfig(context);
+        tsconfigCache.set(cacheKey, tsConfig);
       }
-      return;
+
+      return tsConfig && tsConfig.options ? tsConfig.options.esModuleInterop : false;
     }
 
-    if (n.type === 'ExportNamedDeclaration') {
-      captureDependencyWithSpecifiers(n);
-
-      // capture declaration
-      if (n.declaration != null) {
-        switch (n.declaration.type) {
-          case 'FunctionDeclaration':
-          case 'ClassDeclaration':
-          case 'TypeAlias': // flowtype with babel-eslint parser
-          case 'InterfaceDeclaration':
-          case 'DeclareFunction':
-          case 'TSDeclareFunction':
-          case 'TSEnumDeclaration':
-          case 'TSTypeAliasDeclaration':
-          case 'TSInterfaceDeclaration':
-          case 'TSAbstractClassDeclaration':
-          case 'TSModuleDeclaration':
-            m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n));
-            break;
-          case 'VariableDeclaration':
-            n.declaration.declarations.forEach((d) => {
-              recursivePatternCapture(
-                d.id,
-                (id) => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n)),
-              );
-            });
-            break;
-          default:
+    ast.body.forEach(function (n) {
+      if (n.type === 'ExportDefaultDeclaration') {
+        const exportMeta = captureDoc(source, docStyleParsers, n);
+        if (n.declaration.type === 'Identifier') {
+          addNamespace(exportMeta, n.declaration);
         }
+        m.namespace.set('default', exportMeta);
+        return;
       }
 
-      n.specifiers.forEach((s) => processSpecifier(s, n, m));
-    }
+      if (n.type === 'ExportAllDeclaration') {
+        const getter = captureDependency(n, n.exportKind === 'type');
+        if (getter) { m.dependencies.add(getter); }
+        if (n.exported) {
+          processSpecifier(n, n.exported, m);
+        }
+        return;
+      }
 
-    const exports = ['TSExportAssignment'];
-    if (isEsModuleInteropTrue) {
-      exports.push('TSNamespaceExportDeclaration');
-    }
+      // capture namespaces in case of later export
+      if (n.type === 'ImportDeclaration') {
+        captureDependencyWithSpecifiers(n);
 
-    // This doesn't declare anything, but changes what's being exported.
-    if (includes(exports, n.type)) {
-      const exportedName = n.type === 'TSNamespaceExportDeclaration'
-        ? (n.id || n.name).name
-        : n.expression && n.expression.name || n.expression.id && n.expression.id.name || null;
-      const declTypes = [
-        'VariableDeclaration',
-        'ClassDeclaration',
-        'TSDeclareFunction',
-        'TSEnumDeclaration',
-        'TSTypeAliasDeclaration',
-        'TSInterfaceDeclaration',
-        'TSAbstractClassDeclaration',
-        'TSModuleDeclaration',
-      ];
-      const exportedDecls = ast.body.filter(({ type, id, declarations }) => includes(declTypes, type) && (
-        id && id.name === exportedName || declarations && declarations.find((d) => d.id.name === exportedName)
-      ));
-      if (exportedDecls.length === 0) {
-        // Export is not referencing any local declaration, must be re-exporting
-        m.namespace.set('default', captureDoc(source, docStyleParsers, n));
+        const ns = n.specifiers.find((s) => s.type === 'ImportNamespaceSpecifier');
+        if (ns) {
+          namespaces.set(ns.local.name, n.source.value);
+        }
         return;
       }
-      if (
-        isEsModuleInteropTrue // esModuleInterop is on in tsconfig
-        && !m.namespace.has('default') // and default isn't added already
-      ) {
-        m.namespace.set('default', {}); // add default export
-      }
-      exportedDecls.forEach((decl) => {
-        if (decl.type === 'TSModuleDeclaration') {
-          if (decl.body && decl.body.type === 'TSModuleDeclaration') {
-            m.namespace.set(decl.body.id.name, captureDoc(source, docStyleParsers, decl.body));
-          } else if (decl.body && decl.body.body) {
-            decl.body.body.forEach((moduleBlockNode) => {
-              // Export-assignment exports all members in the namespace,
-              // explicitly exported or not.
-              const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration'
-                ? moduleBlockNode.declaration
-                : moduleBlockNode;
-
-              if (!namespaceDecl) {
-                // TypeScript can check this for us; we needn't
-              } else if (namespaceDecl.type === 'VariableDeclaration') {
-                namespaceDecl.declarations.forEach((d) => recursivePatternCapture(d.id, (id) => m.namespace.set(
-                  id.name,
-                  captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode),
-                )),
+
+      if (n.type === 'ExportNamedDeclaration') {
+        captureDependencyWithSpecifiers(n);
+
+        // capture declaration
+        if (n.declaration != null) {
+          switch (n.declaration.type) {
+            case 'FunctionDeclaration':
+            case 'ClassDeclaration':
+            case 'TypeAlias': // flowtype with babel-eslint parser
+            case 'InterfaceDeclaration':
+            case 'DeclareFunction':
+            case 'TSDeclareFunction':
+            case 'TSEnumDeclaration':
+            case 'TSTypeAliasDeclaration':
+            case 'TSInterfaceDeclaration':
+            case 'TSAbstractClassDeclaration':
+            case 'TSModuleDeclaration':
+              m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n));
+              break;
+            case 'VariableDeclaration':
+              n.declaration.declarations.forEach((d) => {
+                recursivePatternCapture(
+                  d.id,
+                  (id) => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n)),
                 );
-              } else {
-                m.namespace.set(
-                  namespaceDecl.id.name,
-                  captureDoc(source, docStyleParsers, moduleBlockNode));
-              }
-            });
+              });
+              break;
+            default:
           }
-        } else {
-          // Export as default
-          m.namespace.set('default', captureDoc(source, docStyleParsers, decl));
         }
-      });
-    }
-  });
 
-  if (
-    isEsModuleInteropTrue // esModuleInterop is on in tsconfig
-    && m.namespace.size > 0 // anything is exported
-    && !m.namespace.has('default') // and default isn't added already
-  ) {
-    m.namespace.set('default', {}); // add default export
-  }
+        n.specifiers.forEach((s) => processSpecifier(s, n, m));
+      }
+
+      const exports = ['TSExportAssignment'];
+      if (isEsModuleInteropTrue) {
+        exports.push('TSNamespaceExportDeclaration');
+      }
+
+      // This doesn't declare anything, but changes what's being exported.
+      if (includes(exports, n.type)) {
+        const exportedName = n.type === 'TSNamespaceExportDeclaration'
+          ? (n.id || n.name).name
+          : n.expression && n.expression.name || n.expression.id && n.expression.id.name || null;
+        const declTypes = [
+          'VariableDeclaration',
+          'ClassDeclaration',
+          'TSDeclareFunction',
+          'TSEnumDeclaration',
+          'TSTypeAliasDeclaration',
+          'TSInterfaceDeclaration',
+          'TSAbstractClassDeclaration',
+          'TSModuleDeclaration',
+        ];
+        const exportedDecls = ast.body.filter(({ type, id, declarations }) => includes(declTypes, type) && (
+          id && id.name === exportedName || declarations && declarations.find((d) => d.id.name === exportedName)
+        ));
+        if (exportedDecls.length === 0) {
+          // Export is not referencing any local declaration, must be re-exporting
+          m.namespace.set('default', captureDoc(source, docStyleParsers, n));
+          return;
+        }
+        if (
+          isEsModuleInteropTrue // esModuleInterop is on in tsconfig
+          && !m.namespace.has('default') // and default isn't added already
+        ) {
+          m.namespace.set('default', {}); // add default export
+        }
+        exportedDecls.forEach((decl) => {
+          if (decl.type === 'TSModuleDeclaration') {
+            if (decl.body && decl.body.type === 'TSModuleDeclaration') {
+              m.namespace.set(decl.body.id.name, captureDoc(source, docStyleParsers, decl.body));
+            } else if (decl.body && decl.body.body) {
+              decl.body.body.forEach((moduleBlockNode) => {
+                // Export-assignment exports all members in the namespace,
+                // explicitly exported or not.
+                const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration'
+                  ? moduleBlockNode.declaration
+                  : moduleBlockNode;
+
+                if (!namespaceDecl) {
+                  // TypeScript can check this for us; we needn't
+                } else if (namespaceDecl.type === 'VariableDeclaration') {
+                  namespaceDecl.declarations.forEach((d) => recursivePatternCapture(d.id, (id) => m.namespace.set(
+                    id.name,
+                    captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode),
+                  )),
+                  );
+                } else {
+                  m.namespace.set(
+                    namespaceDecl.id.name,
+                    captureDoc(source, docStyleParsers, moduleBlockNode));
+                }
+              });
+            }
+          } else {
+            // Export as default
+            m.namespace.set('default', captureDoc(source, docStyleParsers, decl));
+          }
+        });
+      }
+    });
 
-  if (unambiguouslyESM) {
-    m.parseGoal = 'Module';
+    if (
+      isEsModuleInteropTrue // esModuleInterop is on in tsconfig
+      && m.namespace.size > 0 // anything is exported
+      && !m.namespace.has('default') // and default isn't added already
+    ) {
+      m.namespace.set('default', {}); // add default export
+    }
+
+    if (unambiguouslyESM) {
+      m.parseGoal = 'Module';
+    }
+    return m;
   }
-  return m;
-};
+}
 
 /**
  * The creation of this closure is isolated from other scopes

From 2d38b3367e90df2eabd6c6aad0a05d6a1fc96734 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 13 Mar 2024 14:23:09 -0700
Subject: [PATCH 665/767] [resolvers] [*] [refactor] avoid hoisting

---
 resolvers/node/index.js    |  40 +--
 resolvers/webpack/index.js | 588 ++++++++++++++++++-------------------
 2 files changed, 314 insertions(+), 314 deletions(-)

diff --git a/resolvers/node/index.js b/resolvers/node/index.js
index 7f207fbf31..9e0e753cc7 100644
--- a/resolvers/node/index.js
+++ b/resolvers/node/index.js
@@ -8,26 +8,6 @@ const log = require('debug')('eslint-plugin-import:resolver:node');
 
 exports.interfaceVersion = 2;
 
-exports.resolve = function (source, file, config) {
-  log('Resolving:', source, 'from:', file);
-  let resolvedPath;
-
-  if (isCoreModule(source)) {
-    log('resolved to core');
-    return { found: true, path: null };
-  }
-
-  try {
-    const cachedFilter = function (pkg, dir) { return packageFilter(pkg, dir, config); };
-    resolvedPath = resolve(source, opts(file, config, cachedFilter));
-    log('Resolved to:', resolvedPath);
-    return { found: true, path: resolvedPath };
-  } catch (err) {
-    log('resolve threw error:', err);
-    return { found: false };
-  }
-};
-
 function opts(file, config, packageFilter) {
   return Object.assign({ // more closely matches Node (#333)
     // plus 'mjs' for native modules! (#939)
@@ -64,3 +44,23 @@ function packageFilter(pkg, dir, config) {
   }
   return pkg;
 }
+
+exports.resolve = function (source, file, config) {
+  log('Resolving:', source, 'from:', file);
+  let resolvedPath;
+
+  if (isCoreModule(source)) {
+    log('resolved to core');
+    return { found: true, path: null };
+  }
+
+  try {
+    const cachedFilter = function (pkg, dir) { return packageFilter(pkg, dir, config); };
+    resolvedPath = resolve(source, opts(file, config, cachedFilter));
+    log('Resolved to:', resolvedPath);
+    return { found: true, path: resolvedPath };
+  } catch (err) {
+    log('resolve threw error:', err);
+    return { found: false };
+  }
+};
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 3ca2874dd8..da16eda593 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -16,203 +16,133 @@ const log = require('debug')('eslint-plugin-import:resolver:webpack');
 
 exports.interfaceVersion = 2;
 
-/**
- * Find the full path to 'source', given 'file' as a full reference path.
- *
- * resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js'
- * @param  {string} source - the module to resolve; i.e './some-module'
- * @param  {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js'
- * @param  {object} settings - the webpack config file name, as well as cwd
- * @example
- * options: {
- *  // Path to the webpack config
- *  config: 'webpack.config.js',
- *  // Path to be used to determine where to resolve webpack from
- *  // (may differ from the cwd in some cases)
- *  cwd: process.cwd()
- * }
- * @return {string?} the resolved path to source, undefined if not resolved, or null
- *                   if resolved to a non-FS resource (i.e. script tag at page load)
- */
-exports.resolve = function (source, file, settings) {
-
-  // strip loaders
-  const finalBang = source.lastIndexOf('!');
-  if (finalBang >= 0) {
-    source = source.slice(finalBang + 1);
-  }
-
-  // strip resource query
-  const finalQuestionMark = source.lastIndexOf('?');
-  if (finalQuestionMark >= 0) {
-    source = source.slice(0, finalQuestionMark);
-  }
-
-  let webpackConfig;
-
-  const _configPath = settings && settings.config;
-  /**
-     * Attempt to set the current working directory.
-     * If none is passed, default to the `cwd` where the config is located.
-     */
-  const cwd = settings && settings.cwd;
-  const configIndex = settings && settings['config-index'];
-  const env = settings && settings.env;
-  const argv = settings && typeof settings.argv !== 'undefined' ? settings.argv : {};
-  let packageDir;
-
-  let configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
-    ? path.resolve(_configPath)
-    : _configPath;
-
-  log('Config path from settings:', configPath);
-
-  // see if we've got a config path, a config object, an array of config objects or a config function
-  if (!configPath || typeof configPath === 'string') {
-
-    // see if we've got an absolute path
-    if (!configPath || !path.isAbsolute(configPath)) {
-      // if not, find ancestral package.json and use its directory as base for the path
-      packageDir = findRoot(path.resolve(file));
-      if (!packageDir) { throw new Error('package not found above ' + file); }
-    }
-
-    configPath = findConfigPath(configPath, packageDir);
-
-    log('Config path resolved to:', configPath);
-    if (configPath) {
-      try {
-        webpackConfig = require(configPath);
-      } catch (e) {
-        console.log('Error resolving webpackConfig', e);
-        throw e;
-      }
+function registerCompiler(moduleDescriptor) {
+  if (moduleDescriptor) {
+    if (typeof moduleDescriptor === 'string') {
+      require(moduleDescriptor);
+    } else if (!Array.isArray(moduleDescriptor)) {
+      moduleDescriptor.register(require(moduleDescriptor.module));
     } else {
-      log('No config path found relative to', file, '; using {}');
-      webpackConfig = {};
-    }
-
-    if (webpackConfig && webpackConfig.default) {
-      log('Using ES6 module "default" key instead of module.exports.');
-      webpackConfig = webpackConfig.default;
+      for (let i = 0; i < moduleDescriptor.length; i++) {
+        try {
+          registerCompiler(moduleDescriptor[i]);
+          break;
+        } catch (e) {
+          log('Failed to register compiler for moduleDescriptor[]:', i, moduleDescriptor);
+        }
+      }
     }
-
-  } else {
-    webpackConfig = configPath;
-    configPath = null;
   }
+}
 
-  if (typeof webpackConfig === 'function') {
-    webpackConfig = webpackConfig(env, argv);
-  }
+function findConfigPath(configPath, packageDir) {
+  const extensions = Object.keys(interpret.extensions).sort(function (a, b) {
+    return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length;
+  });
+  let extension;
 
-  if (Array.isArray(webpackConfig)) {
-    webpackConfig = webpackConfig.map((cfg) => {
-      if (typeof cfg === 'function') {
-        return cfg(env, argv);
+  if (configPath) {
+    // extensions is not reused below, so safe to mutate it here.
+    extensions.reverse();
+    extensions.forEach(function (maybeExtension) {
+      if (extension) {
+        return;
       }
 
-      return cfg;
+      if (configPath.substr(-maybeExtension.length) === maybeExtension) {
+        extension = maybeExtension;
+      }
     });
 
-    if (typeof configIndex !== 'undefined' && webpackConfig.length > configIndex) {
-      webpackConfig = webpackConfig[configIndex];
-    } else {
-      webpackConfig = find(webpackConfig, function findFirstWithResolve(config) {
-        return !!config.resolve;
-      });
+    // see if we've got an absolute path
+    if (!path.isAbsolute(configPath)) {
+      configPath = path.join(packageDir, configPath);
     }
-  }
-
-  if (typeof webpackConfig.then === 'function') {
-    webpackConfig = {};
+  } else {
+    extensions.forEach(function (maybeExtension) {
+      if (extension) {
+        return;
+      }
 
-    console.warn('Webpack config returns a `Promise`; that signature is not supported at the moment. Using empty object instead.');
+      const maybePath = path.resolve(
+        path.join(packageDir, 'webpack.config' + maybeExtension)
+      );
+      if (fs.existsSync(maybePath)) {
+        configPath = maybePath;
+        extension = maybeExtension;
+      }
+    });
   }
 
-  if (webpackConfig == null) {
-    webpackConfig = {};
-
-    console.warn('No webpack configuration with a "resolve" field found. Using empty object instead.');
-  }
+  registerCompiler(interpret.extensions[extension]);
+  return configPath;
+}
 
-  log('Using config: ', webpackConfig);
+function findExternal(source, externals, context, resolveSync) {
+  if (!externals) { return false; }
 
-  const resolveSync = getResolveSync(configPath, webpackConfig, cwd);
+  // string match
+  if (typeof externals === 'string') { return source === externals; }
 
-  // externals
-  if (findExternal(source, webpackConfig.externals, path.dirname(file), resolveSync)) {
-    return { found: true, path: null };
+  // array: recurse
+  if (Array.isArray(externals)) {
+    return externals.some(function (e) { return findExternal(source, e, context, resolveSync); });
   }
 
-  // otherwise, resolve "normally"
-
-  try {
-    return { found: true, path: resolveSync(path.dirname(file), source) };
-  } catch (err) {
-    if (isCore(source)) {
-      return { found: true, path: null };
-    }
-
-    log('Error during module resolution:', err);
-    return { found: false };
+  if (isRegex(externals)) {
+    return externals.test(source);
   }
-};
 
-const MAX_CACHE = 10;
-const _cache = [];
-function getResolveSync(configPath, webpackConfig, cwd) {
-  const cacheKey = { configPath, webpackConfig };
-  let cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
-  if (!cached) {
-    cached = {
-      key: cacheKey,
-      value: createResolveSync(configPath, webpackConfig, cwd),
+  if (typeof externals === 'function') {
+    let functionExternalFound = false;
+    const callback = function (err, value) {
+      if (err) {
+        functionExternalFound = false;
+      } else {
+        functionExternalFound = findExternal(source, value, context, resolveSync);
+      }
     };
-    // put in front and pop last item
-    if (_cache.unshift(cached) > MAX_CACHE) {
-      _cache.pop();
+    // - for prior webpack 5, 'externals function' uses 3 arguments
+    // - for webpack 5, the count of arguments is less than 3
+    if (externals.length === 3) {
+      externals.call(null, context, source, callback);
+    } else {
+      const ctx = {
+        context,
+        request: source,
+        contextInfo: {
+          issuer: '',
+          issuerLayer: null,
+          compiler: '',
+        },
+        getResolve: () => (resolveContext, requestToResolve, cb) => {
+          if (cb) {
+            try {
+              cb(null, resolveSync(resolveContext, requestToResolve));
+            } catch (e) {
+              cb(e);
+            }
+          } else {
+            log('getResolve without callback not supported');
+            return Promise.reject(new Error('Not supported'));
+          }
+        },
+      };
+      const result = externals.call(null, ctx, callback);
+      // todo handling Promise object (using synchronous-promise package?)
+      if (result && typeof result.then === 'function') {
+        log('Asynchronous functions for externals not supported');
+      }
     }
-  }
-  return cached.value;
-}
-
-function createResolveSync(configPath, webpackConfig, cwd) {
-  let webpackRequire;
-  let basedir = null;
-
-  if (typeof configPath === 'string') {
-    // This can be changed via the settings passed in when defining the resolver
-    basedir = cwd || path.dirname(configPath);
-    log(`Attempting to load webpack path from ${basedir}`);
-  }
-
-  try {
-    // Attempt to resolve webpack from the given `basedir`
-    const webpackFilename = resolve('webpack', { basedir, preserveSymlinks: false });
-    const webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false };
-
-    webpackRequire = function (id) {
-      return require(resolve(id, webpackResolveOpts));
-    };
-  } catch (e) {
-    // Something has gone wrong (or we're in a test). Use our own bundled
-    // enhanced-resolve.
-    log('Using bundled enhanced-resolve.');
-    webpackRequire = require;
+    return functionExternalFound;
   }
 
-  const enhancedResolvePackage = webpackRequire('enhanced-resolve/package.json');
-  const enhancedResolveVersion = enhancedResolvePackage.version;
-  log('enhanced-resolve version:', enhancedResolveVersion);
-
-  const resolveConfig = webpackConfig.resolve || {};
-
-  if (semver.major(enhancedResolveVersion) >= 2) {
-    return createWebpack2ResolveSync(webpackRequire, resolveConfig);
+  // else, vanilla object
+  for (const key in externals) {
+    if (!hasOwn(externals, key)) { continue; }
+    if (source === key) { return true; }
   }
-
-  return createWebpack1ResolveSync(webpackRequire, resolveConfig, webpackConfig.plugins);
+  return false;
 }
 
 /**
@@ -242,6 +172,22 @@ const webpack1DefaultMains = [
   'webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main',
 ];
 
+/* eslint-disable */
+// from https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L365
+function makeRootPlugin(ModulesInRootPlugin, name, root) {
+  if (typeof root === 'string') {
+    return new ModulesInRootPlugin(name, root);
+  } else if (Array.isArray(root)) {
+    return function() {
+      root.forEach(function (root) {
+        this.apply(new ModulesInRootPlugin(name, root));
+      }, this);
+    };
+  }
+  return function () {};
+}
+/* eslint-enable */
+
 // adapted from tests &
 // https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L322
 function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
@@ -298,154 +244,208 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
     });
   }
 
-  resolver.apply.apply(resolver, resolvePlugins);
-
-  return function () {
-    return resolver.resolveSync.apply(resolver, arguments);
-  };
+  resolver.apply.apply(resolver, resolvePlugins);
+
+  return function () {
+    return resolver.resolveSync.apply(resolver, arguments);
+  };
+}
+
+function createResolveSync(configPath, webpackConfig, cwd) {
+  let webpackRequire;
+  let basedir = null;
+
+  if (typeof configPath === 'string') {
+    // This can be changed via the settings passed in when defining the resolver
+    basedir = cwd || path.dirname(configPath);
+    log(`Attempting to load webpack path from ${basedir}`);
+  }
+
+  try {
+    // Attempt to resolve webpack from the given `basedir`
+    const webpackFilename = resolve('webpack', { basedir, preserveSymlinks: false });
+    const webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false };
+
+    webpackRequire = function (id) {
+      return require(resolve(id, webpackResolveOpts));
+    };
+  } catch (e) {
+    // Something has gone wrong (or we're in a test). Use our own bundled
+    // enhanced-resolve.
+    log('Using bundled enhanced-resolve.');
+    webpackRequire = require;
+  }
+
+  const enhancedResolvePackage = webpackRequire('enhanced-resolve/package.json');
+  const enhancedResolveVersion = enhancedResolvePackage.version;
+  log('enhanced-resolve version:', enhancedResolveVersion);
+
+  const resolveConfig = webpackConfig.resolve || {};
+
+  if (semver.major(enhancedResolveVersion) >= 2) {
+    return createWebpack2ResolveSync(webpackRequire, resolveConfig);
+  }
+
+  return createWebpack1ResolveSync(webpackRequire, resolveConfig, webpackConfig.plugins);
 }
 
-/* eslint-disable */
-// from https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L365
-function makeRootPlugin(ModulesInRootPlugin, name, root) {
-  if (typeof root === 'string') {
-    return new ModulesInRootPlugin(name, root);
-  } else if (Array.isArray(root)) {
-    return function() {
-      root.forEach(function (root) {
-        this.apply(new ModulesInRootPlugin(name, root));
-      }, this);
+const MAX_CACHE = 10;
+const _cache = [];
+function getResolveSync(configPath, webpackConfig, cwd) {
+  const cacheKey = { configPath, webpackConfig };
+  let cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
+  if (!cached) {
+    cached = {
+      key: cacheKey,
+      value: createResolveSync(configPath, webpackConfig, cwd),
     };
+    // put in front and pop last item
+    if (_cache.unshift(cached) > MAX_CACHE) {
+      _cache.pop();
+    }
   }
-  return function () {};
+  return cached.value;
 }
-/* eslint-enable */
 
-function findExternal(source, externals, context, resolveSync) {
-  if (!externals) { return false; }
-
-  // string match
-  if (typeof externals === 'string') { return source === externals; }
+/**
+ * Find the full path to 'source', given 'file' as a full reference path.
+ *
+ * resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js'
+ * @param  {string} source - the module to resolve; i.e './some-module'
+ * @param  {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js'
+ * @param  {object} settings - the webpack config file name, as well as cwd
+ * @example
+ * options: {
+ *  // Path to the webpack config
+ *  config: 'webpack.config.js',
+ *  // Path to be used to determine where to resolve webpack from
+ *  // (may differ from the cwd in some cases)
+ *  cwd: process.cwd()
+ * }
+ * @return {string?} the resolved path to source, undefined if not resolved, or null
+ *                   if resolved to a non-FS resource (i.e. script tag at page load)
+ */
+exports.resolve = function (source, file, settings) {
 
-  // array: recurse
-  if (Array.isArray(externals)) {
-    return externals.some(function (e) { return findExternal(source, e, context, resolveSync); });
+  // strip loaders
+  const finalBang = source.lastIndexOf('!');
+  if (finalBang >= 0) {
+    source = source.slice(finalBang + 1);
   }
 
-  if (isRegex(externals)) {
-    return externals.test(source);
+  // strip resource query
+  const finalQuestionMark = source.lastIndexOf('?');
+  if (finalQuestionMark >= 0) {
+    source = source.slice(0, finalQuestionMark);
   }
 
-  if (typeof externals === 'function') {
-    let functionExternalFound = false;
-    const callback = function (err, value) {
-      if (err) {
-        functionExternalFound = false;
-      } else {
-        functionExternalFound = findExternal(source, value, context, resolveSync);
+  let webpackConfig;
+
+  const _configPath = settings && settings.config;
+  /**
+     * Attempt to set the current working directory.
+     * If none is passed, default to the `cwd` where the config is located.
+     */
+  const cwd = settings && settings.cwd;
+  const configIndex = settings && settings['config-index'];
+  const env = settings && settings.env;
+  const argv = settings && typeof settings.argv !== 'undefined' ? settings.argv : {};
+  let packageDir;
+
+  let configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
+    ? path.resolve(_configPath)
+    : _configPath;
+
+  log('Config path from settings:', configPath);
+
+  // see if we've got a config path, a config object, an array of config objects or a config function
+  if (!configPath || typeof configPath === 'string') {
+
+    // see if we've got an absolute path
+    if (!configPath || !path.isAbsolute(configPath)) {
+      // if not, find ancestral package.json and use its directory as base for the path
+      packageDir = findRoot(path.resolve(file));
+      if (!packageDir) { throw new Error('package not found above ' + file); }
+    }
+
+    configPath = findConfigPath(configPath, packageDir);
+
+    log('Config path resolved to:', configPath);
+    if (configPath) {
+      try {
+        webpackConfig = require(configPath);
+      } catch (e) {
+        console.log('Error resolving webpackConfig', e);
+        throw e;
       }
-    };
-    // - for prior webpack 5, 'externals function' uses 3 arguments
-    // - for webpack 5, the count of arguments is less than 3
-    if (externals.length === 3) {
-      externals.call(null, context, source, callback);
     } else {
-      const ctx = {
-        context,
-        request: source,
-        contextInfo: {
-          issuer: '',
-          issuerLayer: null,
-          compiler: '',
-        },
-        getResolve: () => (resolveContext, requestToResolve, cb) => {
-          if (cb) {
-            try {
-              cb(null, resolveSync(resolveContext, requestToResolve));
-            } catch (e) {
-              cb(e);
-            }
-          } else {
-            log('getResolve without callback not supported');
-            return Promise.reject(new Error('Not supported'));
-          }
-        },
-      };
-      const result = externals.call(null, ctx, callback);
-      // todo handling Promise object (using synchronous-promise package?)
-      if (result && typeof result.then === 'function') {
-        log('Asynchronous functions for externals not supported');
-      }
+      log('No config path found relative to', file, '; using {}');
+      webpackConfig = {};
     }
-    return functionExternalFound;
-  }
 
-  // else, vanilla object
-  for (const key in externals) {
-    if (!hasOwn(externals, key)) { continue; }
-    if (source === key) { return true; }
+    if (webpackConfig && webpackConfig.default) {
+      log('Using ES6 module "default" key instead of module.exports.');
+      webpackConfig = webpackConfig.default;
+    }
+
+  } else {
+    webpackConfig = configPath;
+    configPath = null;
   }
-  return false;
-}
 
-function findConfigPath(configPath, packageDir) {
-  const extensions = Object.keys(interpret.extensions).sort(function (a, b) {
-    return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length;
-  });
-  let extension;
+  if (typeof webpackConfig === 'function') {
+    webpackConfig = webpackConfig(env, argv);
+  }
 
-  if (configPath) {
-    // extensions is not reused below, so safe to mutate it here.
-    extensions.reverse();
-    extensions.forEach(function (maybeExtension) {
-      if (extension) {
-        return;
+  if (Array.isArray(webpackConfig)) {
+    webpackConfig = webpackConfig.map((cfg) => {
+      if (typeof cfg === 'function') {
+        return cfg(env, argv);
       }
 
-      if (configPath.substr(-maybeExtension.length) === maybeExtension) {
-        extension = maybeExtension;
-      }
+      return cfg;
     });
 
-    // see if we've got an absolute path
-    if (!path.isAbsolute(configPath)) {
-      configPath = path.join(packageDir, configPath);
+    if (typeof configIndex !== 'undefined' && webpackConfig.length > configIndex) {
+      webpackConfig = webpackConfig[configIndex];
+    } else {
+      webpackConfig = find(webpackConfig, function findFirstWithResolve(config) {
+        return !!config.resolve;
+      });
     }
-  } else {
-    extensions.forEach(function (maybeExtension) {
-      if (extension) {
-        return;
-      }
+  }
 
-      const maybePath = path.resolve(
-        path.join(packageDir, 'webpack.config' + maybeExtension)
-      );
-      if (fs.existsSync(maybePath)) {
-        configPath = maybePath;
-        extension = maybeExtension;
-      }
-    });
+  if (typeof webpackConfig.then === 'function') {
+    webpackConfig = {};
+
+    console.warn('Webpack config returns a `Promise`; that signature is not supported at the moment. Using empty object instead.');
   }
 
-  registerCompiler(interpret.extensions[extension]);
-  return configPath;
-}
+  if (webpackConfig == null) {
+    webpackConfig = {};
 
-function registerCompiler(moduleDescriptor) {
-  if (moduleDescriptor) {
-    if (typeof moduleDescriptor === 'string') {
-      require(moduleDescriptor);
-    } else if (!Array.isArray(moduleDescriptor)) {
-      moduleDescriptor.register(require(moduleDescriptor.module));
-    } else {
-      for (let i = 0; i < moduleDescriptor.length; i++) {
-        try {
-          registerCompiler(moduleDescriptor[i]);
-          break;
-        } catch (e) {
-          log('Failed to register compiler for moduleDescriptor[]:', i, moduleDescriptor);
-        }
-      }
+    console.warn('No webpack configuration with a "resolve" field found. Using empty object instead.');
+  }
+
+  log('Using config: ', webpackConfig);
+
+  const resolveSync = getResolveSync(configPath, webpackConfig, cwd);
+
+  // externals
+  if (findExternal(source, webpackConfig.externals, path.dirname(file), resolveSync)) {
+    return { found: true, path: null };
+  }
+
+  // otherwise, resolve "normally"
+
+  try {
+    return { found: true, path: resolveSync(path.dirname(file), source) };
+  } catch (err) {
+    if (isCore(source)) {
+      return { found: true, path: null };
     }
+
+    log('Error during module resolution:', err);
+    return { found: false };
   }
-}
+};

From 70ca58fac5d2b2c827caa06fb1925c623e3f4034 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 13 Mar 2024 14:23:38 -0700
Subject: [PATCH 666/767] [utils] [refactor] avoid hoisting

---
 utils/ignore.js  |  36 +++++++--------
 utils/parse.js   |  82 ++++++++++++++++-----------------
 utils/resolve.js | 116 +++++++++++++++++++++++------------------------
 3 files changed, 117 insertions(+), 117 deletions(-)

diff --git a/utils/ignore.js b/utils/ignore.js
index 59ac821eb8..56f2ef7239 100644
--- a/utils/ignore.js
+++ b/utils/ignore.js
@@ -10,17 +10,6 @@ const log = require('debug')('eslint-plugin-import:utils:ignore');
 /** @type {Set<import('./types').Extension>} */ let cachedSet;
 /** @type {import('./types').ESLintSettings} */ let lastSettings;
 
-/** @type {(context: import('eslint').Rule.RuleContext) => Set<import('./types').Extension>} */
-function validExtensions(context) {
-  if (cachedSet && context.settings === lastSettings) {
-    return cachedSet;
-  }
-
-  lastSettings = context.settings;
-  cachedSet = makeValidExtensionSet(context.settings);
-  return cachedSet;
-}
-
 /** @type {import('./ignore').getFileExtensions} */
 function makeValidExtensionSet(settings) {
   // start with explicit JS-parsed extensions
@@ -42,6 +31,24 @@ function makeValidExtensionSet(settings) {
 }
 exports.getFileExtensions = makeValidExtensionSet;
 
+/** @type {(context: import('eslint').Rule.RuleContext) => Set<import('./types').Extension>} */
+function validExtensions(context) {
+  if (cachedSet && context.settings === lastSettings) {
+    return cachedSet;
+  }
+
+  lastSettings = context.settings;
+  cachedSet = makeValidExtensionSet(context.settings);
+  return cachedSet;
+}
+
+/** @type {import('./ignore').hasValidExtension} */
+function hasValidExtension(path, context) {
+  // eslint-disable-next-line no-extra-parens
+  return validExtensions(context).has(/** @type {import('./types').Extension} */ (extname(path)));
+}
+exports.hasValidExtension = hasValidExtension;
+
 /** @type {import('./ignore').default} */
 exports.default = function ignore(path, context) {
   // check extension whitelist first (cheap)
@@ -60,10 +67,3 @@ exports.default = function ignore(path, context) {
 
   return false;
 };
-
-/** @type {import('./ignore').hasValidExtension} */
-function hasValidExtension(path, context) {
-  // eslint-disable-next-line no-extra-parens
-  return validExtensions(context).has(/** @type {import('./types').Extension} */ (extname(path)));
-}
-exports.hasValidExtension = hasValidExtension;
diff --git a/utils/parse.js b/utils/parse.js
index 804186ca97..94aca1d0f8 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -61,6 +61,47 @@ function transformHashbang(text) {
   return text.replace(/^#!([^\r\n]+)/u, (_, captured) => `//${captured}`);
 }
 
+/** @type {(path: string, context: import('eslint').Rule.RuleContext & { settings?: ESLintSettings }) => import('eslint').Rule.RuleContext['parserPath']} */
+function getParserPath(path, context) {
+  const parsers = context.settings['import/parsers'];
+  if (parsers != null) {
+    // eslint-disable-next-line no-extra-parens
+    const extension = /** @type {Extension} */ (extname(path));
+    for (const parserPath in parsers) {
+      if (parsers[parserPath].indexOf(extension) > -1) {
+        // use this alternate parser
+        log('using alt parser:', parserPath);
+        return parserPath;
+      }
+    }
+  }
+  // default to use ESLint parser
+  return context.parserPath;
+}
+
+/** @type {(path: string, context: import('eslint').Rule.RuleContext) => string | null | (import('eslint').Linter.ParserModule)} */
+function getParser(path, context) {
+  const parserPath = getParserPath(path, context);
+  if (parserPath) {
+    return parserPath;
+  }
+  if (
+    !!context.languageOptions
+    && !!context.languageOptions.parser
+    && typeof context.languageOptions.parser !== 'string'
+    && (
+      // @ts-expect-error TODO: figure out a better type
+      typeof context.languageOptions.parser.parse === 'function'
+      // @ts-expect-error TODO: figure out a better type
+      || typeof context.languageOptions.parser.parseForESLint === 'function'
+    )
+  ) {
+    return context.languageOptions.parser;
+  }
+
+  return null;
+}
+
 /** @type {import('./parse').default} */
 exports.default = function parse(path, content, context) {
   if (context == null) { throw new Error('need context to parse properly'); }
@@ -131,44 +172,3 @@ exports.default = function parse(path, content, context) {
   // @ts-expect-error TODO: FIXME
   return makeParseReturn(ast, keysFromParser(parserOrPath, parser, undefined));
 };
-
-/** @type {(path: string, context: import('eslint').Rule.RuleContext) => string | null | (import('eslint').Linter.ParserModule)} */
-function getParser(path, context) {
-  const parserPath = getParserPath(path, context);
-  if (parserPath) {
-    return parserPath;
-  }
-  if (
-    !!context.languageOptions
-    && !!context.languageOptions.parser
-    && typeof context.languageOptions.parser !== 'string'
-    && (
-      // @ts-expect-error TODO: figure out a better type
-      typeof context.languageOptions.parser.parse === 'function'
-      // @ts-expect-error TODO: figure out a better type
-      || typeof context.languageOptions.parser.parseForESLint === 'function'
-    )
-  ) {
-    return context.languageOptions.parser;
-  }
-
-  return null;
-}
-
-/** @type {(path: string, context: import('eslint').Rule.RuleContext & { settings?: ESLintSettings }) => import('eslint').Rule.RuleContext['parserPath']} */
-function getParserPath(path, context) {
-  const parsers = context.settings['import/parsers'];
-  if (parsers != null) {
-    // eslint-disable-next-line no-extra-parens
-    const extension = /** @type {Extension} */ (extname(path));
-    for (const parserPath in parsers) {
-      if (parsers[parserPath].indexOf(extension) > -1) {
-        // use this alternate parser
-        log('using alt parser:', parserPath);
-        return parserPath;
-      }
-    }
-  }
-  // default to use ESLint parser
-  return context.parserPath;
-}
diff --git a/utils/resolve.js b/utils/resolve.js
index 05f7b35abf..5a3084351e 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -34,6 +34,14 @@ const createRequire = Module.createRequire
     return mod.exports;
   };
 
+/** @type {(resolver: object) => resolver is import('./resolve').Resolver} */
+function isResolverValid(resolver) {
+  if ('interfaceVersion' in resolver && resolver.interfaceVersion === 2) {
+    return 'resolve' in resolver && !!resolver.resolve && typeof resolver.resolve === 'function';
+  }
+  return 'resolveImport' in resolver && !!resolver.resolveImport && typeof resolver.resolveImport === 'function';
+}
+
 /** @type {<T extends string>(target: T, sourceFile?: string | null | undefined) => undefined | ReturnType<typeof require>} */
 function tryRequire(target, sourceFile) {
   let resolved;
@@ -57,6 +65,56 @@ function tryRequire(target, sourceFile) {
   return require(resolved);
 }
 
+/** @type {<T extends Map<string, unknown>>(resolvers: string[] | string | { [k: string]: string }, map: T) => T} */
+function resolverReducer(resolvers, map) {
+  if (Array.isArray(resolvers)) {
+    resolvers.forEach((r) => resolverReducer(r, map));
+    return map;
+  }
+
+  if (typeof resolvers === 'string') {
+    map.set(resolvers, null);
+    return map;
+  }
+
+  if (typeof resolvers === 'object') {
+    for (const key in resolvers) {
+      map.set(key, resolvers[key]);
+    }
+    return map;
+  }
+
+  const err = new Error('invalid resolver config');
+  err.name = ERROR_NAME;
+  throw err;
+}
+
+/** @type {(sourceFile: string) => string} */
+function getBaseDir(sourceFile) {
+  return pkgDir(sourceFile) || process.cwd();
+}
+
+/** @type {(name: string, sourceFile: string) => import('./resolve').Resolver} */
+function requireResolver(name, sourceFile) {
+  // Try to resolve package with conventional name
+  const resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile)
+    || tryRequire(name, sourceFile)
+    || tryRequire(path.resolve(getBaseDir(sourceFile), name));
+
+  if (!resolver) {
+    const err = new Error(`unable to load resolver "${name}".`);
+    err.name = ERROR_NAME;
+    throw err;
+  }
+  if (!isResolverValid(resolver)) {
+    const err = new Error(`${name} with invalid interface loaded as resolver`);
+    err.name = ERROR_NAME;
+    throw err;
+  }
+
+  return resolver;
+}
+
 // https://stackoverflow.com/a/27382838
 /** @type {import('./resolve').fileExistsWithCaseSync} */
 exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings, strict) {
@@ -159,64 +217,6 @@ function relative(modulePath, sourceFile, settings) {
 }
 exports.relative = relative;
 
-/** @type {<T extends Map<string, unknown>>(resolvers: string[] | string | { [k: string]: string }, map: T) => T} */
-function resolverReducer(resolvers, map) {
-  if (Array.isArray(resolvers)) {
-    resolvers.forEach((r) => resolverReducer(r, map));
-    return map;
-  }
-
-  if (typeof resolvers === 'string') {
-    map.set(resolvers, null);
-    return map;
-  }
-
-  if (typeof resolvers === 'object') {
-    for (const key in resolvers) {
-      map.set(key, resolvers[key]);
-    }
-    return map;
-  }
-
-  const err = new Error('invalid resolver config');
-  err.name = ERROR_NAME;
-  throw err;
-}
-
-/** @type {(sourceFile: string) => string} */
-function getBaseDir(sourceFile) {
-  return pkgDir(sourceFile) || process.cwd();
-}
-
-/** @type {(name: string, sourceFile: string) => import('./resolve').Resolver} */
-function requireResolver(name, sourceFile) {
-  // Try to resolve package with conventional name
-  const resolver = tryRequire(`eslint-import-resolver-${name}`, sourceFile)
-    || tryRequire(name, sourceFile)
-    || tryRequire(path.resolve(getBaseDir(sourceFile), name));
-
-  if (!resolver) {
-    const err = new Error(`unable to load resolver "${name}".`);
-    err.name = ERROR_NAME;
-    throw err;
-  }
-  if (!isResolverValid(resolver)) {
-    const err = new Error(`${name} with invalid interface loaded as resolver`);
-    err.name = ERROR_NAME;
-    throw err;
-  }
-
-  return resolver;
-}
-
-/** @type {(resolver: object) => resolver is import('./resolve').Resolver} */
-function isResolverValid(resolver) {
-  if ('interfaceVersion' in resolver && resolver.interfaceVersion === 2) {
-    return 'resolve' in resolver && !!resolver.resolve && typeof resolver.resolve === 'function';
-  }
-  return 'resolveImport' in resolver && !!resolver.resolveImport && typeof resolver.resolveImport === 'function';
-}
-
 /** @type {Set<import('eslint').Rule.RuleContext>} */
 const erroredContexts = new Set();
 

From 2efdf79af9a543a4c4cb02265a56acc2b7ed0317 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 13 Mar 2024 14:23:50 -0700
Subject: [PATCH 667/767] [eslint] avoid hoisting

---
 .eslintrc                        |  10 ++
 src/core/importType.js           |  49 +++++-----
 src/core/packagePath.js          |   8 +-
 src/rules/no-cycle.js            |   8 +-
 src/rules/no-duplicates.js       | 160 +++++++++++++++----------------
 src/rules/no-namespace.js        | 140 +++++++++++++--------------
 src/rules/no-restricted-paths.js |  18 ++--
 src/rules/order.js               |  12 +--
 tests/src/package.js             |  14 +--
 tests/src/utils.js               |   8 +-
 10 files changed, 216 insertions(+), 211 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index ddf7bc5628..8dc0b2637a 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -96,6 +96,7 @@
         "no-multiple-empty-lines": [2, { "max": 1, "maxEOF": 1, "maxBOF": 0 }],
         "no-return-assign": [2, "always"],
         "no-trailing-spaces": 2,
+        "no-use-before-define": [2, { "functions": true, "classes": true, "variables": true }],
         "no-var": 2,
         "object-curly-spacing": [2, "always"],
         "object-shorthand": ["error", "always", {
@@ -225,6 +226,15 @@
                 "no-console": 1,
             },
         },
+        {
+            "files": [
+                "utils/**", // TODO
+                "src/ExportMap.js", // TODO
+            ],
+            "rules": {
+                "no-use-before-define": "off",
+            },
+        },
         {
             "files": [
                 "resolvers/*/test/**/*",
diff --git a/src/core/importType.js b/src/core/importType.js
index 6a37d1bb14..32e200f1de 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -4,6 +4,11 @@ import isCoreModule from 'is-core-module';
 import resolve from 'eslint-module-utils/resolve';
 import { getContextPackagePath } from './packagePath';
 
+const scopedRegExp = /^@[^/]+\/?[^/]+/;
+export function isScoped(name) {
+  return name && scopedRegExp.test(name);
+}
+
 function baseModule(name) {
   if (isScoped(name)) {
     const [scope, pkg] = name.split('/');
@@ -30,20 +35,6 @@ export function isBuiltIn(name, settings, path) {
   return isCoreModule(base) || extras.indexOf(base) > -1;
 }
 
-export function isExternalModule(name, path, context) {
-  if (arguments.length < 3) {
-    throw new TypeError('isExternalModule: name, path, and context are all required');
-  }
-  return (isModule(name) || isScoped(name)) && typeTest(name, context, path) === 'external';
-}
-
-export function isExternalModuleMain(name, path, context) {
-  if (arguments.length < 3) {
-    throw new TypeError('isExternalModule: name, path, and context are all required');
-  }
-  return isModuleMain(name) && typeTest(name, context, path) === 'external';
-}
-
 const moduleRegExp = /^\w/;
 function isModule(name) {
   return name && moduleRegExp.test(name);
@@ -54,20 +45,9 @@ function isModuleMain(name) {
   return name && moduleMainRegExp.test(name);
 }
 
-const scopedRegExp = /^@[^/]+\/?[^/]+/;
-export function isScoped(name) {
-  return name && scopedRegExp.test(name);
-}
-
-const scopedMainRegExp = /^@[^/]+\/?[^/]+$/;
-export function isScopedMain(name) {
-  return name && scopedMainRegExp.test(name);
-}
-
 function isRelativeToParent(name) {
   return (/^\.\.$|^\.\.[\\/]/).test(name);
 }
-
 const indexFiles = ['.', './', './index', './index.js'];
 function isIndex(name) {
   return indexFiles.indexOf(name) !== -1;
@@ -123,6 +103,25 @@ function typeTest(name, context, path) {
   return 'unknown';
 }
 
+export function isExternalModule(name, path, context) {
+  if (arguments.length < 3) {
+    throw new TypeError('isExternalModule: name, path, and context are all required');
+  }
+  return (isModule(name) || isScoped(name)) && typeTest(name, context, path) === 'external';
+}
+
+export function isExternalModuleMain(name, path, context) {
+  if (arguments.length < 3) {
+    throw new TypeError('isExternalModule: name, path, and context are all required');
+  }
+  return isModuleMain(name) && typeTest(name, context, path) === 'external';
+}
+
+const scopedMainRegExp = /^@[^/]+\/?[^/]+$/;
+export function isScopedMain(name) {
+  return name && scopedMainRegExp.test(name);
+}
+
 export default function resolveImportType(name, context) {
   return typeTest(name, context, resolve(name, context));
 }
diff --git a/src/core/packagePath.js b/src/core/packagePath.js
index 1a7a28f4b4..142f44aa4d 100644
--- a/src/core/packagePath.js
+++ b/src/core/packagePath.js
@@ -2,15 +2,15 @@ import { dirname } from 'path';
 import pkgUp from 'eslint-module-utils/pkgUp';
 import readPkgUp from 'eslint-module-utils/readPkgUp';
 
-export function getContextPackagePath(context) {
-  return getFilePackagePath(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
-}
-
 export function getFilePackagePath(filePath) {
   const fp = pkgUp({ cwd: filePath });
   return dirname(fp);
 }
 
+export function getContextPackagePath(context) {
+  return getFilePackagePath(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
+}
+
 export function getFilePackageName(filePath) {
   const { pkg, path } = readPkgUp({ cwd: filePath, normalize: false });
   if (pkg) {
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 5b9d8c0709..11c2f44fc0 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -11,6 +11,10 @@ import docsUrl from '../docsUrl';
 
 const traversed = new Set();
 
+function routeString(route) {
+  return route.map((s) => `${s.value}:${s.loc.start.line}`).join('=>');
+}
+
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -151,7 +155,3 @@ module.exports = {
     });
   },
 };
-
-function routeString(route) {
-  return route.map((s) => `${s.value}:${s.loc.start.line}`).join('=>');
-}
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 6b4f4d559e..033e854e03 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -9,28 +9,68 @@ try {
   typescriptPkg = require('typescript/package.json'); // eslint-disable-line import/no-extraneous-dependencies
 } catch (e) { /**/ }
 
-function checkImports(imported, context) {
-  for (const [module, nodes] of imported.entries()) {
-    if (nodes.length > 1) {
-      const message = `'${module}' imported multiple times.`;
-      const [first, ...rest] = nodes;
-      const sourceCode = context.getSourceCode();
-      const fix = getFix(first, rest, sourceCode, context);
+function isPunctuator(node, value) {
+  return node.type === 'Punctuator' && node.value === value;
+}
 
-      context.report({
-        node: first.source,
-        message,
-        fix, // Attach the autofix (if any) to the first import.
-      });
+// Get the name of the default import of `node`, if any.
+function getDefaultImportName(node) {
+  const defaultSpecifier = node.specifiers
+    .find((specifier) => specifier.type === 'ImportDefaultSpecifier');
+  return defaultSpecifier != null ? defaultSpecifier.local.name : undefined;
+}
 
-      for (const node of rest) {
-        context.report({
-          node: node.source,
-          message,
-        });
-      }
-    }
-  }
+// Checks whether `node` has a namespace import.
+function hasNamespace(node) {
+  const specifiers = node.specifiers
+    .filter((specifier) => specifier.type === 'ImportNamespaceSpecifier');
+  return specifiers.length > 0;
+}
+
+// Checks whether `node` has any non-default specifiers.
+function hasSpecifiers(node) {
+  const specifiers = node.specifiers
+    .filter((specifier) => specifier.type === 'ImportSpecifier');
+  return specifiers.length > 0;
+}
+
+// Checks whether `node` has a comment (that ends) on the previous line or on
+// the same line as `node` (starts).
+function hasCommentBefore(node, sourceCode) {
+  return sourceCode.getCommentsBefore(node)
+    .some((comment) => comment.loc.end.line >= node.loc.start.line - 1);
+}
+
+// Checks whether `node` has a comment (that starts) on the same line as `node`
+// (ends).
+function hasCommentAfter(node, sourceCode) {
+  return sourceCode.getCommentsAfter(node)
+    .some((comment) => comment.loc.start.line === node.loc.end.line);
+}
+
+// Checks whether `node` has any comments _inside,_ except inside the `{...}`
+// part (if any).
+function hasCommentInsideNonSpecifiers(node, sourceCode) {
+  const tokens = sourceCode.getTokens(node);
+  const openBraceIndex = tokens.findIndex((token) => isPunctuator(token, '{'));
+  const closeBraceIndex = tokens.findIndex((token) => isPunctuator(token, '}'));
+  // Slice away the first token, since we're no looking for comments _before_
+  // `node` (only inside). If there's a `{...}` part, look for comments before
+  // the `{`, but not before the `}` (hence the `+1`s).
+  const someTokens = openBraceIndex >= 0 && closeBraceIndex >= 0
+    ? tokens.slice(1, openBraceIndex + 1).concat(tokens.slice(closeBraceIndex + 1))
+    : tokens.slice(1);
+  return someTokens.some((token) => sourceCode.getCommentsBefore(token).length > 0);
+}
+
+// It's not obvious what the user wants to do with comments associated with
+// duplicate imports, so skip imports with comments when autofixing.
+function hasProblematicComments(node, sourceCode) {
+  return (
+    hasCommentBefore(node, sourceCode)
+    || hasCommentAfter(node, sourceCode)
+    || hasCommentInsideNonSpecifiers(node, sourceCode)
+  );
 }
 
 function getFix(first, rest, sourceCode, context) {
@@ -203,68 +243,28 @@ function getFix(first, rest, sourceCode, context) {
   };
 }
 
-function isPunctuator(node, value) {
-  return node.type === 'Punctuator' && node.value === value;
-}
-
-// Get the name of the default import of `node`, if any.
-function getDefaultImportName(node) {
-  const defaultSpecifier = node.specifiers
-    .find((specifier) => specifier.type === 'ImportDefaultSpecifier');
-  return defaultSpecifier != null ? defaultSpecifier.local.name : undefined;
-}
-
-// Checks whether `node` has a namespace import.
-function hasNamespace(node) {
-  const specifiers = node.specifiers
-    .filter((specifier) => specifier.type === 'ImportNamespaceSpecifier');
-  return specifiers.length > 0;
-}
-
-// Checks whether `node` has any non-default specifiers.
-function hasSpecifiers(node) {
-  const specifiers = node.specifiers
-    .filter((specifier) => specifier.type === 'ImportSpecifier');
-  return specifiers.length > 0;
-}
-
-// It's not obvious what the user wants to do with comments associated with
-// duplicate imports, so skip imports with comments when autofixing.
-function hasProblematicComments(node, sourceCode) {
-  return (
-    hasCommentBefore(node, sourceCode)
-    || hasCommentAfter(node, sourceCode)
-    || hasCommentInsideNonSpecifiers(node, sourceCode)
-  );
-}
-
-// Checks whether `node` has a comment (that ends) on the previous line or on
-// the same line as `node` (starts).
-function hasCommentBefore(node, sourceCode) {
-  return sourceCode.getCommentsBefore(node)
-    .some((comment) => comment.loc.end.line >= node.loc.start.line - 1);
-}
+function checkImports(imported, context) {
+  for (const [module, nodes] of imported.entries()) {
+    if (nodes.length > 1) {
+      const message = `'${module}' imported multiple times.`;
+      const [first, ...rest] = nodes;
+      const sourceCode = context.getSourceCode();
+      const fix = getFix(first, rest, sourceCode, context);
 
-// Checks whether `node` has a comment (that starts) on the same line as `node`
-// (ends).
-function hasCommentAfter(node, sourceCode) {
-  return sourceCode.getCommentsAfter(node)
-    .some((comment) => comment.loc.start.line === node.loc.end.line);
-}
+      context.report({
+        node: first.source,
+        message,
+        fix, // Attach the autofix (if any) to the first import.
+      });
 
-// Checks whether `node` has any comments _inside,_ except inside the `{...}`
-// part (if any).
-function hasCommentInsideNonSpecifiers(node, sourceCode) {
-  const tokens = sourceCode.getTokens(node);
-  const openBraceIndex = tokens.findIndex((token) => isPunctuator(token, '{'));
-  const closeBraceIndex = tokens.findIndex((token) => isPunctuator(token, '}'));
-  // Slice away the first token, since we're no looking for comments _before_
-  // `node` (only inside). If there's a `{...}` part, look for comments before
-  // the `{`, but not before the `}` (hence the `+1`s).
-  const someTokens = openBraceIndex >= 0 && closeBraceIndex >= 0
-    ? tokens.slice(1, openBraceIndex + 1).concat(tokens.slice(closeBraceIndex + 1))
-    : tokens.slice(1);
-  return someTokens.some((token) => sourceCode.getCommentsBefore(token).length > 0);
+      for (const node of rest) {
+        context.report({
+          node: node.source,
+          message,
+        });
+      }
+    }
+  }
 }
 
 module.exports = {
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index d3e591876f..3c6617a41c 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -6,9 +6,74 @@
 import minimatch from 'minimatch';
 import docsUrl from '../docsUrl';
 
-//------------------------------------------------------------------------------
-// Rule Definition
-//------------------------------------------------------------------------------
+/**
+ * @param {MemberExpression} memberExpression
+ * @returns {string} the name of the member in the object expression, e.g. the `x` in `namespace.x`
+ */
+function getMemberPropertyName(memberExpression) {
+  return memberExpression.property.type === 'Identifier'
+    ? memberExpression.property.name
+    : memberExpression.property.value;
+}
+
+/**
+ * @param {ScopeManager} scopeManager
+ * @param {ASTNode} node
+ * @return {Set<string>}
+ */
+function getVariableNamesInScope(scopeManager, node) {
+  let currentNode = node;
+  let scope = scopeManager.acquire(currentNode);
+  while (scope == null) {
+    currentNode = currentNode.parent;
+    scope = scopeManager.acquire(currentNode, true);
+  }
+  return new Set(scope.variables.concat(scope.upper.variables).map((variable) => variable.name));
+}
+
+/**
+ *
+ * @param {*} names
+ * @param {*} nameConflicts
+ * @param {*} namespaceName
+ */
+function generateLocalNames(names, nameConflicts, namespaceName) {
+  const localNames = {};
+  names.forEach((name) => {
+    let localName;
+    if (!nameConflicts[name].has(name)) {
+      localName = name;
+    } else if (!nameConflicts[name].has(`${namespaceName}_${name}`)) {
+      localName = `${namespaceName}_${name}`;
+    } else {
+      for (let i = 1; i < Infinity; i++) {
+        if (!nameConflicts[name].has(`${namespaceName}_${name}_${i}`)) {
+          localName = `${namespaceName}_${name}_${i}`;
+          break;
+        }
+      }
+    }
+    localNames[name] = localName;
+  });
+  return localNames;
+}
+
+/**
+ * @param {Identifier[]} namespaceIdentifiers
+ * @returns {boolean} `true` if the namespace variable is more than just a glorified constant
+ */
+function usesNamespaceAsObject(namespaceIdentifiers) {
+  return !namespaceIdentifiers.every((identifier) => {
+    const parent = identifier.parent;
+
+    // `namespace.x` or `namespace['x']`
+    return (
+      parent
+      && parent.type === 'MemberExpression'
+      && (parent.property.type === 'Identifier' || parent.property.type === 'Literal')
+    );
+  });
+}
 
 module.exports = {
   meta: {
@@ -103,72 +168,3 @@ module.exports = {
     };
   },
 };
-
-/**
- * @param {Identifier[]} namespaceIdentifiers
- * @returns {boolean} `true` if the namespace variable is more than just a glorified constant
- */
-function usesNamespaceAsObject(namespaceIdentifiers) {
-  return !namespaceIdentifiers.every((identifier) => {
-    const parent = identifier.parent;
-
-    // `namespace.x` or `namespace['x']`
-    return (
-      parent
-      && parent.type === 'MemberExpression'
-      && (parent.property.type === 'Identifier' || parent.property.type === 'Literal')
-    );
-  });
-}
-
-/**
- * @param {MemberExpression} memberExpression
- * @returns {string} the name of the member in the object expression, e.g. the `x` in `namespace.x`
- */
-function getMemberPropertyName(memberExpression) {
-  return memberExpression.property.type === 'Identifier'
-    ? memberExpression.property.name
-    : memberExpression.property.value;
-}
-
-/**
- * @param {ScopeManager} scopeManager
- * @param {ASTNode} node
- * @return {Set<string>}
- */
-function getVariableNamesInScope(scopeManager, node) {
-  let currentNode = node;
-  let scope = scopeManager.acquire(currentNode);
-  while (scope == null) {
-    currentNode = currentNode.parent;
-    scope = scopeManager.acquire(currentNode, true);
-  }
-  return new Set(scope.variables.concat(scope.upper.variables).map((variable) => variable.name));
-}
-
-/**
- *
- * @param {*} names
- * @param {*} nameConflicts
- * @param {*} namespaceName
- */
-function generateLocalNames(names, nameConflicts, namespaceName) {
-  const localNames = {};
-  names.forEach((name) => {
-    let localName;
-    if (!nameConflicts[name].has(name)) {
-      localName = name;
-    } else if (!nameConflicts[name].has(`${namespaceName}_${name}`)) {
-      localName = `${namespaceName}_${name}`;
-    } else {
-      for (let i = 1; i < Infinity; i++) {
-        if (!nameConflicts[name].has(`${namespaceName}_${name}_${i}`)) {
-          localName = `${namespaceName}_${name}_${i}`;
-          break;
-        }
-      }
-    }
-    localNames[name] = localName;
-  });
-  return localNames;
-}
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index cd680a1946..75952dd058 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -12,6 +12,15 @@ const containsPath = (filepath, target) => {
   return relative === '' || !relative.startsWith('..');
 };
 
+function isMatchingTargetPath(filename, targetPath) {
+  if (isGlob(targetPath)) {
+    const mm = new Minimatch(targetPath);
+    return mm.match(filename);
+  }
+
+  return containsPath(filename, targetPath);
+}
+
 module.exports = {
   meta: {
     type: 'problem',
@@ -83,15 +92,6 @@ module.exports = {
         .some((targetPath) => isMatchingTargetPath(currentFilename, targetPath)),
     );
 
-    function isMatchingTargetPath(filename, targetPath) {
-      if (isGlob(targetPath)) {
-        const mm = new Minimatch(targetPath);
-        return mm.match(filename);
-      }
-
-      return containsPath(filename, targetPath);
-    }
-
     function isValidExceptionPath(absoluteFromPath, absoluteExceptionPath) {
       const relativeExceptionPath = path.relative(absoluteFromPath, absoluteExceptionPath);
 
diff --git a/src/rules/order.js b/src/rules/order.js
index 44d25be63c..7071513bf3 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -92,6 +92,12 @@ function findRootNode(node) {
   return parent;
 }
 
+function commentOnSameLineAs(node) {
+  return (token) => (token.type === 'Block' ||  token.type === 'Line')
+      && token.loc.start.line === token.loc.end.line
+      && token.loc.end.line === node.loc.end.line;
+}
+
 function findEndOfLineWithComments(sourceCode, node) {
   const tokensToEndOfLine = takeTokensAfterWhile(sourceCode, node, commentOnSameLineAs(node));
   const endOfTokens = tokensToEndOfLine.length > 0
@@ -111,12 +117,6 @@ function findEndOfLineWithComments(sourceCode, node) {
   return result;
 }
 
-function commentOnSameLineAs(node) {
-  return (token) => (token.type === 'Block' ||  token.type === 'Line')
-      && token.loc.start.line === token.loc.end.line
-      && token.loc.end.line === node.loc.end.line;
-}
-
 function findStartOfLineWithComments(sourceCode, node) {
   const tokensToEndOfLine = takeTokensBeforeWhile(sourceCode, node, commentOnSameLineAs(node));
   const startOfTokens = tokensToEndOfLine.length > 0 ? tokensToEndOfLine[0].range[0] : node.range[0];
diff --git a/tests/src/package.js b/tests/src/package.js
index 08138084c6..c56bd1333d 100644
--- a/tests/src/package.js
+++ b/tests/src/package.js
@@ -45,6 +45,13 @@ describe('package', function () {
     });
   });
 
+  function getRulePath(ruleName) {
+    // 'require' does not work with dynamic paths because of the compilation step by babel
+    // (which resolves paths according to the root folder configuration)
+    // the usage of require.resolve on a static path gets around this
+    return path.resolve(require.resolve('rules/no-unresolved'), '..', ruleName);
+  }
+
   it('has configs only for rules that exist', function () {
     for (const configFile in module.configs) {
       const preamble = 'import/';
@@ -54,13 +61,6 @@ describe('package', function () {
           .not.to.throw(Error);
       }
     }
-
-    function getRulePath(ruleName) {
-      // 'require' does not work with dynamic paths because of the compilation step by babel
-      // (which resolves paths according to the root folder configuration)
-      // the usage of require.resolve on a static path gets around this
-      return path.resolve(require.resolve('rules/no-unresolved'), '..', ruleName);
-    }
   });
 
   it('marks deprecated rules in their metadata', function () {
diff --git a/tests/src/utils.js b/tests/src/utils.js
index d5215b02e3..24d5504a71 100644
--- a/tests/src/utils.js
+++ b/tests/src/utils.js
@@ -42,10 +42,6 @@ export function eslintVersionSatisfies(specifier) {
   return semver.satisfies(eslintPkg.version, specifier);
 }
 
-export function testVersion(specifier, t) {
-  return eslintVersionSatisfies(specifier) ? test(t()) : [];
-}
-
 export function test(t) {
   if (arguments.length !== 1) {
     throw new SyntaxError('`test` requires exactly one object argument');
@@ -61,6 +57,10 @@ export function test(t) {
   };
 }
 
+export function testVersion(specifier, t) {
+  return eslintVersionSatisfies(specifier) ? test(t()) : [];
+}
+
 export function testContext(settings) {
   return { getFilename() { return FILENAME; },
     settings: settings || {} };

From c77c1a6ace311f99ed25878768c2dbee49c0512a Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Wed, 13 Mar 2024 18:41:22 +0200
Subject: [PATCH 668/767] [eslint] ignore some warnings

---
 .eslintrc | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/.eslintrc b/.eslintrc
index 8dc0b2637a..224ffcb0e3 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -235,6 +235,16 @@
                 "no-use-before-define": "off",
             },
         },
+        {
+            "files": [
+                "resolvers/webpack/index.js",
+                "resolvers/webpack/test/example.js",
+                "utils/parse.js",
+            ],
+            "rules": {
+                "no-console": "off",
+            },
+        },
         {
             "files": [
                 "resolvers/*/test/**/*",

From 7a28ba23885dbb2bda98b5c6d7659134ea6d7777 Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Mon, 18 Mar 2024 21:11:25 +0200
Subject: [PATCH 669/767] [Refactor] `ExportMap`: separate ExportMap instance
 from its builder logic

---
 .eslintrc                                 |   2 +-
 CHANGELOG.md                              |   2 +
 src/exportMap.js                          | 178 ++++++++++++++++++++
 src/{ExportMap.js => exportMapBuilder.js} | 188 +---------------------
 src/rules/default.js                      |   4 +-
 src/rules/export.js                       |   4 +-
 src/rules/named.js                        |   6 +-
 src/rules/namespace.js                    |  11 +-
 src/rules/no-cycle.js                     |   4 +-
 src/rules/no-deprecated.js                |   7 +-
 src/rules/no-named-as-default-member.js   |   4 +-
 src/rules/no-named-as-default.js          |   4 +-
 src/rules/no-unused-modules.js            |   4 +-
 tests/src/core/getExports.js              |  60 +++----
 14 files changed, 242 insertions(+), 236 deletions(-)
 create mode 100644 src/exportMap.js
 rename src/{ExportMap.js => exportMapBuilder.js} (78%)

diff --git a/.eslintrc b/.eslintrc
index 224ffcb0e3..1bbbba0148 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -229,7 +229,7 @@
         {
             "files": [
                 "utils/**", // TODO
-                "src/ExportMap.js", // TODO
+                "src/exportMapBuilder.js", // TODO
             ],
             "rules": {
                 "no-use-before-define": "off",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9552774dce..7ad93fbd30 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
 - [`no-unused-modules`]: add console message to help debug [#2866]
 - [Refactor] `ExportMap`: make procedures static instead of monkeypatching exportmap ([#2982], thanks [@soryy708])
+- [Refactor] `ExportMap`: separate ExportMap instance from its builder logic ([#2985], thanks [@soryy708])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1109,6 +1110,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2985]: https://github.com/import-js/eslint-plugin-import/pull/2985
 [#2982]: https://github.com/import-js/eslint-plugin-import/pull/2982
 [#2944]: https://github.com/import-js/eslint-plugin-import/pull/2944
 [#2942]: https://github.com/import-js/eslint-plugin-import/pull/2942
diff --git a/src/exportMap.js b/src/exportMap.js
new file mode 100644
index 0000000000..e4d61638c5
--- /dev/null
+++ b/src/exportMap.js
@@ -0,0 +1,178 @@
+export default class ExportMap {
+  constructor(path) {
+    this.path = path;
+    this.namespace = new Map();
+    // todo: restructure to key on path, value is resolver + map of names
+    this.reexports = new Map();
+    /**
+     * star-exports
+     * @type {Set<() => ExportMap>}
+     */
+    this.dependencies = new Set();
+    /**
+     * dependencies of this module that are not explicitly re-exported
+     * @type {Map<string, () => ExportMap>}
+     */
+    this.imports = new Map();
+    this.errors = [];
+    /**
+     * type {'ambiguous' | 'Module' | 'Script'}
+     */
+    this.parseGoal = 'ambiguous';
+  }
+
+  get hasDefault() { return this.get('default') != null; } // stronger than this.has
+
+  get size() {
+    let size = this.namespace.size + this.reexports.size;
+    this.dependencies.forEach((dep) => {
+      const d = dep();
+      // CJS / ignored dependencies won't exist (#717)
+      if (d == null) { return; }
+      size += d.size;
+    });
+    return size;
+  }
+
+  /**
+   * Note that this does not check explicitly re-exported names for existence
+   * in the base namespace, but it will expand all `export * from '...'` exports
+   * if not found in the explicit namespace.
+   * @param  {string}  name
+   * @return {boolean} true if `name` is exported by this module.
+   */
+  has(name) {
+    if (this.namespace.has(name)) { return true; }
+    if (this.reexports.has(name)) { return true; }
+
+    // default exports must be explicitly re-exported (#328)
+    if (name !== 'default') {
+      for (const dep of this.dependencies) {
+        const innerMap = dep();
+
+        // todo: report as unresolved?
+        if (!innerMap) { continue; }
+
+        if (innerMap.has(name)) { return true; }
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * ensure that imported name fully resolves.
+   * @param  {string} name
+   * @return {{ found: boolean, path: ExportMap[] }}
+   */
+  hasDeep(name) {
+    if (this.namespace.has(name)) { return { found: true, path: [this] }; }
+
+    if (this.reexports.has(name)) {
+      const reexports = this.reexports.get(name);
+      const imported = reexports.getImport();
+
+      // if import is ignored, return explicit 'null'
+      if (imported == null) { return { found: true, path: [this] }; }
+
+      // safeguard against cycles, only if name matches
+      if (imported.path === this.path && reexports.local === name) {
+        return { found: false, path: [this] };
+      }
+
+      const deep = imported.hasDeep(reexports.local);
+      deep.path.unshift(this);
+
+      return deep;
+    }
+
+    // default exports must be explicitly re-exported (#328)
+    if (name !== 'default') {
+      for (const dep of this.dependencies) {
+        const innerMap = dep();
+        if (innerMap == null) { return { found: true, path: [this] }; }
+        // todo: report as unresolved?
+        if (!innerMap) { continue; }
+
+        // safeguard against cycles
+        if (innerMap.path === this.path) { continue; }
+
+        const innerValue = innerMap.hasDeep(name);
+        if (innerValue.found) {
+          innerValue.path.unshift(this);
+          return innerValue;
+        }
+      }
+    }
+
+    return { found: false, path: [this] };
+  }
+
+  get(name) {
+    if (this.namespace.has(name)) { return this.namespace.get(name); }
+
+    if (this.reexports.has(name)) {
+      const reexports = this.reexports.get(name);
+      const imported = reexports.getImport();
+
+      // if import is ignored, return explicit 'null'
+      if (imported == null) { return null; }
+
+      // safeguard against cycles, only if name matches
+      if (imported.path === this.path && reexports.local === name) { return undefined; }
+
+      return imported.get(reexports.local);
+    }
+
+    // default exports must be explicitly re-exported (#328)
+    if (name !== 'default') {
+      for (const dep of this.dependencies) {
+        const innerMap = dep();
+        // todo: report as unresolved?
+        if (!innerMap) { continue; }
+
+        // safeguard against cycles
+        if (innerMap.path === this.path) { continue; }
+
+        const innerValue = innerMap.get(name);
+        if (innerValue !== undefined) { return innerValue; }
+      }
+    }
+
+    return undefined;
+  }
+
+  forEach(callback, thisArg) {
+    this.namespace.forEach((v, n) => { callback.call(thisArg, v, n, this); });
+
+    this.reexports.forEach((reexports, name) => {
+      const reexported = reexports.getImport();
+      // can't look up meta for ignored re-exports (#348)
+      callback.call(thisArg, reexported && reexported.get(reexports.local), name, this);
+    });
+
+    this.dependencies.forEach((dep) => {
+      const d = dep();
+      // CJS / ignored dependencies won't exist (#717)
+      if (d == null) { return; }
+
+      d.forEach((v, n) => {
+        if (n !== 'default') {
+          callback.call(thisArg, v, n, this);
+        }
+      });
+    });
+  }
+
+  // todo: keys, values, entries?
+
+  reportErrors(context, declaration) {
+    const msg = this.errors
+      .map((e) => `${e.message} (${e.lineNumber}:${e.column})`)
+      .join(', ');
+    context.report({
+      node: declaration.source,
+      message: `Parse errors in imported module '${declaration.source.value}': ${msg}`,
+    });
+  }
+}
diff --git a/src/ExportMap.js b/src/exportMapBuilder.js
similarity index 78%
rename from src/ExportMap.js
rename to src/exportMapBuilder.js
index 9ee65a504f..f2b40e7b4c 100644
--- a/src/ExportMap.js
+++ b/src/exportMapBuilder.js
@@ -18,6 +18,7 @@ import * as unambiguous from 'eslint-module-utils/unambiguous';
 import { tsConfigLoader } from 'tsconfig-paths/lib/tsconfig-loader';
 
 import includes from 'array-includes';
+import ExportMap from './exportMap';
 
 let ts;
 
@@ -117,189 +118,12 @@ const availableDocStyleParsers = {
 
 const supportedImportTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
 
-export default class ExportMap {
-  constructor(path) {
-    this.path = path;
-    this.namespace = new Map();
-    // todo: restructure to key on path, value is resolver + map of names
-    this.reexports = new Map();
-    /**
-     * star-exports
-     * @type {Set} of () => ExportMap
-     */
-    this.dependencies = new Set();
-    /**
-     * dependencies of this module that are not explicitly re-exported
-     * @type {Map} from path = () => ExportMap
-     */
-    this.imports = new Map();
-    this.errors = [];
-    /**
-     * type {'ambiguous' | 'Module' | 'Script'}
-     */
-    this.parseGoal = 'ambiguous';
-  }
-
-  get hasDefault() { return this.get('default') != null; } // stronger than this.has
-
-  get size() {
-    let size = this.namespace.size + this.reexports.size;
-    this.dependencies.forEach((dep) => {
-      const d = dep();
-      // CJS / ignored dependencies won't exist (#717)
-      if (d == null) { return; }
-      size += d.size;
-    });
-    return size;
-  }
-
-  /**
-   * Note that this does not check explicitly re-exported names for existence
-   * in the base namespace, but it will expand all `export * from '...'` exports
-   * if not found in the explicit namespace.
-   * @param  {string}  name
-   * @return {Boolean} true if `name` is exported by this module.
-   */
-  has(name) {
-    if (this.namespace.has(name)) { return true; }
-    if (this.reexports.has(name)) { return true; }
-
-    // default exports must be explicitly re-exported (#328)
-    if (name !== 'default') {
-      for (const dep of this.dependencies) {
-        const innerMap = dep();
-
-        // todo: report as unresolved?
-        if (!innerMap) { continue; }
-
-        if (innerMap.has(name)) { return true; }
-      }
-    }
-
-    return false;
-  }
-
-  /**
-   * ensure that imported name fully resolves.
-   * @param  {string} name
-   * @return {{ found: boolean, path: ExportMap[] }}
-   */
-  hasDeep(name) {
-    if (this.namespace.has(name)) { return { found: true, path: [this] }; }
-
-    if (this.reexports.has(name)) {
-      const reexports = this.reexports.get(name);
-      const imported = reexports.getImport();
-
-      // if import is ignored, return explicit 'null'
-      if (imported == null) { return { found: true, path: [this] }; }
-
-      // safeguard against cycles, only if name matches
-      if (imported.path === this.path && reexports.local === name) {
-        return { found: false, path: [this] };
-      }
-
-      const deep = imported.hasDeep(reexports.local);
-      deep.path.unshift(this);
-
-      return deep;
-    }
-
-    // default exports must be explicitly re-exported (#328)
-    if (name !== 'default') {
-      for (const dep of this.dependencies) {
-        const innerMap = dep();
-        if (innerMap == null) { return { found: true, path: [this] }; }
-        // todo: report as unresolved?
-        if (!innerMap) { continue; }
-
-        // safeguard against cycles
-        if (innerMap.path === this.path) { continue; }
-
-        const innerValue = innerMap.hasDeep(name);
-        if (innerValue.found) {
-          innerValue.path.unshift(this);
-          return innerValue;
-        }
-      }
-    }
-
-    return { found: false, path: [this] };
-  }
-
-  get(name) {
-    if (this.namespace.has(name)) { return this.namespace.get(name); }
-
-    if (this.reexports.has(name)) {
-      const reexports = this.reexports.get(name);
-      const imported = reexports.getImport();
-
-      // if import is ignored, return explicit 'null'
-      if (imported == null) { return null; }
-
-      // safeguard against cycles, only if name matches
-      if (imported.path === this.path && reexports.local === name) { return undefined; }
-
-      return imported.get(reexports.local);
-    }
-
-    // default exports must be explicitly re-exported (#328)
-    if (name !== 'default') {
-      for (const dep of this.dependencies) {
-        const innerMap = dep();
-        // todo: report as unresolved?
-        if (!innerMap) { continue; }
-
-        // safeguard against cycles
-        if (innerMap.path === this.path) { continue; }
-
-        const innerValue = innerMap.get(name);
-        if (innerValue !== undefined) { return innerValue; }
-      }
-    }
-
-    return undefined;
-  }
-
-  forEach(callback, thisArg) {
-    this.namespace.forEach((v, n) => { callback.call(thisArg, v, n, this); });
-
-    this.reexports.forEach((reexports, name) => {
-      const reexported = reexports.getImport();
-      // can't look up meta for ignored re-exports (#348)
-      callback.call(thisArg, reexported && reexported.get(reexports.local), name, this);
-    });
-
-    this.dependencies.forEach((dep) => {
-      const d = dep();
-      // CJS / ignored dependencies won't exist (#717)
-      if (d == null) { return; }
-
-      d.forEach((v, n) => {
-        if (n !== 'default') {
-          callback.call(thisArg, v, n, this);
-        }
-      });
-    });
-  }
-
-  // todo: keys, values, entries?
-
-  reportErrors(context, declaration) {
-    const msg = this.errors
-      .map((e) => `${e.message} (${e.lineNumber}:${e.column})`)
-      .join(', ');
-    context.report({
-      node: declaration.source,
-      message: `Parse errors in imported module '${declaration.source.value}': ${msg}`,
-    });
-  }
-
+export default class ExportMapBuilder {
   static get(source, context) {
     const path = resolve(source, context);
     if (path == null) { return null; }
 
-    return ExportMap.for(childContext(path, context));
+    return ExportMapBuilder.for(childContext(path, context));
   }
 
   static for(context) {
@@ -343,7 +167,7 @@ export default class ExportMap {
     }
 
     log('cache miss', cacheKey, 'for path', path);
-    exportMap = ExportMap.parse(path, content, context);
+    exportMap = ExportMapBuilder.parse(path, content, context);
 
     // ambiguous modules return null
     if (exportMap == null) {
@@ -447,7 +271,7 @@ export default class ExportMap {
     function resolveImport(value) {
       const rp = remotePath(value);
       if (rp == null) { return null; }
-      return ExportMap.for(childContext(rp, context));
+      return ExportMapBuilder.for(childContext(rp, context));
     }
 
     function getNamespace(identifier) {
@@ -738,7 +562,7 @@ export default class ExportMap {
  * caused memory leaks. See #1266.
  */
 function thunkFor(p, context) {
-  return () => ExportMap.for(childContext(p, context));
+  return () => ExportMapBuilder.for(childContext(p, context));
 }
 
 /**
diff --git a/src/rules/default.js b/src/rules/default.js
index 297a80c463..cbaa49f1fc 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -1,4 +1,4 @@
-import Exports from '../ExportMap';
+import ExportMapBuilder from '../exportMapBuilder';
 import docsUrl from '../docsUrl';
 
 module.exports = {
@@ -19,7 +19,7 @@ module.exports = {
       );
 
       if (!defaultSpecifier) { return; }
-      const imports = Exports.get(node.source.value, context);
+      const imports = ExportMapBuilder.get(node.source.value, context);
       if (imports == null) { return; }
 
       if (imports.errors.length) {
diff --git a/src/rules/export.js b/src/rules/export.js
index c540f1e3c9..b1dc5ca9ea 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -1,4 +1,4 @@
-import ExportMap, { recursivePatternCapture } from '../ExportMap';
+import ExportMapBuilder, { recursivePatternCapture } from '../exportMapBuilder';
 import docsUrl from '../docsUrl';
 import includes from 'array-includes';
 import flatMap from 'array.prototype.flatmap';
@@ -197,7 +197,7 @@ module.exports = {
         // `export * as X from 'path'` does not conflict
         if (node.exported && node.exported.name) { return; }
 
-        const remoteExports = ExportMap.get(node.source.value, context);
+        const remoteExports = ExportMapBuilder.get(node.source.value, context);
         if (remoteExports == null) { return; }
 
         if (remoteExports.errors.length) {
diff --git a/src/rules/named.js b/src/rules/named.js
index e7fe4e4dce..043d72eabe 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -1,5 +1,5 @@
 import * as path from 'path';
-import Exports from '../ExportMap';
+import ExportMapBuilder from '../exportMapBuilder';
 import docsUrl from '../docsUrl';
 
 module.exports = {
@@ -41,7 +41,7 @@ module.exports = {
         return; // no named imports/exports
       }
 
-      const imports = Exports.get(node.source.value, context);
+      const imports = ExportMapBuilder.get(node.source.value, context);
       if (imports == null || imports.parseGoal === 'ambiguous') {
         return;
       }
@@ -93,7 +93,7 @@ module.exports = {
       const call = node.init;
       const [source] = call.arguments;
       const variableImports = node.id.properties;
-      const variableExports = Exports.get(source.value, context);
+      const variableExports = ExportMapBuilder.get(source.value, context);
 
       if (
         // return if it's not a commonjs require statement
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 77a3ea9077..e1ca2870b1 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -1,5 +1,6 @@
 import declaredScope from 'eslint-module-utils/declaredScope';
-import Exports from '../ExportMap';
+import ExportMapBuilder from '../exportMapBuilder';
+import ExportMap from '../exportMap';
 import importDeclaration from '../importDeclaration';
 import docsUrl from '../docsUrl';
 
@@ -8,7 +9,7 @@ function processBodyStatement(context, namespaces, declaration) {
 
   if (declaration.specifiers.length === 0) { return; }
 
-  const imports = Exports.get(declaration.source.value, context);
+  const imports = ExportMapBuilder.get(declaration.source.value, context);
   if (imports == null) { return null; }
 
   if (imports.errors.length > 0) {
@@ -88,7 +89,7 @@ module.exports = {
       ExportNamespaceSpecifier(namespace) {
         const declaration = importDeclaration(context);
 
-        const imports = Exports.get(declaration.source.value, context);
+        const imports = ExportMapBuilder.get(declaration.source.value, context);
         if (imports == null) { return null; }
 
         if (imports.errors.length) {
@@ -122,7 +123,7 @@ module.exports = {
         let namespace = namespaces.get(dereference.object.name);
         const namepath = [dereference.object.name];
         // while property is namespace and parent is member expression, keep validating
-        while (namespace instanceof Exports && dereference.type === 'MemberExpression') {
+        while (namespace instanceof ExportMap && dereference.type === 'MemberExpression') {
           if (dereference.computed) {
             if (!allowComputed) {
               context.report(
@@ -161,7 +162,7 @@ module.exports = {
 
         // DFS traverse child namespaces
         function testKey(pattern, namespace, path = [init.name]) {
-          if (!(namespace instanceof Exports)) { return; }
+          if (!(namespace instanceof ExportMap)) { return; }
 
           if (pattern.type !== 'ObjectPattern') { return; }
 
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index 11c2f44fc0..b7b907b062 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -4,7 +4,7 @@
  */
 
 import resolve from 'eslint-module-utils/resolve';
-import Exports from '../ExportMap';
+import ExportMapBuilder from '../exportMapBuilder';
 import { isExternalModule } from '../core/importType';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
@@ -88,7 +88,7 @@ module.exports = {
         return; // ignore type imports
       }
 
-      const imported = Exports.get(sourceNode.value, context);
+      const imported = ExportMapBuilder.get(sourceNode.value, context);
 
       if (imported == null) {
         return;  // no-unresolved territory
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index 06eeff8ea7..50072f3f85 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -1,5 +1,6 @@
 import declaredScope from 'eslint-module-utils/declaredScope';
-import Exports from '../ExportMap';
+import ExportMapBuilder from '../exportMapBuilder';
+import ExportMap from '../exportMap';
 import docsUrl from '../docsUrl';
 
 function message(deprecation) {
@@ -31,7 +32,7 @@ module.exports = {
       if (node.type !== 'ImportDeclaration') { return; }
       if (node.source == null) { return; } // local export, ignore
 
-      const imports = Exports.get(node.source.value, context);
+      const imports = ExportMapBuilder.get(node.source.value, context);
       if (imports == null) { return; }
 
       const moduleDeprecation = imports.doc && imports.doc.tags.find((t) => t.title === 'deprecated');
@@ -114,7 +115,7 @@ module.exports = {
         let namespace = namespaces.get(dereference.object.name);
         const namepath = [dereference.object.name];
         // while property is namespace and parent is member expression, keep validating
-        while (namespace instanceof Exports && dereference.type === 'MemberExpression') {
+        while (namespace instanceof ExportMap && dereference.type === 'MemberExpression') {
           // ignore computed parts for now
           if (dereference.computed) { return; }
 
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index e00a4cbc87..d594c58433 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -4,7 +4,7 @@
  * @copyright 2016 Desmond Brand. All rights reserved.
  * See LICENSE in root directory for full license.
  */
-import Exports from '../ExportMap';
+import ExportMapBuilder from '../exportMapBuilder';
 import importDeclaration from '../importDeclaration';
 import docsUrl from '../docsUrl';
 
@@ -36,7 +36,7 @@ module.exports = {
     return {
       ImportDefaultSpecifier(node) {
         const declaration = importDeclaration(context);
-        const exportMap = Exports.get(declaration.source.value, context);
+        const exportMap = ExportMapBuilder.get(declaration.source.value, context);
         if (exportMap == null) { return; }
 
         if (exportMap.errors.length) {
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index 40b1e175b2..3e73ff2f44 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -1,4 +1,4 @@
-import Exports from '../ExportMap';
+import ExportMapBuilder from '../exportMapBuilder';
 import importDeclaration from '../importDeclaration';
 import docsUrl from '../docsUrl';
 
@@ -20,7 +20,7 @@ module.exports = {
 
       const declaration = importDeclaration(context);
 
-      const imports = Exports.get(declaration.source.value, context);
+      const imports = ExportMapBuilder.get(declaration.source.value, context);
       if (imports == null) { return; }
 
       if (imports.errors.length) {
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index ec3425dacd..812efffbca 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -13,7 +13,7 @@ import values from 'object.values';
 import includes from 'array-includes';
 import flatMap from 'array.prototype.flatmap';
 
-import Exports, { recursivePatternCapture } from '../ExportMap';
+import ExportMapBuilder, { recursivePatternCapture } from '../exportMapBuilder';
 import docsUrl from '../docsUrl';
 
 let FileEnumerator;
@@ -194,7 +194,7 @@ const prepareImportsAndExports = (srcFiles, context) => {
   srcFiles.forEach((file) => {
     const exports = new Map();
     const imports = new Map();
-    const currentExports = Exports.get(file, context);
+    const currentExports = ExportMapBuilder.get(file, context);
     if (currentExports) {
       const {
         dependencies,
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 1dd6e88014..611a13055f 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -4,7 +4,7 @@ import sinon from 'sinon';
 import eslintPkg from 'eslint/package.json';
 import typescriptPkg from 'typescript/package.json';
 import * as tsConfigLoader from 'tsconfig-paths/lib/tsconfig-loader';
-import ExportMap from '../../../src/ExportMap';
+import ExportMapBuilder from '../../../src/exportMapBuilder';
 
 import * as fs from 'fs';
 
@@ -28,7 +28,7 @@ describe('ExportMap', function () {
   it('handles ExportAllDeclaration', function () {
     let imports;
     expect(function () {
-      imports = ExportMap.get('./export-all', fakeContext);
+      imports = ExportMapBuilder.get('./export-all', fakeContext);
     }).not.to.throw(Error);
 
     expect(imports).to.exist;
@@ -37,25 +37,25 @@ describe('ExportMap', function () {
   });
 
   it('returns a cached copy on subsequent requests', function () {
-    expect(ExportMap.get('./named-exports', fakeContext))
-      .to.exist.and.equal(ExportMap.get('./named-exports', fakeContext));
+    expect(ExportMapBuilder.get('./named-exports', fakeContext))
+      .to.exist.and.equal(ExportMapBuilder.get('./named-exports', fakeContext));
   });
 
   it('does not return a cached copy after modification', (done) => {
-    const firstAccess = ExportMap.get('./mutator', fakeContext);
+    const firstAccess = ExportMapBuilder.get('./mutator', fakeContext);
     expect(firstAccess).to.exist;
 
     // mutate (update modified time)
     const newDate = new Date();
     fs.utimes(getFilename('mutator.js'), newDate, newDate, (error) => {
       expect(error).not.to.exist;
-      expect(ExportMap.get('./mutator', fakeContext)).not.to.equal(firstAccess);
+      expect(ExportMapBuilder.get('./mutator', fakeContext)).not.to.equal(firstAccess);
       done();
     });
   });
 
   it('does not return a cached copy with different settings', () => {
-    const firstAccess = ExportMap.get('./named-exports', fakeContext);
+    const firstAccess = ExportMapBuilder.get('./named-exports', fakeContext);
     expect(firstAccess).to.exist;
 
     const differentSettings = {
@@ -63,7 +63,7 @@ describe('ExportMap', function () {
       parserPath: 'espree',
     };
 
-    expect(ExportMap.get('./named-exports', differentSettings))
+    expect(ExportMapBuilder.get('./named-exports', differentSettings))
       .to.exist.and
       .not.to.equal(firstAccess);
   });
@@ -71,7 +71,7 @@ describe('ExportMap', function () {
   it('does not throw for a missing file', function () {
     let imports;
     expect(function () {
-      imports = ExportMap.get('./does-not-exist', fakeContext);
+      imports = ExportMapBuilder.get('./does-not-exist', fakeContext);
     }).not.to.throw(Error);
 
     expect(imports).not.to.exist;
@@ -81,7 +81,7 @@ describe('ExportMap', function () {
   it('exports explicit names for a missing file in exports', function () {
     let imports;
     expect(function () {
-      imports = ExportMap.get('./exports-missing', fakeContext);
+      imports = ExportMapBuilder.get('./exports-missing', fakeContext);
     }).not.to.throw(Error);
 
     expect(imports).to.exist;
@@ -92,7 +92,7 @@ describe('ExportMap', function () {
   it('finds exports for an ES7 module with babel-eslint', function () {
     const path = getFilename('jsx/FooES7.js');
     const contents = fs.readFileSync(path, { encoding: 'utf8' });
-    const imports = ExportMap.parse(
+    const imports = ExportMapBuilder.parse(
       path,
       contents,
       { parserPath: 'babel-eslint', settings: {} },
@@ -112,7 +112,7 @@ describe('ExportMap', function () {
         before('parse file', function () {
           const path = getFilename('deprecated.js');
           const contents = fs.readFileSync(path, { encoding: 'utf8' }).replace(/[\r]\n/g, lineEnding);
-          imports = ExportMap.parse(path, contents, parseContext);
+          imports = ExportMapBuilder.parse(path, contents, parseContext);
 
           // sanity checks
           expect(imports.errors).to.be.empty;
@@ -181,7 +181,7 @@ describe('ExportMap', function () {
         before('parse file', function () {
           const path = getFilename('deprecated-file.js');
           const contents = fs.readFileSync(path, { encoding: 'utf8' });
-          imports = ExportMap.parse(path, contents, parseContext);
+          imports = ExportMapBuilder.parse(path, contents, parseContext);
 
           // sanity checks
           expect(imports.errors).to.be.empty;
@@ -243,7 +243,7 @@ describe('ExportMap', function () {
     it('works with espree & traditional namespace exports', function () {
       const path = getFilename('deep/a.js');
       const contents = fs.readFileSync(path, { encoding: 'utf8' });
-      const a = ExportMap.parse(path, contents, espreeContext);
+      const a = ExportMapBuilder.parse(path, contents, espreeContext);
       expect(a.errors).to.be.empty;
       expect(a.get('b').namespace).to.exist;
       expect(a.get('b').namespace.has('c')).to.be.true;
@@ -252,7 +252,7 @@ describe('ExportMap', function () {
     it('captures namespace exported as default', function () {
       const path = getFilename('deep/default.js');
       const contents = fs.readFileSync(path, { encoding: 'utf8' });
-      const def = ExportMap.parse(path, contents, espreeContext);
+      const def = ExportMapBuilder.parse(path, contents, espreeContext);
       expect(def.errors).to.be.empty;
       expect(def.get('default').namespace).to.exist;
       expect(def.get('default').namespace.has('c')).to.be.true;
@@ -261,7 +261,7 @@ describe('ExportMap', function () {
     it('works with babel-eslint & ES7 namespace exports', function () {
       const path = getFilename('deep-es7/a.js');
       const contents = fs.readFileSync(path, { encoding: 'utf8' });
-      const a = ExportMap.parse(path, contents, babelContext);
+      const a = ExportMapBuilder.parse(path, contents, babelContext);
       expect(a.errors).to.be.empty;
       expect(a.get('b').namespace).to.exist;
       expect(a.get('b').namespace.has('c')).to.be.true;
@@ -278,7 +278,7 @@ describe('ExportMap', function () {
 
       const path = getFilename('deep/cache-1.js');
       const contents = fs.readFileSync(path, { encoding: 'utf8' });
-      a = ExportMap.parse(path, contents, espreeContext);
+      a = ExportMapBuilder.parse(path, contents, espreeContext);
       expect(a.errors).to.be.empty;
 
       expect(a.get('b').namespace).to.exist;
@@ -304,10 +304,10 @@ describe('ExportMap', function () {
   context('Map API', function () {
     context('#size', function () {
 
-      it('counts the names', () => expect(ExportMap.get('./named-exports', fakeContext))
+      it('counts the names', () => expect(ExportMapBuilder.get('./named-exports', fakeContext))
         .to.have.property('size', 12));
 
-      it('includes exported namespace size', () => expect(ExportMap.get('./export-all', fakeContext))
+      it('includes exported namespace size', () => expect(ExportMapBuilder.get('./export-all', fakeContext))
         .to.have.property('size', 1));
 
     });
@@ -315,14 +315,14 @@ describe('ExportMap', function () {
 
   context('issue #210: self-reference', function () {
     it(`doesn't crash`, function () {
-      expect(() => ExportMap.get('./narcissist', fakeContext)).not.to.throw(Error);
+      expect(() => ExportMapBuilder.get('./narcissist', fakeContext)).not.to.throw(Error);
     });
     it(`'has' circular reference`, function () {
-      expect(ExportMap.get('./narcissist', fakeContext))
+      expect(ExportMapBuilder.get('./narcissist', fakeContext))
         .to.exist.and.satisfy((m) => m.has('soGreat'));
     });
     it(`can 'get' circular reference`, function () {
-      expect(ExportMap.get('./narcissist', fakeContext))
+      expect(ExportMapBuilder.get('./narcissist', fakeContext))
         .to.exist.and.satisfy((m) => m.get('soGreat') != null);
     });
   });
@@ -335,7 +335,7 @@ describe('ExportMap', function () {
 
     let imports;
     before('load imports', function () {
-      imports = ExportMap.get('./typescript.ts', context);
+      imports = ExportMapBuilder.get('./typescript.ts', context);
     });
 
     it('returns nothing for a TypeScript file', function () {
@@ -372,7 +372,7 @@ describe('ExportMap', function () {
         before('load imports', function () {
           this.timeout(20e3);  // takes a long time :shrug:
           sinon.spy(tsConfigLoader, 'tsConfigLoader');
-          imports = ExportMap.get('./typescript.ts', context);
+          imports = ExportMapBuilder.get('./typescript.ts', context);
         });
         after('clear spies', function () {
           tsConfigLoader.tsConfigLoader.restore();
@@ -414,9 +414,9 @@ describe('ExportMap', function () {
             },
           };
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(0);
-          ExportMap.parse('./baz.ts', 'export const baz = 5', customContext);
+          ExportMapBuilder.parse('./baz.ts', 'export const baz = 5', customContext);
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(1);
-          ExportMap.parse('./baz.ts', 'export const baz = 5', customContext);
+          ExportMapBuilder.parse('./baz.ts', 'export const baz = 5', customContext);
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(1);
 
           const differentContext = {
@@ -426,17 +426,17 @@ describe('ExportMap', function () {
             },
           };
 
-          ExportMap.parse('./baz.ts', 'export const baz = 5', differentContext);
+          ExportMapBuilder.parse('./baz.ts', 'export const baz = 5', differentContext);
           expect(tsConfigLoader.tsConfigLoader.callCount).to.equal(2);
         });
 
         it('should cache after parsing for an ambiguous module', function () {
           const source = './typescript-declare-module.ts';
-          const parseSpy = sinon.spy(ExportMap, 'parse');
+          const parseSpy = sinon.spy(ExportMapBuilder, 'parse');
 
-          expect(ExportMap.get(source, context)).to.be.null;
+          expect(ExportMapBuilder.get(source, context)).to.be.null;
 
-          ExportMap.get(source, context);
+          ExportMapBuilder.get(source, context);
 
           expect(parseSpy.callCount).to.equal(1);
 

From f3e505bc2bc87f28aa10267aed8172f08c7d9c9a Mon Sep 17 00:00:00 2001
From: minervabot <53988640+minervabot@users.noreply.github.com>
Date: Mon, 2 Jan 2023 02:28:07 -0700
Subject: [PATCH 670/767] [Docs] `order`: Add a quick note on how unbound
 imports and --fix

Having unbound imports mixed among the bound ones causes unexpected and incorrect seeming results. I spent several hours trying to fix this problem only to find it was well known!
---
 CHANGELOG.md        |  3 +++
 docs/rules/order.md | 19 +++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7ad93fbd30..77c908dc33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-unused-modules`]: add console message to help debug [#2866]
 - [Refactor] `ExportMap`: make procedures static instead of monkeypatching exportmap ([#2982], thanks [@soryy708])
 - [Refactor] `ExportMap`: separate ExportMap instance from its builder logic ([#2985], thanks [@soryy708])
+- [Docs] `order`: Add a quick note on how unbound imports and --fix ([#2640], thanks [@minervabot])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1130,6 +1131,7 @@ for info on changes for earlier releases.
 [#2735]: https://github.com/import-js/eslint-plugin-import/pull/2735
 [#2699]: https://github.com/import-js/eslint-plugin-import/pull/2699
 [#2664]: https://github.com/import-js/eslint-plugin-import/pull/2664
+[#2640]: https://github.com/import-js/eslint-plugin-import/pull/2640
 [#2613]: https://github.com/import-js/eslint-plugin-import/pull/2613
 [#2608]: https://github.com/import-js/eslint-plugin-import/pull/2608
 [#2605]: https://github.com/import-js/eslint-plugin-import/pull/2605
@@ -1846,6 +1848,7 @@ for info on changes for earlier releases.
 [@mgwalker]: https://github.com/mgwalker
 [@mhmadhamster]: https://github.com/MhMadHamster
 [@MikeyBeLike]: https://github.com/MikeyBeLike
+[@minervabot]: https://github.com/minervabot
 [@mpint]: https://github.com/mpint
 [@mplewis]: https://github.com/mplewis
 [@mrmckeb]: https://github.com/mrmckeb
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 2335699e6c..24692f2d21 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -77,6 +77,25 @@ import foo from './foo';
 var path = require('path');
 ```
 
+## Limitations of `--fix`
+
+Unbound imports are assumed to have side effects, and will never be moved/reordered. This can cause other imports to get "stuck" around them, and the fix to fail.
+
+```javascript
+import b from 'b'
+import 'format.css';  // This will prevent --fix from working.
+import a from 'a'
+```
+
+As a workaround, move unbound imports to be entirely above or below bound ones.
+
+```javascript
+import 'format1.css';  // OK
+import b from 'b'
+import a from 'a'
+import 'format2.css';  // OK
+```
+
 ## Options
 
 This rule supports the following options:

From fa60e3d738078fa2fccbc36260b9da534795f720 Mon Sep 17 00:00:00 2001
From: Joey Guerra <github@joeyguerra.com>
Date: Tue, 19 Mar 2024 17:33:40 -0500
Subject: [PATCH 671/767] [Tests] appveyor -> GHA (run tests on Windows in both
 pwsh and WSL + Ubuntu)

---
 .github/workflows/native-wsl.yml | 151 ++++++++++++++++++++++++++++
 CHANGELOG.md                     |   3 +
 appveyor.yml                     | 165 -------------------------------
 3 files changed, 154 insertions(+), 165 deletions(-)
 create mode 100644 .github/workflows/native-wsl.yml
 delete mode 100644 appveyor.yml

diff --git a/.github/workflows/native-wsl.yml b/.github/workflows/native-wsl.yml
new file mode 100644
index 0000000000..893d2248d1
--- /dev/null
+++ b/.github/workflows/native-wsl.yml
@@ -0,0 +1,151 @@
+name: Native and WSL
+
+on: [push, pull_request]
+
+jobs:
+  build:
+    runs-on: ${{ matrix.os }}
+    defaults:
+        run:
+          shell: ${{ matrix.configuration == 'wsl' && 'wsl-bash {0}' || 'pwsh' }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [windows-2019]
+        node-version: [18, 16, 14, 12, 10, 8, 6, 4]
+        configuration: [wsl, native]
+
+    steps:
+    - uses: actions/checkout@v4
+    - uses: Vampire/setup-wsl@v3
+      if: matrix.configuration == 'wsl'
+      with:
+        distribution: Ubuntu-22.04
+    - run: curl --version
+    - name: 'WSL: do all npm install steps'
+      if: matrix.configuration == 'wsl'
+      env:
+        ESLINT_VERSION: 7
+        TRAVIS_NODE_VERSION: ${{ matrix.node-version }}
+      run: |
+        curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
+        export NVM_DIR="$HOME/.nvm"
+        [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
+        nvm install --latest-npm ${{ matrix.node-version }}
+
+        if [ ${{ matrix.node-version }} -ge 4 ] && [ ${{ matrix.node-version }} -lt 6 ]; then
+          npm install eslint@4 --no-save --ignore-scripts
+          npm install
+          npm install eslint-import-resolver-typescript@1.0.2 --no-save
+          npm uninstall @angular-eslint/template-parser @typescript-eslint/parser --no-save
+        fi
+        if [ ${{ matrix.node-version }} -ge 6 ] && [ ${{ matrix.node-version }} -lt 7 ]; then
+          npm install eslint@5 --no-save --ignore-scripts
+          npm install
+          npm uninstall @angular-eslint/template-parser --no-save
+          npm install eslint-import-resolver-typescript@1.0.2 @typescript-eslint/parser@3 --no-save
+        fi
+        if [ ${{ matrix.node-version }} -ge 7 ] && [ ${{ matrix.node-version }} -lt 8 ]; then
+          npm install eslint@6 --no-save --ignore-scripts
+          npm install
+          npm install eslint-import-resolver-typescript@1.0.2 typescript-eslint-parser@20 --no-save
+          npm uninstall @angular-eslint/template-parser --no-save
+        fi
+        if [ ${{ matrix.node-version }} -eq 8 ]; then
+          npm install eslint@6 --no-save --ignore-scripts
+          npm install
+          npm uninstall @angular-eslint/template-parser --no-save
+          npm install @typescript-eslint/parser@3 --no-save
+        fi
+        if [ ${{ matrix.node-version }} -gt 8 ] && [ ${{ matrix.node-version }} -lt 10 ]; then
+          npm install eslint@7 --no-save --ignore-scripts
+          npm install
+          npm install @typescript-eslint/parser@3 --no-save
+        fi
+        if [ ${{ matrix.node-version }} -ge 10 ] && [ ${{ matrix.node-version }} -lt 12 ]; then
+          npm install
+          npm install @typescript-eslint/parser@4 --no-save
+        fi
+        if [ ${{ matrix.node-version }} -ge 12 ]; then
+          npm install
+        fi
+        npm run copy-metafiles
+        npm run pretest
+        npm run tests-only
+
+    - name: install dependencies for node <= 10
+      if: matrix.node-version <= '10' && matrix.configuration == 'native'
+      run: |
+        npm install --legacy-peer-deps
+        npm install eslint@7 --no-save
+
+    - name: Install dependencies for node > 10
+      if: matrix.node-version > '10'  && matrix.configuration == 'native'
+      run: npm install
+
+    - name: install the latest version of nyc
+      if: matrix.configuration == 'native'
+      run: npm install nyc@latest --no-save
+
+    - name: copy metafiles for node <= 8
+      if: matrix.node-version <= 8 && matrix.configuration == 'native'
+      env:
+        ESLINT_VERSION: 6
+        TRAVIS_NODE_VERSION: ${{ matrix.node-version }}
+      run: |
+        npm run copy-metafiles
+        bash ./tests/dep-time-travel.sh 2>&1
+    - name: copy metafiles for Node > 8
+      if: matrix.node-version > 8 && matrix.configuration == 'native'
+      env:
+        ESLINT_VERSION: 7
+        TRAVIS_NODE_VERSION: ${{ matrix.node-version }}
+      run: |
+        npm run copy-metafiles
+        bash ./tests/dep-time-travel.sh 2>&1
+
+    - name: install ./resolver dependencies in Native
+      if: matrix.configuration == 'native'
+      shell: pwsh
+      run: |
+        npm config set package-lock false
+        $resolverDir = "./resolvers"
+        Get-ChildItem -Directory $resolverDir |
+          ForEach {
+            Write-output $(Resolve-Path $(Join-Path $resolverDir  $_.Name))
+            Push-Location $(Resolve-Path $(Join-Path $resolverDir  $_.Name))
+              npm install
+              npm ls nyc > $null;
+              if ($?) {
+                npm install nyc@latest --no-save
+              }
+              Pop-Location
+            }
+
+    - name: run tests in Native
+      if: matrix.configuration == 'native'
+      shell: pwsh
+      run: |
+        npm run pretest
+        npm run tests-only
+        $resolverDir = "./resolvers";
+        $resolvers = @();
+        Get-ChildItem -Directory $resolverDir |
+          ForEach {
+            $resolvers += "$(Resolve-Path $(Join-Path $resolverDir $_.Name))";
+          }
+        $env:RESOLVERS = [string]::Join(";", $resolvers);
+        foreach ($resolver in $resolvers) {
+            Set-Location -Path $resolver.Trim('"')
+            npm run tests-only
+            Set-Location -Path $PSScriptRoot
+        }
+
+    - name: codecov
+      uses: codecov/codecov-action@v3.1.5
+
+  windows:
+    runs-on: ubuntu-latest
+    needs: [build]
+    steps:
+      - run: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77c908dc33..f8a6f80d0e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Refactor] `ExportMap`: make procedures static instead of monkeypatching exportmap ([#2982], thanks [@soryy708])
 - [Refactor] `ExportMap`: separate ExportMap instance from its builder logic ([#2985], thanks [@soryy708])
 - [Docs] `order`: Add a quick note on how unbound imports and --fix ([#2640], thanks [@minervabot])
+- [Tests] appveyor -> GHA (run tests on Windows in both pwsh and WSL + Ubuntu) ([#2987], thanks [@joeyguerra])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1111,6 +1112,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2987]: https://github.com/import-js/eslint-plugin-import/pull/2987
 [#2985]: https://github.com/import-js/eslint-plugin-import/pull/2985
 [#2982]: https://github.com/import-js/eslint-plugin-import/pull/2982
 [#2944]: https://github.com/import-js/eslint-plugin-import/pull/2944
@@ -1791,6 +1793,7 @@ for info on changes for earlier releases.
 [@jkimbo]: https://github.com/jkimbo
 [@joaovieira]: https://github.com/joaovieira
 [@joe-matsec]: https://github.com/joe-matsec
+[@joeyguerra]: https://github.com/joeyguerra
 [@johndevedu]: https://github.com/johndevedu
 [@johnthagen]: https://github.com/johnthagen
 [@jonboiser]: https://github.com/jonboiser
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index e50ab87d2a..0000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,165 +0,0 @@
-configuration:
-  - Native
-  - WSL
-
-# Test against this version of Node.js
-environment:
-  matrix:
-    - nodejs_version: "16"
-    - nodejs_version: "14"
-    - nodejs_version: "12"
-    - nodejs_version: "10"
-    - nodejs_version: "8"
-    # - nodejs_version: "6"
-    # - nodejs_version: "4"
-
-image: Visual Studio 2019
-matrix:
-  fast_finish: false
-  exclude:
-    - configuration: WSL
-      nodejs_version: "8"
-    - configuration: WSL
-      nodejs_version: "6"
-    - configuration: WSL
-      nodejs_version: "4"
-
-  allow_failures:
-    - nodejs_version: "4" # for eslint 5
-    - configuration: WSL
-
-platform:
-  - x86
-  - x64
-
-# Initialization scripts. (runs before repo cloning)
-init:
-  # Declare version-numbers of packages to install
-  - ps: >-
-      if ($env:nodejs_version -eq "4") {
-        $env:NPM_VERSION="3"
-      }
-      if ($env:nodejs_version -in @("8")) {
-        $env:NPM_VERSION="6"
-      }
-      if ($env:nodejs_version -in @("10", "12", "14", "16")) {
-        $env:NPM_VERSION="6" # TODO: use npm 7
-        $env:NPM_CONFIG_LEGACY_PEER_DEPS="true"
-      }
-  - ps: >-
-      $env:ESLINT_VERSION="7";
-      if ([int]$env:nodejs_version -le 8) {
-        $env:ESLINT_VERSION="6"
-      }
-      if ([int]$env:nodejs_version -le 7) {
-        $env:ESLINT_VERSION="5"
-      }
-      if ([int]$env:nodejs_version -le 6) {
-        $env:ESLINT_VERSION="4"
-      }
-  - ps: $env:WINDOWS_NYC_VERSION = "15.0.1"
-  - ps: $env:TRAVIS_NODE_VERSION = $env:nodejs_version
-
-  # Add `ci`-command to `PATH` for running commands either using cmd or wsl depending on the configuration
-  - ps: $env:PATH += ";$(Join-Path $(pwd) "scripts")"
-
-# Install scripts. (runs after repo cloning)
-before_build:
-  # Install propert `npm`-version
-  - IF DEFINED NPM_VERSION ci sudo npm install -g npm@%NPM_VERSION%
-
-  # Install dependencies
-  - ci npm install
-  - ci npm run copy-metafiles
-  - bash ./tests/dep-time-travel.sh 2>&1
-
-  # fix symlinks
-  - git config core.symlinks true
-  - git reset --hard
-  - ci git reset --hard
-
-  # Install dependencies of resolvers
-  - ps: >-
-      $resolverDir = "./resolvers";
-      $resolvers = @();
-      Get-ChildItem -Directory $resolverDir |
-        ForEach {
-          $resolvers += "$(Resolve-Path $(Join-Path $resolverDir $_))";
-        }
-      $env:RESOLVERS = [string]::Join(";", $resolvers);
-  - FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm install & popd )
-
-  # Install proper `eslint`-version
-  - IF DEFINED ESLINT_VERSION ci npm install --no-save eslint@%ESLINT_VERSION%
-
-# Build scripts (project isn't actually built)
-build_script:
-  - ps: "# This Project isn't actually built"
-
-# Test scripts
-test_script:
-  # Output useful info for debugging.
-  - ci node --version
-  - ci npm --version
-
-  # Run core tests
-  - ci npm run pretest
-  - ci npm run tests-only
-
-  # Run resolver tests
-  - ps: >-
-      $resolverDir = "./resolvers";
-      $resolvers = @();
-      Get-ChildItem -Directory $resolverDir |
-        ForEach {
-          $resolvers += "$(Resolve-Path $(Join-Path $resolverDir $_))";
-        }
-      $env:RESOLVERS = [string]::Join(";", $resolvers);
-  - FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm test & popd )
-
-# Configuration-specific steps
-for:
-  - matrix:
-      except:
-        - configuration: WSL
-    install:
-      # Get the latest stable version of Node.js or io.js
-      - ps: Install-Product node $env:nodejs_version
-    before_test:
-      # Upgrade nyc
-      - ci npm i --no-save nyc@%WINDOWS_NYC_VERSION%
-      - ps: >-
-          $resolverDir = "./resolvers";
-          $resolvers = @();
-          Get-ChildItem -Directory $resolverDir |
-            ForEach {
-              Push-Location $(Resolve-Path $(Join-Path $resolverDir $_));
-              ci npm ls nyc > $null;
-              if ($?) {
-                $resolvers += "$(pwd)";
-              }
-              Pop-Location;
-            }
-          $env:RESOLVERS = [string]::Join(";", $resolvers);
-      - IF DEFINED RESOLVERS FOR %%G in ("%RESOLVERS:;=";"%") do ( pushd %%~G & ci npm install --no-save nyc@%WINDOWS_NYC_VERSION% & popd )
-    # TODO: enable codecov for native windows builds
-    #on_success:
-    #- ci $ProgressPreference = 'SilentlyContinue'
-    #- ci Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe
-    #- ci -Outfile codecov.exe
-    #- ci .\codecov.exe
-  - matrix:
-      only:
-        - configuration: WSL
-    # Install scripts. (runs after repo cloning)
-    install:
-      # Get a specific version of Node.js
-      - ps: $env:WSLENV += ":nodejs_version"
-      - ps: wsl curl -sL 'https://deb.nodesource.com/setup_${nodejs_version}.x' `| sudo APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 -E bash -
-      - wsl sudo DEBIAN_FRONTEND=noninteractive apt install -y nodejs
-    on_success:
-      - ci curl -Os https://uploader.codecov.io/latest/linux/codecov
-      - ci chmod +x codecov
-      - ci ./codecov
-
-build: on

From 5508b6c6dfd4c0472ad98b10d3f45788bd6718fc Mon Sep 17 00:00:00 2001
From: Ashok Suthar <coderatlabs@gmail.com>
Date: Thu, 14 Mar 2024 07:45:50 +0100
Subject: [PATCH 672/767] [actions] migrate OSX tests to GHA

Co-authored-by: Ashok Suthar <coderatlabs@gmail.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 .github/workflows/node-4+.yml |  8 ++++++-
 .travis.yml                   | 40 -----------------------------------
 CHANGELOG.md                  |  4 ++++
 3 files changed, 11 insertions(+), 41 deletions(-)
 delete mode 100644 .travis.yml

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 2925adda8a..62c654decc 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -22,11 +22,14 @@ jobs:
   latest:
     needs: [matrix]
     name: 'majors'
-    runs-on: ubuntu-latest
+    runs-on: ${{ matrix.os }}
 
     strategy:
       fail-fast: false
       matrix:
+        os:
+          - ubuntu-latest
+          - macos-latest
         node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
         eslint:
           - 8
@@ -38,16 +41,19 @@ jobs:
           - 2
         include:
           - node-version: 'lts/*'
+            os: ubuntu-latest
             eslint: 7
             ts-parser: 4
             env:
               TS_PARSER: 4
           - node-version: 'lts/*'
+            os: ubuntu-latest
             eslint: 7
             ts-parser: 3
             env:
               TS_PARSER: 3
           - node-version: 'lts/*'
+            os: ubuntu-latest
             eslint: 7
             ts-parser: 2
             env:
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 21a7070fb7..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-language: node_js
-
-# osx backlog is often deep, so to be polite we can just hit these highlights
-matrix:
-  include:
-  - os: osx
-    env: ESLINT_VERSION=5
-    node_js: 14
-  - os: osx
-    env: ESLINT_VERSION=5
-    node_js: 12
-  - os: osx
-    env: ESLINT_VERSION=5
-    node_js: 10
-  - os: osx
-    env: ESLINT_VERSION=4
-    node_js: 8
-  - os: osx
-    env: ESLINT_VERSION=3
-    node_js: 6
-  - os: osx
-    env: ESLINT_VERSION=2
-    node_js: 4
-
-  fast_finish: true
-
-before_install:
-  - 'nvm install-latest-npm'
-  - 'NPM_CONFIG_LEGACY_PEER_DEPS=true npm install'
-  - 'npm run copy-metafiles'
-install:
-  - 'NPM_CONFIG_LEGACY_PEER_DEPS=true npm install'
-  - 'if [ -n "${ESLINT_VERSION}" ]; then ./tests/dep-time-travel.sh; fi'
-  - 'npm run pretest'
-
-script:
-  - npm run tests-only
-
-after_success:
-  - bash <(curl -Os https://uploader.codecov.io/latest/linux/codecov)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8a6f80d0e..b1aa3a9785 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Refactor] `ExportMap`: separate ExportMap instance from its builder logic ([#2985], thanks [@soryy708])
 - [Docs] `order`: Add a quick note on how unbound imports and --fix ([#2640], thanks [@minervabot])
 - [Tests] appveyor -> GHA (run tests on Windows in both pwsh and WSL + Ubuntu) ([#2987], thanks [@joeyguerra])
+- [actions] migrate OSX tests to GHA ([ljharb#37], thanks [@aks-])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1458,6 +1459,8 @@ for info on changes for earlier releases.
 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
 
+[ljharb#37]: https://github.com/ljharb/eslint-plugin-import/pull/37
+
 [#2930]: https://github.com/import-js/eslint-plugin-import/issues/2930
 [#2687]: https://github.com/import-js/eslint-plugin-import/issues/2687
 [#2684]: https://github.com/import-js/eslint-plugin-import/issues/2684
@@ -1690,6 +1693,7 @@ for info on changes for earlier releases.
 [@adjerbetian]: https://github.com/adjerbetian
 [@AdriAt360]: https://github.com/AdriAt360
 [@ai]: https://github.com/ai
+[@aks-]: https://github.com/aks-
 [@aladdin-add]: https://github.com/aladdin-add
 [@alex-page]: https://github.com/alex-page
 [@alexgorbatchev]: https://github.com/alexgorbatchev

From 38f8d25ef710747fe318d99b3f42e70bd1efc0f4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sat, 23 Mar 2024 22:47:24 -0700
Subject: [PATCH 673/767] [actions] update actions to node20

---
 .github/workflows/node-4+.yml      | 4 ++--
 .github/workflows/node-pretest.yml | 4 ++--
 .github/workflows/packages.yml     | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 62c654decc..60fa609dbe 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -105,7 +105,7 @@ jobs:
             eslint: 5
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: ljharb/actions/node/install@main
         continue-on-error: ${{ matrix.eslint == 4 && matrix.node-version == 4 }}
         name: 'nvm install ${{ matrix.node-version }} && npm install, with eslint ${{ matrix.eslint }}'
@@ -119,7 +119,7 @@ jobs:
           skip-ls-check: true
       - run: npm run pretest
       - run: npm run tests-only
-      - uses: codecov/codecov-action@v3
+      - uses: codecov/codecov-action@v3.1.5
 
   node:
     name: 'node 4+'
diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml
index e4340018e4..f8db36de57 100644
--- a/.github/workflows/node-pretest.yml
+++ b/.github/workflows/node-pretest.yml
@@ -10,7 +10,7 @@ jobs:
   #   runs-on: ubuntu-latest
 
   #   steps:
-  #     - uses: actions/checkout@v3
+  #     - uses: actions/checkout@v4
   #     - uses: ljharb/actions/node/install@main
   #       name: 'nvm install lts/* && npm install'
   #       with:
@@ -22,7 +22,7 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: ljharb/actions/node/install@main
         name: 'nvm install lts/* && npm install'
         with:
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index a6fb4e4cb5..213e1a43ce 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -38,7 +38,7 @@ jobs:
           # - utils
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: ljharb/actions/node/install@main
         name: 'nvm install ${{ matrix.node-version }} && npm install'
         env:
@@ -50,7 +50,7 @@ jobs:
           after_install: npm run copy-metafiles && ./tests/dep-time-travel.sh && cd ${{ matrix.package }} && npm install
           skip-ls-check: true
       - run: cd ${{ matrix.package }} && npm run tests-only
-      - uses: codecov/codecov-action@v3
+      - uses: codecov/codecov-action@v3.1.5
 
   packages:
     name: 'packages: all tests'

From 2de78c1eac5064858cc366e211913c4f9e43919b Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Mon, 25 Mar 2024 19:21:56 +0200
Subject: [PATCH 674/767] [Refactor] `exportMapBuilder`: avoid hoisting

---
 .eslintrc               |   1 -
 CHANGELOG.md            |   2 +
 src/exportMapBuilder.js | 305 ++++++++++++++++++++--------------------
 3 files changed, 155 insertions(+), 153 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 1bbbba0148..80e1014c60 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -229,7 +229,6 @@
         {
             "files": [
                 "utils/**", // TODO
-                "src/exportMapBuilder.js", // TODO
             ],
             "rules": {
                 "no-use-before-define": "off",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1aa3a9785..c05ea32c01 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] `order`: Add a quick note on how unbound imports and --fix ([#2640], thanks [@minervabot])
 - [Tests] appveyor -> GHA (run tests on Windows in both pwsh and WSL + Ubuntu) ([#2987], thanks [@joeyguerra])
 - [actions] migrate OSX tests to GHA ([ljharb#37], thanks [@aks-])
+- [Refactor] `exportMapBuilder`: avoid hoisting ([#2989], thanks [@soryy708])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1113,6 +1114,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
 [#2987]: https://github.com/import-js/eslint-plugin-import/pull/2987
 [#2985]: https://github.com/import-js/eslint-plugin-import/pull/2985
 [#2982]: https://github.com/import-js/eslint-plugin-import/pull/2982
diff --git a/src/exportMapBuilder.js b/src/exportMapBuilder.js
index f2b40e7b4c..5aeb306d0b 100644
--- a/src/exportMapBuilder.js
+++ b/src/exportMapBuilder.js
@@ -118,6 +118,100 @@ const availableDocStyleParsers = {
 
 const supportedImportTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
 
+let parserOptionsHash = '';
+let prevParserOptions = '';
+let settingsHash = '';
+let prevSettings = '';
+/**
+ * don't hold full context object in memory, just grab what we need.
+ * also calculate a cacheKey, where parts of the cacheKey hash are memoized
+ */
+function childContext(path, context) {
+  const { settings, parserOptions, parserPath } = context;
+
+  if (JSON.stringify(settings) !== prevSettings) {
+    settingsHash = hashObject({ settings }).digest('hex');
+    prevSettings = JSON.stringify(settings);
+  }
+
+  if (JSON.stringify(parserOptions) !== prevParserOptions) {
+    parserOptionsHash = hashObject({ parserOptions }).digest('hex');
+    prevParserOptions = JSON.stringify(parserOptions);
+  }
+
+  return {
+    cacheKey: String(parserPath) + parserOptionsHash + settingsHash + String(path),
+    settings,
+    parserOptions,
+    parserPath,
+    path,
+  };
+}
+
+/**
+ * sometimes legacy support isn't _that_ hard... right?
+ */
+function makeSourceCode(text, ast) {
+  if (SourceCode.length > 1) {
+    // ESLint 3
+    return new SourceCode(text, ast);
+  } else {
+    // ESLint 4, 5
+    return new SourceCode({ text, ast });
+  }
+}
+
+/**
+ * Traverse a pattern/identifier node, calling 'callback'
+ * for each leaf identifier.
+ * @param  {node}   pattern
+ * @param  {Function} callback
+ * @return {void}
+ */
+export function recursivePatternCapture(pattern, callback) {
+  switch (pattern.type) {
+    case 'Identifier': // base case
+      callback(pattern);
+      break;
+
+    case 'ObjectPattern':
+      pattern.properties.forEach((p) => {
+        if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
+          callback(p.argument);
+          return;
+        }
+        recursivePatternCapture(p.value, callback);
+      });
+      break;
+
+    case 'ArrayPattern':
+      pattern.elements.forEach((element) => {
+        if (element == null) { return; }
+        if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
+          callback(element.argument);
+          return;
+        }
+        recursivePatternCapture(element, callback);
+      });
+      break;
+
+    case 'AssignmentPattern':
+      callback(pattern.left);
+      break;
+    default:
+  }
+}
+
+/**
+ * The creation of this closure is isolated from other scopes
+ * to avoid over-retention of unrelated variables, which has
+ * caused memory leaks. See #1266.
+ */
+function thunkFor(p, context) {
+  // eslint-disable-next-line no-use-before-define
+  return () => ExportMapBuilder.for(childContext(p, context));
+}
+
 export default class ExportMapBuilder {
   static get(source, context) {
     const path = resolve(source, context);
@@ -183,6 +277,43 @@ export default class ExportMapBuilder {
   }
 
   static parse(path, content, context) {
+    function readTsConfig(context) {
+      const tsconfigInfo = tsConfigLoader({
+        cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
+        getEnv: (key) => process.env[key],
+      });
+      try {
+        if (tsconfigInfo.tsConfigPath !== undefined) {
+          // Projects not using TypeScript won't have `typescript` installed.
+          if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
+
+          const configFile = ts.readConfigFile(tsconfigInfo.tsConfigPath, ts.sys.readFile);
+          return ts.parseJsonConfigFileContent(
+            configFile.config,
+            ts.sys,
+            dirname(tsconfigInfo.tsConfigPath),
+          );
+        }
+      } catch (e) {
+        // Catch any errors
+      }
+
+      return null;
+    }
+
+    function isEsModuleInterop() {
+      const cacheKey = hashObject({
+        tsconfigRootDir: context.parserOptions && context.parserOptions.tsconfigRootDir,
+      }).digest('hex');
+      let tsConfig = tsconfigCache.get(cacheKey);
+      if (typeof tsConfig === 'undefined') {
+        tsConfig = readTsConfig(context);
+        tsconfigCache.set(cacheKey, tsConfig);
+      }
+
+      return tsConfig && tsConfig.options ? tsConfig.options.esModuleInterop : false;
+    }
+
     const m = new ExportMap(path);
     const isEsModuleInteropTrue = isEsModuleInterop();
 
@@ -201,6 +332,10 @@ export default class ExportMapBuilder {
 
     let hasDynamicImports = false;
 
+    function remotePath(value) {
+      return resolve.relative(value, path, context.settings);
+    }
+
     function processDynamicImport(source) {
       hasDynamicImports = true;
       if (source.type !== 'Literal') {
@@ -264,10 +399,6 @@ export default class ExportMapBuilder {
 
     const namespaces = new Map();
 
-    function remotePath(value) {
-      return resolve.relative(value, path, context.settings);
-    }
-
     function resolveImport(value) {
       const rp = remotePath(value);
       if (rp == null) { return null; }
@@ -324,27 +455,6 @@ export default class ExportMapBuilder {
       m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) });
     }
 
-    function captureDependencyWithSpecifiers(n) {
-      // import type { Foo } (TS and Flow); import typeof { Foo } (Flow)
-      const declarationIsType = n.importKind === 'type' || n.importKind === 'typeof';
-      // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
-      // shouldn't be considered to be just importing types
-      let specifiersOnlyImportingTypes = n.specifiers.length > 0;
-      const importedSpecifiers = new Set();
-      n.specifiers.forEach((specifier) => {
-        if (specifier.type === 'ImportSpecifier') {
-          importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
-        } else if (supportedImportTypes.has(specifier.type)) {
-          importedSpecifiers.add(specifier.type);
-        }
-
-        // import { type Foo } (Flow); import { typeof Foo } (Flow)
-        specifiersOnlyImportingTypes = specifiersOnlyImportingTypes
-          && (specifier.importKind === 'type' || specifier.importKind === 'typeof');
-      });
-      captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
-    }
-
     function captureDependency({ source }, isOnlyImportingTypes, importedSpecifiers = new Set()) {
       if (source == null) { return null; }
 
@@ -369,44 +479,28 @@ export default class ExportMapBuilder {
       return getter;
     }
 
-    const source = makeSourceCode(content, ast);
-
-    function readTsConfig(context) {
-      const tsconfigInfo = tsConfigLoader({
-        cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
-        getEnv: (key) => process.env[key],
-      });
-      try {
-        if (tsconfigInfo.tsConfigPath !== undefined) {
-          // Projects not using TypeScript won't have `typescript` installed.
-          if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
-
-          const configFile = ts.readConfigFile(tsconfigInfo.tsConfigPath, ts.sys.readFile);
-          return ts.parseJsonConfigFileContent(
-            configFile.config,
-            ts.sys,
-            dirname(tsconfigInfo.tsConfigPath),
-          );
+    function captureDependencyWithSpecifiers(n) {
+      // import type { Foo } (TS and Flow); import typeof { Foo } (Flow)
+      const declarationIsType = n.importKind === 'type' || n.importKind === 'typeof';
+      // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
+      // shouldn't be considered to be just importing types
+      let specifiersOnlyImportingTypes = n.specifiers.length > 0;
+      const importedSpecifiers = new Set();
+      n.specifiers.forEach((specifier) => {
+        if (specifier.type === 'ImportSpecifier') {
+          importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
+        } else if (supportedImportTypes.has(specifier.type)) {
+          importedSpecifiers.add(specifier.type);
         }
-      } catch (e) {
-        // Catch any errors
-      }
 
-      return null;
+        // import { type Foo } (Flow); import { typeof Foo } (Flow)
+        specifiersOnlyImportingTypes = specifiersOnlyImportingTypes
+          && (specifier.importKind === 'type' || specifier.importKind === 'typeof');
+      });
+      captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
     }
 
-    function isEsModuleInterop() {
-      const cacheKey = hashObject({
-        tsconfigRootDir: context.parserOptions && context.parserOptions.tsconfigRootDir,
-      }).digest('hex');
-      let tsConfig = tsconfigCache.get(cacheKey);
-      if (typeof tsConfig === 'undefined') {
-        tsConfig = readTsConfig(context);
-        tsconfigCache.set(cacheKey, tsConfig);
-      }
-
-      return tsConfig && tsConfig.options ? tsConfig.options.esModuleInterop : false;
-    }
+    const source = makeSourceCode(content, ast);
 
     ast.body.forEach(function (n) {
       if (n.type === 'ExportDefaultDeclaration') {
@@ -555,96 +649,3 @@ export default class ExportMapBuilder {
     return m;
   }
 }
-
-/**
- * The creation of this closure is isolated from other scopes
- * to avoid over-retention of unrelated variables, which has
- * caused memory leaks. See #1266.
- */
-function thunkFor(p, context) {
-  return () => ExportMapBuilder.for(childContext(p, context));
-}
-
-/**
- * Traverse a pattern/identifier node, calling 'callback'
- * for each leaf identifier.
- * @param  {node}   pattern
- * @param  {Function} callback
- * @return {void}
- */
-export function recursivePatternCapture(pattern, callback) {
-  switch (pattern.type) {
-    case 'Identifier': // base case
-      callback(pattern);
-      break;
-
-    case 'ObjectPattern':
-      pattern.properties.forEach((p) => {
-        if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
-          callback(p.argument);
-          return;
-        }
-        recursivePatternCapture(p.value, callback);
-      });
-      break;
-
-    case 'ArrayPattern':
-      pattern.elements.forEach((element) => {
-        if (element == null) { return; }
-        if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
-          callback(element.argument);
-          return;
-        }
-        recursivePatternCapture(element, callback);
-      });
-      break;
-
-    case 'AssignmentPattern':
-      callback(pattern.left);
-      break;
-    default:
-  }
-}
-
-let parserOptionsHash = '';
-let prevParserOptions = '';
-let settingsHash = '';
-let prevSettings = '';
-/**
- * don't hold full context object in memory, just grab what we need.
- * also calculate a cacheKey, where parts of the cacheKey hash are memoized
- */
-function childContext(path, context) {
-  const { settings, parserOptions, parserPath } = context;
-
-  if (JSON.stringify(settings) !== prevSettings) {
-    settingsHash = hashObject({ settings }).digest('hex');
-    prevSettings = JSON.stringify(settings);
-  }
-
-  if (JSON.stringify(parserOptions) !== prevParserOptions) {
-    parserOptionsHash = hashObject({ parserOptions }).digest('hex');
-    prevParserOptions = JSON.stringify(parserOptions);
-  }
-
-  return {
-    cacheKey: String(parserPath) + parserOptionsHash + settingsHash + String(path),
-    settings,
-    parserOptions,
-    parserPath,
-    path,
-  };
-}
-
-/**
- * sometimes legacy support isn't _that_ hard... right?
- */
-function makeSourceCode(text, ast) {
-  if (SourceCode.length > 1) {
-    // ESLint 3
-    return new SourceCode(text, ast);
-  } else {
-    // ESLint 4, 5
-    return new SourceCode({ text, ast });
-  }
-}

From 8587c85a60ccb3839cb2eabe50cf098a4a2c03c2 Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Wed, 27 Mar 2024 18:39:53 +0200
Subject: [PATCH 675/767] [Refactor] `ExportMap`: extract "builder" logic to
 separate files

---
 CHANGELOG.md                             |   2 +
 src/exportMap/builder.js                 | 206 +++++++
 src/exportMap/captureDependency.js       |  60 +++
 src/exportMap/childContext.js            |  32 ++
 src/exportMap/doc.js                     |  90 ++++
 src/{exportMap.js => exportMap/index.js} |   0
 src/exportMap/namespace.js               |  39 ++
 src/exportMap/patternCapture.js          |  40 ++
 src/exportMap/remotePath.js              |  12 +
 src/exportMap/specifier.js               |  32 ++
 src/exportMap/typescript.js              |  43 ++
 src/exportMap/visitor.js                 | 171 ++++++
 src/exportMapBuilder.js                  | 651 -----------------------
 src/rules/default.js                     |   2 +-
 src/rules/export.js                      |   3 +-
 src/rules/named.js                       |   2 +-
 src/rules/namespace.js                   |   2 +-
 src/rules/no-cycle.js                    |   2 +-
 src/rules/no-deprecated.js               |   2 +-
 src/rules/no-named-as-default-member.js  |   2 +-
 src/rules/no-named-as-default.js         |   2 +-
 src/rules/no-unused-modules.js           |   3 +-
 tests/src/core/getExports.js             |   2 +-
 23 files changed, 739 insertions(+), 661 deletions(-)
 create mode 100644 src/exportMap/builder.js
 create mode 100644 src/exportMap/captureDependency.js
 create mode 100644 src/exportMap/childContext.js
 create mode 100644 src/exportMap/doc.js
 rename src/{exportMap.js => exportMap/index.js} (100%)
 create mode 100644 src/exportMap/namespace.js
 create mode 100644 src/exportMap/patternCapture.js
 create mode 100644 src/exportMap/remotePath.js
 create mode 100644 src/exportMap/specifier.js
 create mode 100644 src/exportMap/typescript.js
 create mode 100644 src/exportMap/visitor.js
 delete mode 100644 src/exportMapBuilder.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c05ea32c01..a07647c82d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Tests] appveyor -> GHA (run tests on Windows in both pwsh and WSL + Ubuntu) ([#2987], thanks [@joeyguerra])
 - [actions] migrate OSX tests to GHA ([ljharb#37], thanks [@aks-])
 - [Refactor] `exportMapBuilder`: avoid hoisting ([#2989], thanks [@soryy708])
+- [Refactor] `ExportMap`: extract "builder" logic to separate files ([#2991], thanks [@soryy708])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1114,6 +1115,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#2991]: https://github.com/import-js/eslint-plugin-import/pull/2991
 [#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
 [#2987]: https://github.com/import-js/eslint-plugin-import/pull/2987
 [#2985]: https://github.com/import-js/eslint-plugin-import/pull/2985
diff --git a/src/exportMap/builder.js b/src/exportMap/builder.js
new file mode 100644
index 0000000000..5348dba375
--- /dev/null
+++ b/src/exportMap/builder.js
@@ -0,0 +1,206 @@
+import fs from 'fs';
+
+import doctrine from 'doctrine';
+
+import debug from 'debug';
+
+import parse from 'eslint-module-utils/parse';
+import visit from 'eslint-module-utils/visit';
+import resolve from 'eslint-module-utils/resolve';
+import isIgnored, { hasValidExtension } from 'eslint-module-utils/ignore';
+
+import { hashObject } from 'eslint-module-utils/hash';
+import * as unambiguous from 'eslint-module-utils/unambiguous';
+
+import ExportMap from '.';
+import childContext from './childContext';
+import { isEsModuleInterop } from './typescript';
+import { RemotePath } from './remotePath';
+import ImportExportVisitorBuilder from './visitor';
+
+const log = debug('eslint-plugin-import:ExportMap');
+
+const exportCache = new Map();
+
+/**
+ * The creation of this closure is isolated from other scopes
+ * to avoid over-retention of unrelated variables, which has
+ * caused memory leaks. See #1266.
+ */
+function thunkFor(p, context) {
+  // eslint-disable-next-line no-use-before-define
+  return () => ExportMapBuilder.for(childContext(p, context));
+}
+
+export default class ExportMapBuilder {
+  static get(source, context) {
+    const path = resolve(source, context);
+    if (path == null) { return null; }
+
+    return ExportMapBuilder.for(childContext(path, context));
+  }
+
+  static for(context) {
+    const { path } = context;
+
+    const cacheKey = context.cacheKey || hashObject(context).digest('hex');
+    let exportMap = exportCache.get(cacheKey);
+
+    // return cached ignore
+    if (exportMap === null) { return null; }
+
+    const stats = fs.statSync(path);
+    if (exportMap != null) {
+      // date equality check
+      if (exportMap.mtime - stats.mtime === 0) {
+        return exportMap;
+      }
+      // future: check content equality?
+    }
+
+    // check valid extensions first
+    if (!hasValidExtension(path, context)) {
+      exportCache.set(cacheKey, null);
+      return null;
+    }
+
+    // check for and cache ignore
+    if (isIgnored(path, context)) {
+      log('ignored path due to ignore settings:', path);
+      exportCache.set(cacheKey, null);
+      return null;
+    }
+
+    const content = fs.readFileSync(path, { encoding: 'utf8' });
+
+    // check for and cache unambiguous modules
+    if (!unambiguous.test(content)) {
+      log('ignored path due to unambiguous regex:', path);
+      exportCache.set(cacheKey, null);
+      return null;
+    }
+
+    log('cache miss', cacheKey, 'for path', path);
+    exportMap = ExportMapBuilder.parse(path, content, context);
+
+    // ambiguous modules return null
+    if (exportMap == null) {
+      log('ignored path due to ambiguous parse:', path);
+      exportCache.set(cacheKey, null);
+      return null;
+    }
+
+    exportMap.mtime = stats.mtime;
+
+    exportCache.set(cacheKey, exportMap);
+    return exportMap;
+  }
+
+  static parse(path, content, context) {
+    const exportMap = new ExportMap(path);
+    const isEsModuleInteropTrue = isEsModuleInterop(context);
+
+    let ast;
+    let visitorKeys;
+    try {
+      const result = parse(path, content, context);
+      ast = result.ast;
+      visitorKeys = result.visitorKeys;
+    } catch (err) {
+      exportMap.errors.push(err);
+      return exportMap; // can't continue
+    }
+
+    exportMap.visitorKeys = visitorKeys;
+
+    let hasDynamicImports = false;
+
+    const remotePathResolver = new RemotePath(path, context);
+
+    function processDynamicImport(source) {
+      hasDynamicImports = true;
+      if (source.type !== 'Literal') {
+        return null;
+      }
+      const p = remotePathResolver.resolve(source.value);
+      if (p == null) {
+        return null;
+      }
+      const importedSpecifiers = new Set();
+      importedSpecifiers.add('ImportNamespaceSpecifier');
+      const getter = thunkFor(p, context);
+      exportMap.imports.set(p, {
+        getter,
+        declarations: new Set([{
+          source: {
+          // capturing actual node reference holds full AST in memory!
+            value: source.value,
+            loc: source.loc,
+          },
+          importedSpecifiers,
+          dynamic: true,
+        }]),
+      });
+    }
+
+    visit(ast, visitorKeys, {
+      ImportExpression(node) {
+        processDynamicImport(node.source);
+      },
+      CallExpression(node) {
+        if (node.callee.type === 'Import') {
+          processDynamicImport(node.arguments[0]);
+        }
+      },
+    });
+
+    const unambiguouslyESM = unambiguous.isModule(ast);
+    if (!unambiguouslyESM && !hasDynamicImports) { return null; }
+
+    // attempt to collect module doc
+    if (ast.comments) {
+      ast.comments.some((c) => {
+        if (c.type !== 'Block') { return false; }
+        try {
+          const doc = doctrine.parse(c.value, { unwrap: true });
+          if (doc.tags.some((t) => t.title === 'module')) {
+            exportMap.doc = doc;
+            return true;
+          }
+        } catch (err) { /* ignore */ }
+        return false;
+      });
+    }
+
+    const visitorBuilder = new ImportExportVisitorBuilder(
+      path,
+      context,
+      exportMap,
+      ExportMapBuilder,
+      content,
+      ast,
+      isEsModuleInteropTrue,
+      thunkFor,
+    );
+    ast.body.forEach(function (astNode) {
+      const visitor = visitorBuilder.build(astNode);
+
+      if (visitor[astNode.type]) {
+        visitor[astNode.type].call(visitorBuilder);
+      }
+    });
+
+    if (
+      isEsModuleInteropTrue // esModuleInterop is on in tsconfig
+      && exportMap.namespace.size > 0 // anything is exported
+      && !exportMap.namespace.has('default') // and default isn't added already
+    ) {
+      exportMap.namespace.set('default', {}); // add default export
+    }
+
+    if (unambiguouslyESM) {
+      exportMap.parseGoal = 'Module';
+    }
+    return exportMap;
+  }
+}
diff --git a/src/exportMap/captureDependency.js b/src/exportMap/captureDependency.js
new file mode 100644
index 0000000000..9ad37d0e20
--- /dev/null
+++ b/src/exportMap/captureDependency.js
@@ -0,0 +1,60 @@
+export function captureDependency(
+  { source },
+  isOnlyImportingTypes,
+  remotePathResolver,
+  exportMap,
+  context,
+  thunkFor,
+  importedSpecifiers = new Set(),
+) {
+  if (source == null) { return null; }
+
+  const p = remotePathResolver.resolve(source.value);
+  if (p == null) { return null; }
+
+  const declarationMetadata = {
+    // capturing actual node reference holds full AST in memory!
+    source: { value: source.value, loc: source.loc },
+    isOnlyImportingTypes,
+    importedSpecifiers,
+  };
+
+  const existing = exportMap.imports.get(p);
+  if (existing != null) {
+    existing.declarations.add(declarationMetadata);
+    return existing.getter;
+  }
+
+  const getter = thunkFor(p, context);
+  exportMap.imports.set(p, { getter, declarations: new Set([declarationMetadata]) });
+  return getter;
+}
+
+const supportedImportTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
+
+export function captureDependencyWithSpecifiers(
+  n,
+  remotePathResolver,
+  exportMap,
+  context,
+  thunkFor,
+) {
+  // import type { Foo } (TS and Flow); import typeof { Foo } (Flow)
+  const declarationIsType = n.importKind === 'type' || n.importKind === 'typeof';
+  // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
+  // shouldn't be considered to be just importing types
+  let specifiersOnlyImportingTypes = n.specifiers.length > 0;
+  const importedSpecifiers = new Set();
+  n.specifiers.forEach((specifier) => {
+    if (specifier.type === 'ImportSpecifier') {
+      importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
+    } else if (supportedImportTypes.has(specifier.type)) {
+      importedSpecifiers.add(specifier.type);
+    }
+
+    // import { type Foo } (Flow); import { typeof Foo } (Flow)
+    specifiersOnlyImportingTypes = specifiersOnlyImportingTypes
+      && (specifier.importKind === 'type' || specifier.importKind === 'typeof');
+  });
+  captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, remotePathResolver, exportMap, context, thunkFor, importedSpecifiers);
+}
diff --git a/src/exportMap/childContext.js b/src/exportMap/childContext.js
new file mode 100644
index 0000000000..5f82b8e575
--- /dev/null
+++ b/src/exportMap/childContext.js
@@ -0,0 +1,32 @@
+import { hashObject } from 'eslint-module-utils/hash';
+
+let parserOptionsHash = '';
+let prevParserOptions = '';
+let settingsHash = '';
+let prevSettings = '';
+
+/**
+ * don't hold full context object in memory, just grab what we need.
+ * also calculate a cacheKey, where parts of the cacheKey hash are memoized
+ */
+export default function childContext(path, context) {
+  const { settings, parserOptions, parserPath } = context;
+
+  if (JSON.stringify(settings) !== prevSettings) {
+    settingsHash = hashObject({ settings }).digest('hex');
+    prevSettings = JSON.stringify(settings);
+  }
+
+  if (JSON.stringify(parserOptions) !== prevParserOptions) {
+    parserOptionsHash = hashObject({ parserOptions }).digest('hex');
+    prevParserOptions = JSON.stringify(parserOptions);
+  }
+
+  return {
+    cacheKey: String(parserPath) + parserOptionsHash + settingsHash + String(path),
+    settings,
+    parserOptions,
+    parserPath,
+    path,
+  };
+}
diff --git a/src/exportMap/doc.js b/src/exportMap/doc.js
new file mode 100644
index 0000000000..c721ae25fc
--- /dev/null
+++ b/src/exportMap/doc.js
@@ -0,0 +1,90 @@
+import doctrine from 'doctrine';
+
+/**
+ * parse docs from the first node that has leading comments
+ */
+export function captureDoc(source, docStyleParsers, ...nodes) {
+  const metadata = {};
+
+  // 'some' short-circuits on first 'true'
+  nodes.some((n) => {
+    try {
+
+      let leadingComments;
+
+      // n.leadingComments is legacy `attachComments` behavior
+      if ('leadingComments' in n) {
+        leadingComments = n.leadingComments;
+      } else if (n.range) {
+        leadingComments = source.getCommentsBefore(n);
+      }
+
+      if (!leadingComments || leadingComments.length === 0) { return false; }
+
+      for (const name in docStyleParsers) {
+        const doc = docStyleParsers[name](leadingComments);
+        if (doc) {
+          metadata.doc = doc;
+        }
+      }
+
+      return true;
+    } catch (err) {
+      return false;
+    }
+  });
+
+  return metadata;
+}
+
+/**
+ * parse JSDoc from leading comments
+ * @param {object[]} comments
+ * @return {{ doc: object }}
+ */
+function captureJsDoc(comments) {
+  let doc;
+
+  // capture XSDoc
+  comments.forEach((comment) => {
+    // skip non-block comments
+    if (comment.type !== 'Block') { return; }
+    try {
+      doc = doctrine.parse(comment.value, { unwrap: true });
+    } catch (err) {
+      /* don't care, for now? maybe add to `errors?` */
+    }
+  });
+
+  return doc;
+}
+
+/**
+  * parse TomDoc section from comments
+  */
+function captureTomDoc(comments) {
+  // collect lines up to first paragraph break
+  const lines = [];
+  for (let i = 0; i < comments.length; i++) {
+    const comment = comments[i];
+    if (comment.value.match(/^\s*$/)) { break; }
+    lines.push(comment.value.trim());
+  }
+
+  // return doctrine-like object
+  const statusMatch = lines.join(' ').match(/^(Public|Internal|Deprecated):\s*(.+)/);
+  if (statusMatch) {
+    return {
+      description: statusMatch[2],
+      tags: [{
+        title: statusMatch[1].toLowerCase(),
+        description: statusMatch[2],
+      }],
+    };
+  }
+}
+
+export const availableDocStyleParsers = {
+  jsdoc: captureJsDoc,
+  tomdoc: captureTomDoc,
+};
diff --git a/src/exportMap.js b/src/exportMap/index.js
similarity index 100%
rename from src/exportMap.js
rename to src/exportMap/index.js
diff --git a/src/exportMap/namespace.js b/src/exportMap/namespace.js
new file mode 100644
index 0000000000..370f47579d
--- /dev/null
+++ b/src/exportMap/namespace.js
@@ -0,0 +1,39 @@
+import childContext from './childContext';
+import { RemotePath } from './remotePath';
+
+export default class Namespace {
+  constructor(
+    path,
+    context,
+    ExportMapBuilder,
+  ) {
+    this.remotePathResolver = new RemotePath(path, context);
+    this.context = context;
+    this.ExportMapBuilder = ExportMapBuilder;
+    this.namespaces = new Map();
+  }
+
+  resolveImport(value) {
+    const rp = this.remotePathResolver.resolve(value);
+    if (rp == null) { return null; }
+    return this.ExportMapBuilder.for(childContext(rp, this.context));
+  }
+
+  getNamespace(identifier) {
+    if (!this.namespaces.has(identifier.name)) { return; }
+    return () => this.resolveImport(this.namespaces.get(identifier.name));
+  }
+
+  add(object, identifier) {
+    const nsfn = this.getNamespace(identifier);
+    if (nsfn) {
+      Object.defineProperty(object, 'namespace', { get: nsfn });
+    }
+
+    return object;
+  }
+
+  rawSet(name, value) {
+    this.namespaces.set(name, value);
+  }
+}
diff --git a/src/exportMap/patternCapture.js b/src/exportMap/patternCapture.js
new file mode 100644
index 0000000000..5bc9806417
--- /dev/null
+++ b/src/exportMap/patternCapture.js
@@ -0,0 +1,40 @@
+/**
+ * Traverse a pattern/identifier node, calling 'callback'
+ * for each leaf identifier.
+ * @param  {node}   pattern
+ * @param  {Function} callback
+ * @return {void}
+ */
+export default function recursivePatternCapture(pattern, callback) {
+  switch (pattern.type) {
+    case 'Identifier': // base case
+      callback(pattern);
+      break;
+
+    case 'ObjectPattern':
+      pattern.properties.forEach((p) => {
+        if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
+          callback(p.argument);
+          return;
+        }
+        recursivePatternCapture(p.value, callback);
+      });
+      break;
+
+    case 'ArrayPattern':
+      pattern.elements.forEach((element) => {
+        if (element == null) { return; }
+        if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
+          callback(element.argument);
+          return;
+        }
+        recursivePatternCapture(element, callback);
+      });
+      break;
+
+    case 'AssignmentPattern':
+      callback(pattern.left);
+      break;
+    default:
+  }
+}
diff --git a/src/exportMap/remotePath.js b/src/exportMap/remotePath.js
new file mode 100644
index 0000000000..0dc5fc0954
--- /dev/null
+++ b/src/exportMap/remotePath.js
@@ -0,0 +1,12 @@
+import resolve from 'eslint-module-utils/resolve';
+
+export class RemotePath {
+  constructor(path, context) {
+    this.path = path;
+    this.context = context;
+  }
+
+  resolve(value) {
+    return resolve.relative(value, this.path, this.context.settings);
+  }
+}
diff --git a/src/exportMap/specifier.js b/src/exportMap/specifier.js
new file mode 100644
index 0000000000..dfaaf618e4
--- /dev/null
+++ b/src/exportMap/specifier.js
@@ -0,0 +1,32 @@
+export default function processSpecifier(specifier, astNode, exportMap, namespace) {
+  const nsource = astNode.source && astNode.source.value;
+  const exportMeta = {};
+  let local;
+
+  switch (specifier.type) {
+    case 'ExportDefaultSpecifier':
+      if (!nsource) { return; }
+      local = 'default';
+      break;
+    case 'ExportNamespaceSpecifier':
+      exportMap.namespace.set(specifier.exported.name, Object.defineProperty(exportMeta, 'namespace', {
+        get() { return namespace.resolveImport(nsource); },
+      }));
+      return;
+    case 'ExportAllDeclaration':
+      exportMap.namespace.set(specifier.exported.name || specifier.exported.value, namespace.add(exportMeta, specifier.source.value));
+      return;
+    case 'ExportSpecifier':
+      if (!astNode.source) {
+        exportMap.namespace.set(specifier.exported.name || specifier.exported.value, namespace.add(exportMeta, specifier.local));
+        return;
+      }
+    // else falls through
+    default:
+      local = specifier.local.name;
+      break;
+  }
+
+  // todo: JSDoc
+  exportMap.reexports.set(specifier.exported.name, { local, getImport: () => namespace.resolveImport(nsource) });
+}
diff --git a/src/exportMap/typescript.js b/src/exportMap/typescript.js
new file mode 100644
index 0000000000..7db4356da8
--- /dev/null
+++ b/src/exportMap/typescript.js
@@ -0,0 +1,43 @@
+import { dirname } from 'path';
+import { tsConfigLoader } from 'tsconfig-paths/lib/tsconfig-loader';
+import { hashObject } from 'eslint-module-utils/hash';
+
+let ts;
+const tsconfigCache = new Map();
+
+function readTsConfig(context) {
+  const tsconfigInfo = tsConfigLoader({
+    cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
+    getEnv: (key) => process.env[key],
+  });
+  try {
+    if (tsconfigInfo.tsConfigPath !== undefined) {
+      // Projects not using TypeScript won't have `typescript` installed.
+      if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
+
+      const configFile = ts.readConfigFile(tsconfigInfo.tsConfigPath, ts.sys.readFile);
+      return ts.parseJsonConfigFileContent(
+        configFile.config,
+        ts.sys,
+        dirname(tsconfigInfo.tsConfigPath),
+      );
+    }
+  } catch (e) {
+    // Catch any errors
+  }
+
+  return null;
+}
+
+export function isEsModuleInterop(context) {
+  const cacheKey = hashObject({
+    tsconfigRootDir: context.parserOptions && context.parserOptions.tsconfigRootDir,
+  }).digest('hex');
+  let tsConfig = tsconfigCache.get(cacheKey);
+  if (typeof tsConfig === 'undefined') {
+    tsConfig = readTsConfig(context);
+    tsconfigCache.set(cacheKey, tsConfig);
+  }
+
+  return tsConfig && tsConfig.options ? tsConfig.options.esModuleInterop : false;
+}
diff --git a/src/exportMap/visitor.js b/src/exportMap/visitor.js
new file mode 100644
index 0000000000..21c1a7c644
--- /dev/null
+++ b/src/exportMap/visitor.js
@@ -0,0 +1,171 @@
+import includes from 'array-includes';
+import { SourceCode } from 'eslint';
+import { availableDocStyleParsers, captureDoc } from './doc';
+import Namespace from './namespace';
+import processSpecifier from './specifier';
+import { captureDependency, captureDependencyWithSpecifiers } from './captureDependency';
+import recursivePatternCapture from './patternCapture';
+import { RemotePath } from './remotePath';
+
+/**
+ * sometimes legacy support isn't _that_ hard... right?
+ */
+function makeSourceCode(text, ast) {
+  if (SourceCode.length > 1) {
+    // ESLint 3
+    return new SourceCode(text, ast);
+  } else {
+    // ESLint 4, 5
+    return new SourceCode({ text, ast });
+  }
+}
+
+export default class ImportExportVisitorBuilder {
+  constructor(
+    path,
+    context,
+    exportMap,
+    ExportMapBuilder,
+    content,
+    ast,
+    isEsModuleInteropTrue,
+    thunkFor,
+  ) {
+    this.context = context;
+    this.namespace = new Namespace(path, context, ExportMapBuilder);
+    this.remotePathResolver = new RemotePath(path, context);
+    this.source = makeSourceCode(content, ast);
+    this.exportMap = exportMap;
+    this.ast = ast;
+    this.isEsModuleInteropTrue = isEsModuleInteropTrue;
+    this.thunkFor = thunkFor;
+    const docstyle = this.context.settings && this.context.settings['import/docstyle'] || ['jsdoc'];
+    this.docStyleParsers = {};
+    docstyle.forEach((style) => {
+      this.docStyleParsers[style] = availableDocStyleParsers[style];
+    });
+  }
+
+  build(astNode) {
+    return {
+      ExportDefaultDeclaration() {
+        const exportMeta = captureDoc(this.source, this.docStyleParsers, astNode);
+        if (astNode.declaration.type === 'Identifier') {
+          this.namespace.add(exportMeta, astNode.declaration);
+        }
+        this.exportMap.namespace.set('default', exportMeta);
+      },
+      ExportAllDeclaration() {
+        const getter = captureDependency(astNode, astNode.exportKind === 'type', this.remotePathResolver, this.exportMap, this.context, this.thunkFor);
+        if (getter) { this.exportMap.dependencies.add(getter); }
+        if (astNode.exported) {
+          processSpecifier(astNode, astNode.exported, this.exportMap, this.namespace);
+        }
+      },
+      /** capture namespaces in case of later export */
+      ImportDeclaration() {
+        captureDependencyWithSpecifiers(astNode, this.remotePathResolver, this.exportMap, this.context, this.thunkFor);
+        const ns = astNode.specifiers.find((s) => s.type === 'ImportNamespaceSpecifier');
+        if (ns) {
+          this.namespace.rawSet(ns.local.name, astNode.source.value);
+        }
+      },
+      ExportNamedDeclaration() {
+        captureDependencyWithSpecifiers(astNode, this.remotePathResolver, this.exportMap, this.context, this.thunkFor);
+        // capture declaration
+        if (astNode.declaration != null) {
+          switch (astNode.declaration.type) {
+            case 'FunctionDeclaration':
+            case 'ClassDeclaration':
+            case 'TypeAlias': // flowtype with babel-eslint parser
+            case 'InterfaceDeclaration':
+            case 'DeclareFunction':
+            case 'TSDeclareFunction':
+            case 'TSEnumDeclaration':
+            case 'TSTypeAliasDeclaration':
+            case 'TSInterfaceDeclaration':
+            case 'TSAbstractClassDeclaration':
+            case 'TSModuleDeclaration':
+              this.exportMap.namespace.set(astNode.declaration.id.name, captureDoc(this.source, this.docStyleParsers, astNode));
+              break;
+            case 'VariableDeclaration':
+              astNode.declaration.declarations.forEach((d) => {
+                recursivePatternCapture(
+                  d.id,
+                  (id) => this.exportMap.namespace.set(id.name, captureDoc(this.source, this.docStyleParsers, d, astNode)),
+                );
+              });
+              break;
+            default:
+          }
+        }
+        astNode.specifiers.forEach((s) => processSpecifier(s, astNode, this.exportMap, this.namespace));
+      },
+      TSExportAssignment: () => this.typeScriptExport(astNode),
+      ...this.isEsModuleInteropTrue && { TSNamespaceExportDeclaration: () => this.typeScriptExport(astNode) },
+    };
+  }
+
+  // This doesn't declare anything, but changes what's being exported.
+  typeScriptExport(astNode) {
+    const exportedName = astNode.type === 'TSNamespaceExportDeclaration'
+      ? (astNode.id || astNode.name).name
+      : astNode.expression && astNode.expression.name || astNode.expression.id && astNode.expression.id.name || null;
+    const declTypes = [
+      'VariableDeclaration',
+      'ClassDeclaration',
+      'TSDeclareFunction',
+      'TSEnumDeclaration',
+      'TSTypeAliasDeclaration',
+      'TSInterfaceDeclaration',
+      'TSAbstractClassDeclaration',
+      'TSModuleDeclaration',
+    ];
+    const exportedDecls = this.ast.body.filter(({ type, id, declarations }) => includes(declTypes, type) && (
+      id && id.name === exportedName || declarations && declarations.find((d) => d.id.name === exportedName)
+    ));
+    if (exportedDecls.length === 0) {
+      // Export is not referencing any local declaration, must be re-exporting
+      this.exportMap.namespace.set('default', captureDoc(this.source, this.docStyleParsers, astNode));
+      return;
+    }
+    if (
+      this.isEsModuleInteropTrue // esModuleInterop is on in tsconfig
+      && !this.exportMap.namespace.has('default') // and default isn't added already
+    ) {
+      this.exportMap.namespace.set('default', {}); // add default export
+    }
+    exportedDecls.forEach((decl) => {
+      if (decl.type === 'TSModuleDeclaration') {
+        if (decl.body && decl.body.type === 'TSModuleDeclaration') {
+          this.exportMap.namespace.set(decl.body.id.name, captureDoc(this.source, this.docStyleParsers, decl.body));
+        } else if (decl.body && decl.body.body) {
+          decl.body.body.forEach((moduleBlockNode) => {
+            // Export-assignment exports all members in the namespace,
+            // explicitly exported or not.
+            const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration'
+              ? moduleBlockNode.declaration
+              : moduleBlockNode;
+
+            if (!namespaceDecl) {
+              // TypeScript can check this for us; we needn't
+            } else if (namespaceDecl.type === 'VariableDeclaration') {
+              namespaceDecl.declarations.forEach((d) => recursivePatternCapture(d.id, (id) => this.exportMap.namespace.set(
+                id.name,
+                captureDoc(this.source, this.docStyleParsers, decl, namespaceDecl, moduleBlockNode),
+              )),
+              );
+            } else {
+              this.exportMap.namespace.set(
+                namespaceDecl.id.name,
+                captureDoc(this.source, this.docStyleParsers, moduleBlockNode));
+            }
+          });
+        }
+      } else {
+        // Export as default
+        this.exportMap.namespace.set('default', captureDoc(this.source, this.docStyleParsers, decl));
+      }
+    });
+  }
+}
diff --git a/src/exportMapBuilder.js b/src/exportMapBuilder.js
deleted file mode 100644
index 5aeb306d0b..0000000000
--- a/src/exportMapBuilder.js
+++ /dev/null
@@ -1,651 +0,0 @@
-import fs from 'fs';
-import { dirname } from 'path';
-
-import doctrine from 'doctrine';
-
-import debug from 'debug';
-
-import { SourceCode } from 'eslint';
-
-import parse from 'eslint-module-utils/parse';
-import visit from 'eslint-module-utils/visit';
-import resolve from 'eslint-module-utils/resolve';
-import isIgnored, { hasValidExtension } from 'eslint-module-utils/ignore';
-
-import { hashObject } from 'eslint-module-utils/hash';
-import * as unambiguous from 'eslint-module-utils/unambiguous';
-
-import { tsConfigLoader } from 'tsconfig-paths/lib/tsconfig-loader';
-
-import includes from 'array-includes';
-import ExportMap from './exportMap';
-
-let ts;
-
-const log = debug('eslint-plugin-import:ExportMap');
-
-const exportCache = new Map();
-const tsconfigCache = new Map();
-
-/**
- * parse docs from the first node that has leading comments
- */
-function captureDoc(source, docStyleParsers, ...nodes) {
-  const metadata = {};
-
-  // 'some' short-circuits on first 'true'
-  nodes.some((n) => {
-    try {
-
-      let leadingComments;
-
-      // n.leadingComments is legacy `attachComments` behavior
-      if ('leadingComments' in n) {
-        leadingComments = n.leadingComments;
-      } else if (n.range) {
-        leadingComments = source.getCommentsBefore(n);
-      }
-
-      if (!leadingComments || leadingComments.length === 0) { return false; }
-
-      for (const name in docStyleParsers) {
-        const doc = docStyleParsers[name](leadingComments);
-        if (doc) {
-          metadata.doc = doc;
-        }
-      }
-
-      return true;
-    } catch (err) {
-      return false;
-    }
-  });
-
-  return metadata;
-}
-
-/**
- * parse JSDoc from leading comments
- * @param {object[]} comments
- * @return {{ doc: object }}
- */
-function captureJsDoc(comments) {
-  let doc;
-
-  // capture XSDoc
-  comments.forEach((comment) => {
-    // skip non-block comments
-    if (comment.type !== 'Block') { return; }
-    try {
-      doc = doctrine.parse(comment.value, { unwrap: true });
-    } catch (err) {
-      /* don't care, for now? maybe add to `errors?` */
-    }
-  });
-
-  return doc;
-}
-
-/**
-  * parse TomDoc section from comments
-  */
-function captureTomDoc(comments) {
-  // collect lines up to first paragraph break
-  const lines = [];
-  for (let i = 0; i < comments.length; i++) {
-    const comment = comments[i];
-    if (comment.value.match(/^\s*$/)) { break; }
-    lines.push(comment.value.trim());
-  }
-
-  // return doctrine-like object
-  const statusMatch = lines.join(' ').match(/^(Public|Internal|Deprecated):\s*(.+)/);
-  if (statusMatch) {
-    return {
-      description: statusMatch[2],
-      tags: [{
-        title: statusMatch[1].toLowerCase(),
-        description: statusMatch[2],
-      }],
-    };
-  }
-}
-
-const availableDocStyleParsers = {
-  jsdoc: captureJsDoc,
-  tomdoc: captureTomDoc,
-};
-
-const supportedImportTypes = new Set(['ImportDefaultSpecifier', 'ImportNamespaceSpecifier']);
-
-let parserOptionsHash = '';
-let prevParserOptions = '';
-let settingsHash = '';
-let prevSettings = '';
-/**
- * don't hold full context object in memory, just grab what we need.
- * also calculate a cacheKey, where parts of the cacheKey hash are memoized
- */
-function childContext(path, context) {
-  const { settings, parserOptions, parserPath } = context;
-
-  if (JSON.stringify(settings) !== prevSettings) {
-    settingsHash = hashObject({ settings }).digest('hex');
-    prevSettings = JSON.stringify(settings);
-  }
-
-  if (JSON.stringify(parserOptions) !== prevParserOptions) {
-    parserOptionsHash = hashObject({ parserOptions }).digest('hex');
-    prevParserOptions = JSON.stringify(parserOptions);
-  }
-
-  return {
-    cacheKey: String(parserPath) + parserOptionsHash + settingsHash + String(path),
-    settings,
-    parserOptions,
-    parserPath,
-    path,
-  };
-}
-
-/**
- * sometimes legacy support isn't _that_ hard... right?
- */
-function makeSourceCode(text, ast) {
-  if (SourceCode.length > 1) {
-    // ESLint 3
-    return new SourceCode(text, ast);
-  } else {
-    // ESLint 4, 5
-    return new SourceCode({ text, ast });
-  }
-}
-
-/**
- * Traverse a pattern/identifier node, calling 'callback'
- * for each leaf identifier.
- * @param  {node}   pattern
- * @param  {Function} callback
- * @return {void}
- */
-export function recursivePatternCapture(pattern, callback) {
-  switch (pattern.type) {
-    case 'Identifier': // base case
-      callback(pattern);
-      break;
-
-    case 'ObjectPattern':
-      pattern.properties.forEach((p) => {
-        if (p.type === 'ExperimentalRestProperty' || p.type === 'RestElement') {
-          callback(p.argument);
-          return;
-        }
-        recursivePatternCapture(p.value, callback);
-      });
-      break;
-
-    case 'ArrayPattern':
-      pattern.elements.forEach((element) => {
-        if (element == null) { return; }
-        if (element.type === 'ExperimentalRestProperty' || element.type === 'RestElement') {
-          callback(element.argument);
-          return;
-        }
-        recursivePatternCapture(element, callback);
-      });
-      break;
-
-    case 'AssignmentPattern':
-      callback(pattern.left);
-      break;
-    default:
-  }
-}
-
-/**
- * The creation of this closure is isolated from other scopes
- * to avoid over-retention of unrelated variables, which has
- * caused memory leaks. See #1266.
- */
-function thunkFor(p, context) {
-  // eslint-disable-next-line no-use-before-define
-  return () => ExportMapBuilder.for(childContext(p, context));
-}
-
-export default class ExportMapBuilder {
-  static get(source, context) {
-    const path = resolve(source, context);
-    if (path == null) { return null; }
-
-    return ExportMapBuilder.for(childContext(path, context));
-  }
-
-  static for(context) {
-    const { path } = context;
-
-    const cacheKey = context.cacheKey || hashObject(context).digest('hex');
-    let exportMap = exportCache.get(cacheKey);
-
-    // return cached ignore
-    if (exportMap === null) { return null; }
-
-    const stats = fs.statSync(path);
-    if (exportMap != null) {
-      // date equality check
-      if (exportMap.mtime - stats.mtime === 0) {
-        return exportMap;
-      }
-      // future: check content equality?
-    }
-
-    // check valid extensions first
-    if (!hasValidExtension(path, context)) {
-      exportCache.set(cacheKey, null);
-      return null;
-    }
-
-    // check for and cache ignore
-    if (isIgnored(path, context)) {
-      log('ignored path due to ignore settings:', path);
-      exportCache.set(cacheKey, null);
-      return null;
-    }
-
-    const content = fs.readFileSync(path, { encoding: 'utf8' });
-
-    // check for and cache unambiguous modules
-    if (!unambiguous.test(content)) {
-      log('ignored path due to unambiguous regex:', path);
-      exportCache.set(cacheKey, null);
-      return null;
-    }
-
-    log('cache miss', cacheKey, 'for path', path);
-    exportMap = ExportMapBuilder.parse(path, content, context);
-
-    // ambiguous modules return null
-    if (exportMap == null) {
-      log('ignored path due to ambiguous parse:', path);
-      exportCache.set(cacheKey, null);
-      return null;
-    }
-
-    exportMap.mtime = stats.mtime;
-
-    exportCache.set(cacheKey, exportMap);
-    return exportMap;
-  }
-
-  static parse(path, content, context) {
-    function readTsConfig(context) {
-      const tsconfigInfo = tsConfigLoader({
-        cwd: context.parserOptions && context.parserOptions.tsconfigRootDir || process.cwd(),
-        getEnv: (key) => process.env[key],
-      });
-      try {
-        if (tsconfigInfo.tsConfigPath !== undefined) {
-          // Projects not using TypeScript won't have `typescript` installed.
-          if (!ts) { ts = require('typescript'); } // eslint-disable-line import/no-extraneous-dependencies
-
-          const configFile = ts.readConfigFile(tsconfigInfo.tsConfigPath, ts.sys.readFile);
-          return ts.parseJsonConfigFileContent(
-            configFile.config,
-            ts.sys,
-            dirname(tsconfigInfo.tsConfigPath),
-          );
-        }
-      } catch (e) {
-        // Catch any errors
-      }
-
-      return null;
-    }
-
-    function isEsModuleInterop() {
-      const cacheKey = hashObject({
-        tsconfigRootDir: context.parserOptions && context.parserOptions.tsconfigRootDir,
-      }).digest('hex');
-      let tsConfig = tsconfigCache.get(cacheKey);
-      if (typeof tsConfig === 'undefined') {
-        tsConfig = readTsConfig(context);
-        tsconfigCache.set(cacheKey, tsConfig);
-      }
-
-      return tsConfig && tsConfig.options ? tsConfig.options.esModuleInterop : false;
-    }
-
-    const m = new ExportMap(path);
-    const isEsModuleInteropTrue = isEsModuleInterop();
-
-    let ast;
-    let visitorKeys;
-    try {
-      const result = parse(path, content, context);
-      ast = result.ast;
-      visitorKeys = result.visitorKeys;
-    } catch (err) {
-      m.errors.push(err);
-      return m; // can't continue
-    }
-
-    m.visitorKeys = visitorKeys;
-
-    let hasDynamicImports = false;
-
-    function remotePath(value) {
-      return resolve.relative(value, path, context.settings);
-    }
-
-    function processDynamicImport(source) {
-      hasDynamicImports = true;
-      if (source.type !== 'Literal') {
-        return null;
-      }
-      const p = remotePath(source.value);
-      if (p == null) {
-        return null;
-      }
-      const importedSpecifiers = new Set();
-      importedSpecifiers.add('ImportNamespaceSpecifier');
-      const getter = thunkFor(p, context);
-      m.imports.set(p, {
-        getter,
-        declarations: new Set([{
-          source: {
-          // capturing actual node reference holds full AST in memory!
-            value: source.value,
-            loc: source.loc,
-          },
-          importedSpecifiers,
-          dynamic: true,
-        }]),
-      });
-    }
-
-    visit(ast, visitorKeys, {
-      ImportExpression(node) {
-        processDynamicImport(node.source);
-      },
-      CallExpression(node) {
-        if (node.callee.type === 'Import') {
-          processDynamicImport(node.arguments[0]);
-        }
-      },
-    });
-
-    const unambiguouslyESM = unambiguous.isModule(ast);
-    if (!unambiguouslyESM && !hasDynamicImports) { return null; }
-
-    const docstyle = context.settings && context.settings['import/docstyle'] || ['jsdoc'];
-    const docStyleParsers = {};
-    docstyle.forEach((style) => {
-      docStyleParsers[style] = availableDocStyleParsers[style];
-    });
-
-    // attempt to collect module doc
-    if (ast.comments) {
-      ast.comments.some((c) => {
-        if (c.type !== 'Block') { return false; }
-        try {
-          const doc = doctrine.parse(c.value, { unwrap: true });
-          if (doc.tags.some((t) => t.title === 'module')) {
-            m.doc = doc;
-            return true;
-          }
-        } catch (err) { /* ignore */ }
-        return false;
-      });
-    }
-
-    const namespaces = new Map();
-
-    function resolveImport(value) {
-      const rp = remotePath(value);
-      if (rp == null) { return null; }
-      return ExportMapBuilder.for(childContext(rp, context));
-    }
-
-    function getNamespace(identifier) {
-      if (!namespaces.has(identifier.name)) { return; }
-
-      return function () {
-        return resolveImport(namespaces.get(identifier.name));
-      };
-    }
-
-    function addNamespace(object, identifier) {
-      const nsfn = getNamespace(identifier);
-      if (nsfn) {
-        Object.defineProperty(object, 'namespace', { get: nsfn });
-      }
-
-      return object;
-    }
-
-    function processSpecifier(s, n, m) {
-      const nsource = n.source && n.source.value;
-      const exportMeta = {};
-      let local;
-
-      switch (s.type) {
-        case 'ExportDefaultSpecifier':
-          if (!nsource) { return; }
-          local = 'default';
-          break;
-        case 'ExportNamespaceSpecifier':
-          m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
-            get() { return resolveImport(nsource); },
-          }));
-          return;
-        case 'ExportAllDeclaration':
-          m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.source.value));
-          return;
-        case 'ExportSpecifier':
-          if (!n.source) {
-            m.namespace.set(s.exported.name || s.exported.value, addNamespace(exportMeta, s.local));
-            return;
-          }
-        // else falls through
-        default:
-          local = s.local.name;
-          break;
-      }
-
-      // todo: JSDoc
-      m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) });
-    }
-
-    function captureDependency({ source }, isOnlyImportingTypes, importedSpecifiers = new Set()) {
-      if (source == null) { return null; }
-
-      const p = remotePath(source.value);
-      if (p == null) { return null; }
-
-      const declarationMetadata = {
-        // capturing actual node reference holds full AST in memory!
-        source: { value: source.value, loc: source.loc },
-        isOnlyImportingTypes,
-        importedSpecifiers,
-      };
-
-      const existing = m.imports.get(p);
-      if (existing != null) {
-        existing.declarations.add(declarationMetadata);
-        return existing.getter;
-      }
-
-      const getter = thunkFor(p, context);
-      m.imports.set(p, { getter, declarations: new Set([declarationMetadata]) });
-      return getter;
-    }
-
-    function captureDependencyWithSpecifiers(n) {
-      // import type { Foo } (TS and Flow); import typeof { Foo } (Flow)
-      const declarationIsType = n.importKind === 'type' || n.importKind === 'typeof';
-      // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and
-      // shouldn't be considered to be just importing types
-      let specifiersOnlyImportingTypes = n.specifiers.length > 0;
-      const importedSpecifiers = new Set();
-      n.specifiers.forEach((specifier) => {
-        if (specifier.type === 'ImportSpecifier') {
-          importedSpecifiers.add(specifier.imported.name || specifier.imported.value);
-        } else if (supportedImportTypes.has(specifier.type)) {
-          importedSpecifiers.add(specifier.type);
-        }
-
-        // import { type Foo } (Flow); import { typeof Foo } (Flow)
-        specifiersOnlyImportingTypes = specifiersOnlyImportingTypes
-          && (specifier.importKind === 'type' || specifier.importKind === 'typeof');
-      });
-      captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers);
-    }
-
-    const source = makeSourceCode(content, ast);
-
-    ast.body.forEach(function (n) {
-      if (n.type === 'ExportDefaultDeclaration') {
-        const exportMeta = captureDoc(source, docStyleParsers, n);
-        if (n.declaration.type === 'Identifier') {
-          addNamespace(exportMeta, n.declaration);
-        }
-        m.namespace.set('default', exportMeta);
-        return;
-      }
-
-      if (n.type === 'ExportAllDeclaration') {
-        const getter = captureDependency(n, n.exportKind === 'type');
-        if (getter) { m.dependencies.add(getter); }
-        if (n.exported) {
-          processSpecifier(n, n.exported, m);
-        }
-        return;
-      }
-
-      // capture namespaces in case of later export
-      if (n.type === 'ImportDeclaration') {
-        captureDependencyWithSpecifiers(n);
-
-        const ns = n.specifiers.find((s) => s.type === 'ImportNamespaceSpecifier');
-        if (ns) {
-          namespaces.set(ns.local.name, n.source.value);
-        }
-        return;
-      }
-
-      if (n.type === 'ExportNamedDeclaration') {
-        captureDependencyWithSpecifiers(n);
-
-        // capture declaration
-        if (n.declaration != null) {
-          switch (n.declaration.type) {
-            case 'FunctionDeclaration':
-            case 'ClassDeclaration':
-            case 'TypeAlias': // flowtype with babel-eslint parser
-            case 'InterfaceDeclaration':
-            case 'DeclareFunction':
-            case 'TSDeclareFunction':
-            case 'TSEnumDeclaration':
-            case 'TSTypeAliasDeclaration':
-            case 'TSInterfaceDeclaration':
-            case 'TSAbstractClassDeclaration':
-            case 'TSModuleDeclaration':
-              m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n));
-              break;
-            case 'VariableDeclaration':
-              n.declaration.declarations.forEach((d) => {
-                recursivePatternCapture(
-                  d.id,
-                  (id) => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n)),
-                );
-              });
-              break;
-            default:
-          }
-        }
-
-        n.specifiers.forEach((s) => processSpecifier(s, n, m));
-      }
-
-      const exports = ['TSExportAssignment'];
-      if (isEsModuleInteropTrue) {
-        exports.push('TSNamespaceExportDeclaration');
-      }
-
-      // This doesn't declare anything, but changes what's being exported.
-      if (includes(exports, n.type)) {
-        const exportedName = n.type === 'TSNamespaceExportDeclaration'
-          ? (n.id || n.name).name
-          : n.expression && n.expression.name || n.expression.id && n.expression.id.name || null;
-        const declTypes = [
-          'VariableDeclaration',
-          'ClassDeclaration',
-          'TSDeclareFunction',
-          'TSEnumDeclaration',
-          'TSTypeAliasDeclaration',
-          'TSInterfaceDeclaration',
-          'TSAbstractClassDeclaration',
-          'TSModuleDeclaration',
-        ];
-        const exportedDecls = ast.body.filter(({ type, id, declarations }) => includes(declTypes, type) && (
-          id && id.name === exportedName || declarations && declarations.find((d) => d.id.name === exportedName)
-        ));
-        if (exportedDecls.length === 0) {
-          // Export is not referencing any local declaration, must be re-exporting
-          m.namespace.set('default', captureDoc(source, docStyleParsers, n));
-          return;
-        }
-        if (
-          isEsModuleInteropTrue // esModuleInterop is on in tsconfig
-          && !m.namespace.has('default') // and default isn't added already
-        ) {
-          m.namespace.set('default', {}); // add default export
-        }
-        exportedDecls.forEach((decl) => {
-          if (decl.type === 'TSModuleDeclaration') {
-            if (decl.body && decl.body.type === 'TSModuleDeclaration') {
-              m.namespace.set(decl.body.id.name, captureDoc(source, docStyleParsers, decl.body));
-            } else if (decl.body && decl.body.body) {
-              decl.body.body.forEach((moduleBlockNode) => {
-                // Export-assignment exports all members in the namespace,
-                // explicitly exported or not.
-                const namespaceDecl = moduleBlockNode.type === 'ExportNamedDeclaration'
-                  ? moduleBlockNode.declaration
-                  : moduleBlockNode;
-
-                if (!namespaceDecl) {
-                  // TypeScript can check this for us; we needn't
-                } else if (namespaceDecl.type === 'VariableDeclaration') {
-                  namespaceDecl.declarations.forEach((d) => recursivePatternCapture(d.id, (id) => m.namespace.set(
-                    id.name,
-                    captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode),
-                  )),
-                  );
-                } else {
-                  m.namespace.set(
-                    namespaceDecl.id.name,
-                    captureDoc(source, docStyleParsers, moduleBlockNode));
-                }
-              });
-            }
-          } else {
-            // Export as default
-            m.namespace.set('default', captureDoc(source, docStyleParsers, decl));
-          }
-        });
-      }
-    });
-
-    if (
-      isEsModuleInteropTrue // esModuleInterop is on in tsconfig
-      && m.namespace.size > 0 // anything is exported
-      && !m.namespace.has('default') // and default isn't added already
-    ) {
-      m.namespace.set('default', {}); // add default export
-    }
-
-    if (unambiguouslyESM) {
-      m.parseGoal = 'Module';
-    }
-    return m;
-  }
-}
diff --git a/src/rules/default.js b/src/rules/default.js
index cbaa49f1fc..0de787c33c 100644
--- a/src/rules/default.js
+++ b/src/rules/default.js
@@ -1,4 +1,4 @@
-import ExportMapBuilder from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
 import docsUrl from '../docsUrl';
 
 module.exports = {
diff --git a/src/rules/export.js b/src/rules/export.js
index b1dc5ca9ea..197a0eb51c 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -1,4 +1,5 @@
-import ExportMapBuilder, { recursivePatternCapture } from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
+import recursivePatternCapture from '../exportMap/patternCapture';
 import docsUrl from '../docsUrl';
 import includes from 'array-includes';
 import flatMap from 'array.prototype.flatmap';
diff --git a/src/rules/named.js b/src/rules/named.js
index 043d72eabe..ed7e5e018b 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -1,5 +1,5 @@
 import * as path from 'path';
-import ExportMapBuilder from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
 import docsUrl from '../docsUrl';
 
 module.exports = {
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index e1ca2870b1..60a4220de2 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -1,5 +1,5 @@
 import declaredScope from 'eslint-module-utils/declaredScope';
-import ExportMapBuilder from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
 import ExportMap from '../exportMap';
 import importDeclaration from '../importDeclaration';
 import docsUrl from '../docsUrl';
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index b7b907b062..e65ff11a49 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -4,7 +4,7 @@
  */
 
 import resolve from 'eslint-module-utils/resolve';
-import ExportMapBuilder from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
 import { isExternalModule } from '../core/importType';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index 50072f3f85..b4299a51d4 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -1,5 +1,5 @@
 import declaredScope from 'eslint-module-utils/declaredScope';
-import ExportMapBuilder from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
 import ExportMap from '../exportMap';
 import docsUrl from '../docsUrl';
 
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index d594c58433..54bec64a2a 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -4,7 +4,7 @@
  * @copyright 2016 Desmond Brand. All rights reserved.
  * See LICENSE in root directory for full license.
  */
-import ExportMapBuilder from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
 import importDeclaration from '../importDeclaration';
 import docsUrl from '../docsUrl';
 
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index 3e73ff2f44..5b24f8e883 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -1,4 +1,4 @@
-import ExportMapBuilder from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
 import importDeclaration from '../importDeclaration';
 import docsUrl from '../docsUrl';
 
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 812efffbca..0ad330b486 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -13,7 +13,8 @@ import values from 'object.values';
 import includes from 'array-includes';
 import flatMap from 'array.prototype.flatmap';
 
-import ExportMapBuilder, { recursivePatternCapture } from '../exportMapBuilder';
+import ExportMapBuilder from '../exportMap/builder';
+import recursivePatternCapture from '../exportMap/patternCapture';
 import docsUrl from '../docsUrl';
 
 let FileEnumerator;
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 611a13055f..76003410d5 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -4,7 +4,7 @@ import sinon from 'sinon';
 import eslintPkg from 'eslint/package.json';
 import typescriptPkg from 'typescript/package.json';
 import * as tsConfigLoader from 'tsconfig-paths/lib/tsconfig-loader';
-import ExportMapBuilder from '../../../src/exportMapBuilder';
+import ExportMapBuilder from '../../../src/exportMap/builder';
 
 import * as fs from 'fs';
 

From f77ceb679d59ced5d9a633123385470a9eea10d9 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Sun, 7 Apr 2024 12:55:28 +1200
Subject: [PATCH 676/767] [actions] cancel in-progress runs on PR updates

---
 .github/workflows/native-wsl.yml | 4 ++++
 .github/workflows/node-4+.yml    | 4 ++++
 .github/workflows/packages.yml   | 4 ++++
 3 files changed, 12 insertions(+)

diff --git a/.github/workflows/native-wsl.yml b/.github/workflows/native-wsl.yml
index 893d2248d1..5e8318899e 100644
--- a/.github/workflows/native-wsl.yml
+++ b/.github/workflows/native-wsl.yml
@@ -2,6 +2,10 @@ name: Native and WSL
 
 on: [push, pull_request]
 
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
 jobs:
   build:
     runs-on: ${{ matrix.os }}
diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index 60fa609dbe..f2dad098ca 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -2,6 +2,10 @@ name: 'Tests: node.js'
 
 on: [pull_request, push]
 
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
 permissions:
   contents: read
 
diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml
index 213e1a43ce..f73f8e18ff 100644
--- a/.github/workflows/packages.yml
+++ b/.github/workflows/packages.yml
@@ -2,6 +2,10 @@ name: 'Tests: packages'
 
 on: [pull_request, push]
 
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
 permissions:
   contents: read
 

From c0ac54b8a721c2b1c9048838acc4d6282f4fe7a7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 25 Apr 2024 10:57:27 -0700
Subject: [PATCH 677/767] [Dev Deps] pin `find-babel-config` to v1.2.0, due to
 a breaking change in v1.2.1

See https://github.com/tleunen/find-babel-config/issues/70#issuecomment-2077838243
---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index 638942f97c..b9fa1eb35f 100644
--- a/package.json
+++ b/package.json
@@ -82,6 +82,7 @@
     "eslint-plugin-eslint-plugin": "^2.3.0",
     "eslint-plugin-import": "2.x",
     "eslint-plugin-json": "^2.1.2",
+    "find-babel-config": "=1.2.0",
     "fs-copy-file-sync": "^1.1.1",
     "glob": "^7.2.3",
     "in-publish": "^2.0.1",

From a3a7176f6bc8a5e614eda95df74c43c30e148022 Mon Sep 17 00:00:00 2001
From: Ankit Sardesai <ankit@makenotion.com>
Date: Tue, 23 Apr 2024 21:40:29 -0700
Subject: [PATCH 678/767] [New] `dynamic-import-chunkname`: Allow empty chunk
 name when webpackMode: 'eager' is set; add suggestions to remove name in
 eager mode'

---
 CHANGELOG.md                                |   3 +
 README.md                                   |   2 +-
 docs/rules/dynamic-import-chunkname.md      |   9 +
 src/rules/dynamic-import-chunkname.js       |  51 ++++-
 tests/src/rules/dynamic-import-chunkname.js | 221 ++++++++++++++++++--
 5 files changed, 268 insertions(+), 18 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a07647c82d..c7cd6c4431 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Added
 - [`dynamic-import-chunkname`]: add `allowEmpty` option to allow empty leading comments ([#2942], thanks [@JiangWeixian])
+- [`dynamic-import-chunkname`]: Allow empty chunk name when webpackMode: 'eager' is set; add suggestions to remove name in eager mode ([#3004], thanks [@amsardesai])
 
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
@@ -1115,6 +1116,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
 [#2991]: https://github.com/import-js/eslint-plugin-import/pull/2991
 [#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
 [#2987]: https://github.com/import-js/eslint-plugin-import/pull/2987
@@ -1701,6 +1703,7 @@ for info on changes for earlier releases.
 [@aladdin-add]: https://github.com/aladdin-add
 [@alex-page]: https://github.com/alex-page
 [@alexgorbatchev]: https://github.com/alexgorbatchev
+[@amsardesai]: https://github.com/amsardesai
 [@andreubotella]: https://github.com/andreubotella
 [@AndrewLeedham]: https://github.com/AndrewLeedham
 [@andyogo]: https://github.com/andyogo
diff --git a/README.md b/README.md
index d6f107d1c9..1fd113c7d0 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 | Name                                                                             | Description                                                                | 💼 | ⚠️    | 🚫 | 🔧 | 💡 | ❌  |
 | :------------------------------------------------------------------------------- | :------------------------------------------------------------------------- | :- | :---- | :- | :- | :- | :- |
 | [consistent-type-specifier-style](docs/rules/consistent-type-specifier-style.md) | Enforce or ban the use of inline type-only markers for named imports.      |    |       |    | 🔧 |    |    |
-| [dynamic-import-chunkname](docs/rules/dynamic-import-chunkname.md)               | Enforce a leading comment with the webpackChunkName for dynamic imports.   |    |       |    |    |    |    |
+| [dynamic-import-chunkname](docs/rules/dynamic-import-chunkname.md)               | Enforce a leading comment with the webpackChunkName for dynamic imports.   |    |       |    |    | 💡 |    |
 | [exports-last](docs/rules/exports-last.md)                                       | Ensure all exports appear after other statements.                          |    |       |    |    |    |    |
 | [extensions](docs/rules/extensions.md)                                           | Ensure consistent use of file extension within the import path.            |    |       |    |    |    |    |
 | [first](docs/rules/first.md)                                                     | Ensure all imports appear before other statements.                         |    |       |    | 🔧 |    |    |
diff --git a/docs/rules/dynamic-import-chunkname.md b/docs/rules/dynamic-import-chunkname.md
index dd526c8913..de554148ee 100644
--- a/docs/rules/dynamic-import-chunkname.md
+++ b/docs/rules/dynamic-import-chunkname.md
@@ -1,5 +1,7 @@
 # import/dynamic-import-chunkname
 
+💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
+
 <!-- end auto-generated rule header -->
 
 This rule reports any dynamic imports without a webpackChunkName specified in a leading block comment in the proper format.
@@ -56,6 +58,13 @@ import(
   // webpackChunkName: "someModule"
   'someModule',
 );
+
+// chunk names are disallowed when eager mode is set
+import(
+  /* webpackMode: "eager" */
+  /* webpackChunkName: "someModule" */
+  'someModule',
+)
 ```
 
 ### valid
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index a62e5c6c12..a72b04d123 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -27,6 +27,7 @@ module.exports = {
         },
       },
     }],
+    hasSuggestions: true,
   },
 
   create(context) {
@@ -36,8 +37,10 @@ module.exports = {
 
     const paddedCommentRegex = /^ (\S[\s\S]+\S) $/;
     const commentStyleRegex = /^( ((webpackChunkName: .+)|((webpackPrefetch|webpackPreload): (true|false|-?[0-9]+))|(webpackIgnore: (true|false))|((webpackInclude|webpackExclude): \/.*\/)|(webpackMode: ["'](lazy|lazy-once|eager|weak)["'])|(webpackExports: (['"]\w+['"]|\[(['"]\w+['"], *)+(['"]\w+['"]*)\]))),?)+ $/;
-    const chunkSubstrFormat = ` webpackChunkName: ["']${webpackChunknameFormat}["'],? `;
+    const chunkSubstrFormat = `webpackChunkName: ["']${webpackChunknameFormat}["'],? `;
     const chunkSubstrRegex = new RegExp(chunkSubstrFormat);
+    const eagerModeFormat = `webpackMode: ["']eager["'],? `;
+    const eagerModeRegex = new RegExp(eagerModeFormat);
 
     function run(node, arg) {
       const sourceCode = context.getSourceCode();
@@ -54,6 +57,7 @@ module.exports = {
       }
 
       let isChunknamePresent = false;
+      let isEagerModePresent = false;
 
       for (const comment of leadingComments) {
         if (comment.type !== 'Block') {
@@ -92,12 +96,55 @@ module.exports = {
           return;
         }
 
+        if (eagerModeRegex.test(comment.value)) {
+          isEagerModePresent = true;
+        }
+
         if (chunkSubstrRegex.test(comment.value)) {
           isChunknamePresent = true;
         }
       }
 
-      if (!isChunknamePresent && !allowEmpty) {
+      if (isChunknamePresent && isEagerModePresent) {
+        context.report({
+          node,
+          message: 'dynamic imports using eager mode do not need a webpackChunkName',
+          suggest: [
+            {
+              desc: 'Remove webpackChunkName',
+              fix(fixer) {
+                for (const comment of leadingComments) {
+                  if (chunkSubstrRegex.test(comment.value)) {
+                    const replacement = comment.value.replace(chunkSubstrRegex, '').trim().replace(/,$/, '');
+                    if (replacement === '') {
+                      return fixer.remove(comment);
+                    } else {
+                      return fixer.replaceText(comment, `/* ${replacement} */`);
+                    }
+                  }
+                }
+              },
+            },
+            {
+              desc: 'Remove webpackMode',
+              fix(fixer) {
+                for (const comment of leadingComments) {
+                  if (eagerModeRegex.test(comment.value)) {
+                    const replacement = comment.value.replace(eagerModeRegex, '').trim().replace(/,$/, '');
+                    if (replacement === '') {
+                      return fixer.remove(comment);
+                    } else {
+                      return fixer.replaceText(comment, `/* ${replacement} */`);
+                    }
+                  }
+                }
+              },
+            },
+          ],
+        });
+      }
+
+      if (!isChunknamePresent && !allowEmpty && !isEagerModePresent) {
         context.report({
           node,
           message:
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index c710507b26..6afd834ab0 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -26,8 +26,9 @@ const nonBlockCommentError = 'dynamic imports require a /* foo */ style comment,
 const noPaddingCommentError = 'dynamic imports require a block comment padded with spaces - /* foo */';
 const invalidSyntaxCommentError = 'dynamic imports require a "webpack" comment with valid syntax';
 const commentFormatError = `dynamic imports require a "webpack" comment with valid syntax`;
-const chunkNameFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${commentFormat}["'],? */`;
-const pickyChunkNameFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${pickyCommentFormat}["'],? */`;
+const chunkNameFormatError = `dynamic imports require a leading comment in the form /*webpackChunkName: ["']${commentFormat}["'],? */`;
+const pickyChunkNameFormatError = `dynamic imports require a leading comment in the form /*webpackChunkName: ["']${pickyCommentFormat}["'],? */`;
+const eagerModeError = `dynamic imports using eager mode do not need a webpackChunkName`;
 
 ruleTester.run('dynamic-import-chunkname', rule, {
   valid: [
@@ -354,7 +355,6 @@ ruleTester.run('dynamic-import-chunkname', rule, {
     },
     {
       code: `import(
-        /* webpackChunkName: "someModule" */
         /* webpackMode: "eager" */
         'someModule'
       )`,
@@ -412,7 +412,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         /* webpackPrefetch: true */
         /* webpackPreload: true */
         /* webpackIgnore: false */
-        /* webpackMode: "eager" */
+        /* webpackMode: "lazy" */
         /* webpackExports: ["default", "named"] */
         'someModule'
       )`,
@@ -981,6 +981,42 @@ ruleTester.run('dynamic-import-chunkname', rule, {
         type: 'CallExpression',
       }],
     },
+    {
+      code: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackMode: "eager" */
+        'someModule'
+      )`,
+      options,
+      parser,
+      output: `import(
+        /* webpackChunkName: "someModule" */
+        /* webpackMode: "eager" */
+        'someModule'
+      )`,
+      errors: [{
+        message: eagerModeError,
+        type: 'CallExpression',
+        suggestions: [
+          {
+            desc: 'Remove webpackChunkName',
+            output: `import(
+        
+        /* webpackMode: "eager" */
+        'someModule'
+      )`,
+          },
+          {
+            desc: 'Remove webpackMode',
+            output: `import(
+        /* webpackChunkName: "someModule" */
+        
+        'someModule'
+      )`,
+          },
+        ],
+      }],
+    },
   ],
 });
 
@@ -1213,15 +1249,6 @@ context('TypeScript', () => {
           options,
           parser: typescriptParser,
         },
-        {
-          code: `import(
-            /* webpackChunkName: "someModule" */
-            /* webpackMode: "lazy" */
-            'someModule'
-          )`,
-          options,
-          parser: typescriptParser,
-        },
         {
           code: `import(
             /* webpackChunkName: 'someModule', webpackMode: 'lazy' */
@@ -1242,7 +1269,7 @@ context('TypeScript', () => {
         {
           code: `import(
             /* webpackChunkName: "someModule" */
-            /* webpackMode: "eager" */
+            /* webpackMode: "lazy" */
             'someModule'
           )`,
           options,
@@ -1299,13 +1326,21 @@ context('TypeScript', () => {
             /* webpackPrefetch: true */
             /* webpackPreload: true */
             /* webpackIgnore: false */
-            /* webpackMode: "eager" */
+            /* webpackMode: "lazy" */
             /* webpackExports: ["default", "named"] */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
         },
+        {
+          code: `import(
+            /* webpackMode: "eager" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+        },
       ],
       invalid: [
         {
@@ -1752,6 +1787,162 @@ context('TypeScript', () => {
             type: nodeType,
           }],
         },
+        {
+          code: `import(
+            /* webpackChunkName: "someModule", webpackMode: "eager" */
+            'someModule'
+          )`,
+          options,
+          parser: typescriptParser,
+          output: `import(
+            /* webpackChunkName: "someModule", webpackMode: "eager" */
+            'someModule'
+          )`,
+          errors: [{
+            message: eagerModeError,
+            type: nodeType,
+            suggestions: [
+              {
+                desc: 'Remove webpackChunkName',
+                output: `import(
+            /* webpackMode: "eager" */
+            'someModule'
+          )`,
+              },
+              {
+                desc: 'Remove webpackMode',
+                output: `import(
+            /* webpackChunkName: "someModule" */
+            'someModule'
+          )`,
+              },
+            ],
+          }],
+        },
+        {
+          code: `
+            import(
+              /* webpackMode: "eager", webpackChunkName: "someModule" */
+              'someModule'
+            )
+          `,
+          options,
+          parser: typescriptParser,
+          output: `
+            import(
+              /* webpackMode: "eager", webpackChunkName: "someModule" */
+              'someModule'
+            )
+          `,
+          errors: [{
+            message: eagerModeError,
+            type: nodeType,
+            suggestions: [
+              {
+                desc: 'Remove webpackChunkName',
+                output: `
+            import(
+              /* webpackMode: "eager" */
+              'someModule'
+            )
+          `,
+              },
+              {
+                desc: 'Remove webpackMode',
+                output: `
+            import(
+              /* webpackChunkName: "someModule" */
+              'someModule'
+            )
+          `,
+              },
+            ],
+          }],
+        },
+        {
+          code: `
+            import(
+              /* webpackMode: "eager", webpackPrefetch: true, webpackChunkName: "someModule" */
+              'someModule'
+            )
+          `,
+          options,
+          parser: typescriptParser,
+          output: `
+            import(
+              /* webpackMode: "eager", webpackPrefetch: true, webpackChunkName: "someModule" */
+              'someModule'
+            )
+          `,
+          errors: [{
+            message: eagerModeError,
+            type: nodeType,
+            suggestions: [
+              {
+                desc: 'Remove webpackChunkName',
+                output: `
+            import(
+              /* webpackMode: "eager", webpackPrefetch: true */
+              'someModule'
+            )
+          `,
+              },
+              {
+                desc: 'Remove webpackMode',
+                output: `
+            import(
+              /* webpackPrefetch: true, webpackChunkName: "someModule" */
+              'someModule'
+            )
+          `,
+              },
+            ],
+          }],
+        },
+        {
+          code: `
+            import(
+              /* webpackChunkName: "someModule" */
+              /* webpackMode: "eager" */
+              'someModule'
+            )
+          `,
+          options,
+          parser: typescriptParser,
+          output: `
+            import(
+              /* webpackChunkName: "someModule" */
+              /* webpackMode: "eager" */
+              'someModule'
+            )
+          `,
+          errors: [{
+            message: eagerModeError,
+            type: nodeType,
+            suggestions: [
+              {
+                desc: 'Remove webpackChunkName',
+                output: `
+            import(
+              ${''}
+              /* webpackMode: "eager" */
+              'someModule'
+            )
+          `,
+              },
+              {
+                desc: 'Remove webpackMode',
+                output: `
+            import(
+              /* webpackChunkName: "someModule" */
+              ${''}
+              'someModule'
+            )
+          `,
+              },
+            ],
+          }],
+        },
       ],
     });
   });

From 6554bd5c30976290024cecc44ef1e96746cf3cf7 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 23 May 2024 12:47:41 -0700
Subject: [PATCH 679/767] [meta] add `repository.directory` field

---
 memo-parser/package.json       | 3 ++-
 resolvers/node/package.json    | 3 ++-
 resolvers/webpack/package.json | 3 ++-
 utils/package.json             | 3 ++-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/memo-parser/package.json b/memo-parser/package.json
index 723005d21b..b89c3c5ada 100644
--- a/memo-parser/package.json
+++ b/memo-parser/package.json
@@ -12,7 +12,8 @@
   },
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/import-js/eslint-plugin-import.git"
+    "url": "git+https://github.com/import-js/eslint-plugin-import.git",
+    "directory": "memo-parser"
   },
   "keywords": [
     "eslint",
diff --git a/resolvers/node/package.json b/resolvers/node/package.json
index bfaab40413..6f6999e6cb 100644
--- a/resolvers/node/package.json
+++ b/resolvers/node/package.json
@@ -13,7 +13,8 @@
   },
   "repository": {
     "type": "git",
-    "url": "https://github.com/import-js/eslint-plugin-import"
+    "url": "https://github.com/import-js/eslint-plugin-import",
+    "directory": "resolvers/node"
   },
   "keywords": [
     "eslint",
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 3fa47d9362..7f8cb718f1 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -14,7 +14,8 @@
   ],
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/import-js/eslint-plugin-import.git"
+    "url": "git+https://github.com/import-js/eslint-plugin-import.git",
+    "directory": "resolvers/webpack"
   },
   "keywords": [
     "eslint-plugin-import",
diff --git a/utils/package.json b/utils/package.json
index df4871790b..4704971505 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -12,7 +12,8 @@
   },
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/import-js/eslint-plugin-import.git"
+    "url": "git+https://github.com/import-js/eslint-plugin-import.git",
+	"directory": "utils"
   },
   "keywords": [
     "eslint-plugin-import",

From fc361a9998b14b9528d841d8349078a5af2da436 Mon Sep 17 00:00:00 2001
From: U812320 <francoisjulien.chabbey@mobi.ch>
Date: Mon, 3 Jun 2024 13:45:31 +0200
Subject: [PATCH 680/767] [Fix] `no-extraneous-dependencies`: allow wrong path

- If you pass only one path to a package.json file, then this path
should be correct
- If you pass multiple paths, there are some situations when those paths
point to a wrong path, this happens typically in a nx monorepo with husky
-- NX will run eslint in the projects folder, so we need to grab the
root package.json
-- Husky will run in the root folder, so one of the path given will be
an incorrect path, but we do not want throw there, otherwise the rull
will fail
---
 CHANGELOG.md                                  |  5 +++++
 src/rules/no-extraneous-dependencies.js       | 17 +++++++++++------
 tests/src/rules/no-extraneous-dependencies.js |  9 +++++++++
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7cd6c4431..941cd6ef87 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`dynamic-import-chunkname`]: add `allowEmpty` option to allow empty leading comments ([#2942], thanks [@JiangWeixian])
 - [`dynamic-import-chunkname`]: Allow empty chunk name when webpackMode: 'eager' is set; add suggestions to remove name in eager mode ([#3004], thanks [@amsardesai])
 
+### Fixed
+- [`no-extraneous-dependencies`]: allow wrong path ([#3012], thanks [@chabb])
+
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
 - [`no-unused-modules`]: add console message to help debug [#2866]
@@ -1116,6 +1119,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
 [#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
 [#2991]: https://github.com/import-js/eslint-plugin-import/pull/2991
 [#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
@@ -1733,6 +1737,7 @@ for info on changes for earlier releases.
 [@bradzacher]: https://github.com/bradzacher
 [@brendo]: https://github.com/brendo
 [@brettz9]: https://github.com/brettz9
+[@chabb]: https://github.com/chabb
 [@Chamion]: https://github.com/Chamion
 [@charlessuh]: https://github.com/charlessuh
 [@charpeni]: https://github.com/charpeni
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index df97987901..0fe42f56f8 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -42,8 +42,11 @@ function extractDepFields(pkg) {
 
 function getPackageDepFields(packageJsonPath, throwAtRead) {
   if (!depFieldCache.has(packageJsonPath)) {
-    const depFields = extractDepFields(readJSON(packageJsonPath, throwAtRead));
-    depFieldCache.set(packageJsonPath, depFields);
+    const packageJson = readJSON(packageJsonPath, throwAtRead);
+    if (packageJson) {
+      const depFields = extractDepFields(packageJson);
+      depFieldCache.set(packageJsonPath, depFields);
+    }
   }
 
   return depFieldCache.get(packageJsonPath);
@@ -72,10 +75,12 @@ function getDependencies(context, packageDir) {
       // use rule config to find package.json
       paths.forEach((dir) => {
         const packageJsonPath = path.join(dir, 'package.json');
-        const _packageContent = getPackageDepFields(packageJsonPath, true);
-        Object.keys(packageContent).forEach((depsKey) => {
-          Object.assign(packageContent[depsKey], _packageContent[depsKey]);
-        });
+        const _packageContent = getPackageDepFields(packageJsonPath, paths.length === 1);
+        if (_packageContent) {
+          Object.keys(packageContent).forEach((depsKey) => {
+            Object.assign(packageContent[depsKey], _packageContent[depsKey]);
+          });
+        }
       });
     } else {
       const packageJsonPath = pkgUp({
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index cb0398ada2..4b221de353 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -26,6 +26,7 @@ const packageDirWithEmpty = path.join(__dirname, '../../files/empty');
 const packageDirBundleDeps = path.join(__dirname, '../../files/bundled-dependencies/as-array-bundle-deps');
 const packageDirBundledDepsAsObject = path.join(__dirname, '../../files/bundled-dependencies/as-object');
 const packageDirBundledDepsRaceCondition = path.join(__dirname, '../../files/bundled-dependencies/race-condition');
+const emptyPackageDir = path.join(__dirname, '../../files/empty-folder');
 
 const {
   dependencies: deps,
@@ -104,6 +105,14 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       code: 'import leftpad from "left-pad";',
       options: [{ packageDir: packageDirMonoRepoRoot }],
     }),
+    test({
+      code: 'import leftpad from "left-pad";',
+      options: [{ packageDir: [emptyPackageDir, packageDirMonoRepoRoot] }],
+    }),
+    test({
+      code: 'import leftpad from "left-pad";',
+      options: [{ packageDir: [packageDirMonoRepoRoot, emptyPackageDir] }],
+    }),
     test({
       code: 'import react from "react";',
       options: [{ packageDir: [packageDirMonoRepoRoot, packageDirMonoRepoWithNested] }],

From 09476d7dac1ab36668283f9626f85e2223652b37 Mon Sep 17 00:00:00 2001
From: silverwind <me@silverwind.io>
Date: Tue, 28 May 2024 22:27:21 +0200
Subject: [PATCH 681/767] [New] `no-unused-modules`: Add
 `ignoreUnusedTypeExports` option

Fixes #2694
---
 CHANGELOG.md                         |  3 ++
 docs/rules/no-unused-modules.md      | 15 ++++++-
 src/rules/no-unused-modules.js       | 35 ++++++++++-----
 tests/src/rules/no-unused-modules.js | 67 ++++++++++++++++++++++++++++
 4 files changed, 106 insertions(+), 14 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 941cd6ef87..b1d2a3425b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
 - [`dynamic-import-chunkname`]: add `allowEmpty` option to allow empty leading comments ([#2942], thanks [@JiangWeixian])
 - [`dynamic-import-chunkname`]: Allow empty chunk name when webpackMode: 'eager' is set; add suggestions to remove name in eager mode ([#3004], thanks [@amsardesai])
+- [`no-unused-modules`]: Add `ignoreUnusedTypeExports` option ([#3011], thanks [@silverwind])
 
 ### Fixed
 - [`no-extraneous-dependencies`]: allow wrong path ([#3012], thanks [@chabb])
@@ -1120,6 +1121,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
+[#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
 [#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
 [#2991]: https://github.com/import-js/eslint-plugin-import/pull/2991
 [#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
@@ -1915,6 +1917,7 @@ for info on changes for earlier releases.
 [@sergei-startsev]: https://github.com/sergei-startsev
 [@sharmilajesupaul]: https://github.com/sharmilajesupaul
 [@sheepsteak]: https://github.com/sheepsteak
+[@silverwind]: https://github.com/silverwind
 [@silviogutierrez]: https://github.com/silviogutierrez
 [@SimenB]: https://github.com/SimenB
 [@simmo]: https://github.com/simmo
diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md
index 53c2479272..359c341ea0 100644
--- a/docs/rules/no-unused-modules.md
+++ b/docs/rules/no-unused-modules.md
@@ -29,8 +29,9 @@ This rule takes the following option:
 
  - **`missingExports`**: if `true`, files without any exports are reported (defaults to `false`)
  - **`unusedExports`**: if `true`, exports without any static usage within other modules are reported (defaults to `false`)
- - `src`: an array with files/paths to be analyzed. It only applies to unused exports. Defaults to `process.cwd()`, if not provided
- - `ignoreExports`: an array with files/paths for which unused exports will not be reported (e.g module entry points in a published package)
+ - **`ignoreUnusedTypeExports`**: if `true`, TypeScript type exports without any static usage within other modules are reported (defaults to `false` and has no effect unless `unusedExports` is `true`)
+ - **`src`**: an array with files/paths to be analyzed. It only applies to unused exports. Defaults to `process.cwd()`, if not provided
+ - **`ignoreExports`**: an array with files/paths for which unused exports will not be reported (e.g module entry points in a published package)
 
 ### Example for missing exports
 
@@ -116,6 +117,16 @@ export function doAnything() {
 export default 5 // will not be reported
 ```
 
+### Unused exports with `ignoreUnusedTypeExports` set to `true`
+
+The following will not be reported:
+
+```ts
+export type Foo = {}; // will not be reported
+export interface Foo = {}; // will not be reported
+export enum Foo {}; // will not be reported
+```
+
 #### Important Note
 
 Exports from files listed as a main file (`main`, `browser`, or `bin` fields in `package.json`) will be ignored by default. This only applies if the `package.json` is not set to `private: true`
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 0ad330b486..46fc93bfe0 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -83,28 +83,30 @@ const DEFAULT = 'default';
 
 function forEachDeclarationIdentifier(declaration, cb) {
   if (declaration) {
+    const isTypeDeclaration = declaration.type === TS_INTERFACE_DECLARATION
+      || declaration.type === TS_TYPE_ALIAS_DECLARATION
+      || declaration.type === TS_ENUM_DECLARATION;
+
     if (
       declaration.type === FUNCTION_DECLARATION
       || declaration.type === CLASS_DECLARATION
-      || declaration.type === TS_INTERFACE_DECLARATION
-      || declaration.type === TS_TYPE_ALIAS_DECLARATION
-      || declaration.type === TS_ENUM_DECLARATION
+      || isTypeDeclaration
     ) {
-      cb(declaration.id.name);
+      cb(declaration.id.name, isTypeDeclaration);
     } else if (declaration.type === VARIABLE_DECLARATION) {
       declaration.declarations.forEach(({ id }) => {
         if (id.type === OBJECT_PATTERN) {
           recursivePatternCapture(id, (pattern) => {
             if (pattern.type === IDENTIFIER) {
-              cb(pattern.name);
+              cb(pattern.name, false);
             }
           });
         } else if (id.type === ARRAY_PATTERN) {
           id.elements.forEach(({ name }) => {
-            cb(name);
+            cb(name, false);
           });
         } else {
-          cb(id.name);
+          cb(id.name, false);
         }
       });
     }
@@ -443,6 +445,10 @@ module.exports = {
           description: 'report exports without any usage',
           type: 'boolean',
         },
+        ignoreUnusedTypeExports: {
+          description: 'ignore type exports without any usage',
+          type: 'boolean',
+        },
       },
       anyOf: [
         {
@@ -470,6 +476,7 @@ module.exports = {
       ignoreExports = [],
       missingExports,
       unusedExports,
+      ignoreUnusedTypeExports,
     } = context.options[0] || {};
 
     if (unusedExports) {
@@ -502,11 +509,15 @@ module.exports = {
       exportCount.set(IMPORT_NAMESPACE_SPECIFIER, namespaceImports);
     };
 
-    const checkUsage = (node, exportedValue) => {
+    const checkUsage = (node, exportedValue, isTypeExport) => {
       if (!unusedExports) {
         return;
       }
 
+      if (isTypeExport && ignoreUnusedTypeExports) {
+        return;
+      }
+
       if (ignoredFiles.has(file)) {
         return;
       }
@@ -935,14 +946,14 @@ module.exports = {
         checkExportPresence(node);
       },
       ExportDefaultDeclaration(node) {
-        checkUsage(node, IMPORT_DEFAULT_SPECIFIER);
+        checkUsage(node, IMPORT_DEFAULT_SPECIFIER, false);
       },
       ExportNamedDeclaration(node) {
         node.specifiers.forEach((specifier) => {
-          checkUsage(specifier, specifier.exported.name || specifier.exported.value);
+          checkUsage(specifier, specifier.exported.name || specifier.exported.value, false);
         });
-        forEachDeclarationIdentifier(node.declaration, (name) => {
-          checkUsage(node, name);
+        forEachDeclarationIdentifier(node.declaration, (name, isTypeExport) => {
+          checkUsage(node, name, isTypeExport);
         });
       },
     };
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index b09d5d759c..80bd70227e 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -38,6 +38,13 @@ const unusedExportsTypescriptOptions = [{
   ignoreExports: undefined,
 }];
 
+const unusedExportsTypescriptIgnoreUnusedTypesOptions = [{
+  unusedExports: true,
+  ignoreUnusedTypeExports: true,
+  src: [testFilePath('./no-unused-modules/typescript')],
+  ignoreExports: undefined,
+}];
+
 const unusedExportsJsxOptions = [{
   unusedExports: true,
   src: [testFilePath('./no-unused-modules/jsx')],
@@ -1209,6 +1216,66 @@ context('TypeScript', function () {
   });
 });
 
+describe('ignoreUnusedTypeExports', () => {
+  getTSParsers().forEach((parser) => {
+    typescriptRuleTester.run('no-unused-modules', rule, {
+      valid: [
+        // unused vars should not report
+        test({
+          options: unusedExportsTypescriptIgnoreUnusedTypesOptions,
+          code: `export interface c {};`,
+          parser,
+          filename: testFilePath(
+            './no-unused-modules/typescript/file-ts-c-unused.ts',
+          ),
+        }),
+        test({
+          options: unusedExportsTypescriptIgnoreUnusedTypesOptions,
+          code: `export type d = {};`,
+          parser,
+          filename: testFilePath(
+            './no-unused-modules/typescript/file-ts-d-unused.ts',
+          ),
+        }),
+        test({
+          options: unusedExportsTypescriptIgnoreUnusedTypesOptions,
+          code: `export enum e { f };`,
+          parser,
+          filename: testFilePath(
+            './no-unused-modules/typescript/file-ts-e-unused.ts',
+          ),
+        }),
+        // used vars should not report
+        test({
+          options: unusedExportsTypescriptIgnoreUnusedTypesOptions,
+          code: `export interface c {};`,
+          parser,
+          filename: testFilePath(
+            './no-unused-modules/typescript/file-ts-c-used-as-type.ts',
+          ),
+        }),
+        test({
+          options: unusedExportsTypescriptIgnoreUnusedTypesOptions,
+          code: `export type d = {};`,
+          parser,
+          filename: testFilePath(
+            './no-unused-modules/typescript/file-ts-d-used-as-type.ts',
+          ),
+        }),
+        test({
+          options: unusedExportsTypescriptIgnoreUnusedTypesOptions,
+          code: `export enum e { f };`,
+          parser,
+          filename: testFilePath(
+            './no-unused-modules/typescript/file-ts-e-used-as-type.ts',
+          ),
+        }),
+      ],
+      invalid: [],
+    });
+  });
+});
+
 describe('correctly work with JSX only files', () => {
   jsxRuleTester.run('no-unused-modules', rule, {
     valid: [

From c387276efac8da06e0d8a4eae06989aa0e6631eb Mon Sep 17 00:00:00 2001
From: Mysak0CZ <michalmpacal@gmail.com>
Date: Fri, 23 Aug 2024 14:01:22 +0200
Subject: [PATCH 682/767] [utils] [fix] `parse`: also delete
 parserOptions.projectService

---
 utils/CHANGELOG.md | 5 +++++
 utils/parse.js     | 1 +
 2 files changed, 6 insertions(+)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 3e2f5a8997..366a834bdb 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -8,6 +8,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [types] use shared config (thanks [@ljharb])
 
+### Fixed
+- `parse`: also delete `parserOptions.projectService` ([#3039], thanks [@Mysak0CZ])
+
 ## v2.8.1 - 2024-02-26
 
 ### Fixed
@@ -142,6 +145,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#3039]: https://github.com/import-js/eslint-plugin-import/pull/3039
 [#2963]: https://github.com/import-js/eslint-plugin-import/pull/2963
 [#2755]: https://github.com/import-js/eslint-plugin-import/pull/2755
 [#2714]: https://github.com/import-js/eslint-plugin-import/pull/2714
@@ -188,6 +192,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@manuth]: https://github.com/manuth
 [@maxkomarychev]: https://github.com/maxkomarychev
 [@mgwalker]: https://github.com/mgwalker
+[@Mysak0CZ]: https://github.com/Mysak0CZ
 [@nicolo-ribaudo]: https://github.com/nicolo-ribaudo
 [@pmcelhaney]: https://github.com/pmcelhaney
 [@sergei-startsev]: https://github.com/sergei-startsev
diff --git a/utils/parse.js b/utils/parse.js
index 94aca1d0f8..75d527b008 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -134,6 +134,7 @@ exports.default = function parse(path, content, context) {
   // only parse one file in isolate mode, which is much, much faster.
   // https://github.com/import-js/eslint-plugin-import/issues/1408#issuecomment-509298962
   delete parserOptions.EXPERIMENTAL_useProjectService;
+  delete parserOptions.projectService;
   delete parserOptions.project;
   delete parserOptions.projects;
 

From bab3a109dce63d0b4fdc4b876dc77f01c34aca4c Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 25 Aug 2024 15:15:43 -0700
Subject: [PATCH 683/767] [utils] [meta] add `exports`, `main`

In theory this should only be breaking if someone is requiring tsconfig.json
---
 utils/CHANGELOG.md |  1 +
 utils/package.json | 34 +++++++++++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 366a834bdb..ac6883b1c4 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Changed
 - [types] use shared config (thanks [@ljharb])
+- [meta] add `exports`, `main`
 
 ### Fixed
 - `parse`: also delete `parserOptions.projectService` ([#3039], thanks [@Mysak0CZ])
diff --git a/utils/package.json b/utils/package.json
index 4704971505..23c8b08e9c 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -5,15 +5,46 @@
   "engines": {
     "node": ">=4"
   },
+  "main": false,
+  "exports": {
+    "./ModuleCache": "./ModuleCache.js",
+    "./ModuleCache.js": "./ModuleCache.js",
+    "./declaredScope": "./declaredScope.js",
+    "./declaredScope.js": "./declaredScope.js",
+    "./hash": "./hash.js",
+    "./hash.js": "./hash.js",
+    "./ignore": "./ignore.js",
+    "./ignore.js": "./ignore.js",
+    "./module-require": "./module-require.js",
+    "./module-require.js": "./module-require.js",
+    "./moduleVisitor": "./moduleVisitor.js",
+    "./moduleVisitor.js": "./moduleVisitor.js",
+    "./parse": "./parse.js",
+    "./parse.js": "./parse.js",
+    "./pkgDir": "./pkgDir.js",
+    "./pkgDir.js": "./pkgDir.js",
+    "./pkgUp": "./pkgUp.js",
+    "./pkgUp.js": "./pkgUp.js",
+    "./readPkgUp": "./readPkgUp.js",
+    "./readPkgUp.js": "./readPkgUp.js",
+    "./resolve": "./resolve.js",
+    "./resolve.js": "./resolve.js",
+    "./unambiguous": "./unambiguous.js",
+    "./unambiguous.js": "./unambiguous.js",
+    "./visit": "./visit.js",
+    "./visit.js": "./visit.js",
+    "./package.json": "./package.json"
+  },
   "scripts": {
     "prepublishOnly": "cp ../{LICENSE,.npmrc} ./",
     "tsc": "tsc -p .",
+    "posttsc": "attw -P .",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "repository": {
     "type": "git",
     "url": "git+https://github.com/import-js/eslint-plugin-import.git",
-	"directory": "utils"
+    "directory": "utils"
   },
   "keywords": [
     "eslint-plugin-import",
@@ -31,6 +62,7 @@
     "debug": "^3.2.7"
   },
   "devDependencies": {
+    "@arethetypeswrong/cli": "^0.15.4",
     "@ljharb/tsconfig": "^0.2.0",
     "@types/debug": "^4.1.12",
     "@types/eslint": "^8.56.3",

From 9b1a3b96caa656fe94bda709c364c7e230028432 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 25 Aug 2024 16:22:22 -0700
Subject: [PATCH 684/767] [utils] v2.8.2

---
 utils/CHANGELOG.md | 10 +++++++---
 utils/package.json |  2 +-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index ac6883b1c4..43bd0e022b 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,13 +5,17 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
-### Changed
-- [types] use shared config (thanks [@ljharb])
-- [meta] add `exports`, `main`
+## v2.8.2 - 2024-08-25
 
 ### Fixed
 - `parse`: also delete `parserOptions.projectService` ([#3039], thanks [@Mysak0CZ])
 
+### Changed
+- [types] use shared config (thanks [@ljharb])
+- [meta] add `exports`, `main`
+- [meta] add `repository.directory` field
+- [refactor] avoid hoisting
+
 ## v2.8.1 - 2024-02-26
 
 ### Fixed
diff --git a/utils/package.json b/utils/package.json
index 23c8b08e9c..6d69e2414a 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.8.1",
+  "version": "2.8.2",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From bdff75d51fc73895f9e1697a02765daf12815714 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Sun, 25 Aug 2024 19:00:48 -0700
Subject: [PATCH 685/767] [Deps] update `array-includes`,
 `array.prototype.findlastindex`, `eslint-module-utils`, `hasown`,
 `is-core-module`, `object.fromentries`, `object.groupby`, `object.values`

---
 package.json | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/package.json b/package.json
index b9fa1eb35f..de0055a09a 100644
--- a/package.json
+++ b/package.json
@@ -105,21 +105,21 @@
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
   },
   "dependencies": {
-    "array-includes": "^3.1.7",
-    "array.prototype.findlastindex": "^1.2.4",
+    "array-includes": "^3.1.8",
+    "array.prototype.findlastindex": "^1.2.5",
     "array.prototype.flat": "^1.3.2",
     "array.prototype.flatmap": "^1.3.2",
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
-    "eslint-module-utils": "^2.8.0",
-    "hasown": "^2.0.1",
-    "is-core-module": "^2.13.1",
+    "eslint-module-utils": "^2.8.2",
+    "hasown": "^2.0.2",
+    "is-core-module": "^2.15.1",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
-    "object.fromentries": "^2.0.7",
-    "object.groupby": "^1.0.2",
-    "object.values": "^1.1.7",
+    "object.fromentries": "^2.0.8",
+    "object.groupby": "^1.0.3",
+    "object.values": "^1.2.0",
     "semver": "^6.3.1",
     "tsconfig-paths": "^3.15.0"
   }

From db8b95d7a5768c0ccd372b6b5228287a182c7679 Mon Sep 17 00:00:00 2001
From: Federico Brigante <me@fregante.com>
Date: Sun, 14 Jul 2024 13:45:26 +0000
Subject: [PATCH 686/767] [resolvers/webpack] [refactor] simplify loop

---
 resolvers/webpack/CHANGELOG.md |  5 ++++-
 resolvers/webpack/index.js     | 31 ++++++++++++++++++-------------
 resolvers/webpack/package.json |  1 -
 3 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 4fed046b46..cd49cc3f4e 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,11 +5,12 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+- [refactor] simplify loop ([#3029], thanks [@fregante])
+
 ## 0.13.8 - 2023-10-22
  - [refactor] use `hasown` instead of `has`
  - [deps] update `array.prototype.find`, `is-core-module`, `resolve`
 
-
 ## 0.13.7 - 2023-08-19
  - [fix] use the `dirname` of the `configPath` as `basedir` ([#2859])
 
@@ -178,6 +179,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
  - `interpret` configs (such as `.babel.js`). Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
+[#3029]: https://github.com/import-js/eslint-plugin-import/pull/3029
 [#2287]: https://github.com/import-js/eslint-plugin-import/pull/2287
 [#2023]: https://github.com/import-js/eslint-plugin-import/pull/2023
 [#1967]: https://github.com/import-js/eslint-plugin-import/pull/1967
@@ -222,6 +224,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 [@benmvp]: https://github.com/benmvp
 [@daltones]: https://github.com/daltones
 [@echenley]: https://github.com/echenley
+[@fregante]: https://github.com/fregante
 [@gausie]: https://github.com/gausie
 [@grahamb]: https://github.com/grahamb
 [@graingert]: https://github.com/graingert
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index da16eda593..eabe3cf338 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -3,7 +3,6 @@
 const findRoot = require('find-root');
 const path = require('path');
 const isEqual = require('lodash/isEqual');
-const find = require('array.prototype.find');
 const interpret = require('interpret');
 const fs = require('fs');
 const isCore = require('is-core-module');
@@ -293,17 +292,20 @@ const MAX_CACHE = 10;
 const _cache = [];
 function getResolveSync(configPath, webpackConfig, cwd) {
   const cacheKey = { configPath, webpackConfig };
-  let cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
-  if (!cached) {
-    cached = {
-      key: cacheKey,
-      value: createResolveSync(configPath, webpackConfig, cwd),
-    };
-    // put in front and pop last item
-    if (_cache.unshift(cached) > MAX_CACHE) {
-      _cache.pop();
+  for (let i = 0; i < _cache.length; i++) {
+    if (isEqual(_cache[i].key, cacheKey)) {
+      return _cache[i].value;
     }
   }
+
+  const cached = {
+    key: cacheKey,
+    value: createResolveSync(configPath, webpackConfig, cwd),
+  };
+  // put in front and pop last item
+  if (_cache.unshift(cached) > MAX_CACHE) {
+    _cache.pop();
+  }
   return cached.value;
 }
 
@@ -409,9 +411,12 @@ exports.resolve = function (source, file, settings) {
     if (typeof configIndex !== 'undefined' && webpackConfig.length > configIndex) {
       webpackConfig = webpackConfig[configIndex];
     } else {
-      webpackConfig = find(webpackConfig, function findFirstWithResolve(config) {
-        return !!config.resolve;
-      });
+      for (let i = 0; i < webpackConfig.length; i++) {
+        if (webpackConfig[i].resolve) {
+          webpackConfig = webpackConfig[i];
+          break;
+        }
+      }
     }
   }
 
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 7f8cb718f1..38465bcdee 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -31,7 +31,6 @@
   },
   "homepage": "https://github.com/import-js/eslint-plugin-import/tree/HEAD/resolvers/webpack",
   "dependencies": {
-    "array.prototype.find": "^2.2.2",
     "debug": "^3.2.7",
     "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",

From 19dbc33ecf09c774db35f362b05caaec027d2e18 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 26 Aug 2024 15:23:07 -0700
Subject: [PATCH 687/767] [resolvers/webpack] [refactor] misc cleanup

---
 resolvers/webpack/index.js | 66 ++++++++++++++++++++------------------
 1 file changed, 34 insertions(+), 32 deletions(-)

diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index eabe3cf338..83297cd185 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -4,12 +4,15 @@ const findRoot = require('find-root');
 const path = require('path');
 const isEqual = require('lodash/isEqual');
 const interpret = require('interpret');
-const fs = require('fs');
+const existsSync = require('fs').existsSync;
 const isCore = require('is-core-module');
 const resolve = require('resolve/sync');
 const semver = require('semver');
 const hasOwn = require('hasown');
 const isRegex = require('is-regex');
+const isArray = Array.isArray;
+const keys = Object.keys;
+const assign = Object.assign;
 
 const log = require('debug')('eslint-plugin-import:resolver:webpack');
 
@@ -19,7 +22,7 @@ function registerCompiler(moduleDescriptor) {
   if (moduleDescriptor) {
     if (typeof moduleDescriptor === 'string') {
       require(moduleDescriptor);
-    } else if (!Array.isArray(moduleDescriptor)) {
+    } else if (!isArray(moduleDescriptor)) {
       moduleDescriptor.register(require(moduleDescriptor.module));
     } else {
       for (let i = 0; i < moduleDescriptor.length; i++) {
@@ -35,42 +38,34 @@ function registerCompiler(moduleDescriptor) {
 }
 
 function findConfigPath(configPath, packageDir) {
-  const extensions = Object.keys(interpret.extensions).sort(function (a, b) {
+  const extensions = keys(interpret.extensions).sort(function (a, b) {
     return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length;
   });
   let extension;
 
   if (configPath) {
-    // extensions is not reused below, so safe to mutate it here.
-    extensions.reverse();
-    extensions.forEach(function (maybeExtension) {
-      if (extension) {
-        return;
-      }
-
-      if (configPath.substr(-maybeExtension.length) === maybeExtension) {
+    for (let i = extensions.length - 1; i >= 0 && !extension; i--) {
+      const maybeExtension = extensions[i];
+      if (configPath.slice(-maybeExtension.length) === maybeExtension) {
         extension = maybeExtension;
       }
-    });
+    }
 
     // see if we've got an absolute path
     if (!path.isAbsolute(configPath)) {
       configPath = path.join(packageDir, configPath);
     }
   } else {
-    extensions.forEach(function (maybeExtension) {
-      if (extension) {
-        return;
-      }
-
+    for (let i = 0; i < extensions.length && !extension; i++) {
+      const maybeExtension = extensions[i];
       const maybePath = path.resolve(
         path.join(packageDir, 'webpack.config' + maybeExtension)
       );
-      if (fs.existsSync(maybePath)) {
+      if (existsSync(maybePath)) {
         configPath = maybePath;
         extension = maybeExtension;
       }
-    });
+    }
   }
 
   registerCompiler(interpret.extensions[extension]);
@@ -84,7 +79,7 @@ function findExternal(source, externals, context, resolveSync) {
   if (typeof externals === 'string') { return source === externals; }
 
   // array: recurse
-  if (Array.isArray(externals)) {
+  if (isArray(externals)) {
     return externals.some(function (e) { return findExternal(source, e, context, resolveSync); });
   }
 
@@ -138,8 +133,9 @@ function findExternal(source, externals, context, resolveSync) {
 
   // else, vanilla object
   for (const key in externals) {
-    if (!hasOwn(externals, key)) { continue; }
-    if (source === key) { return true; }
+    if (hasOwn(externals, key) && source === key) {
+      return true;
+    }
   }
   return false;
 }
@@ -160,15 +156,20 @@ const webpack2DefaultResolveConfig = {
 function createWebpack2ResolveSync(webpackRequire, resolveConfig) {
   const EnhancedResolve = webpackRequire('enhanced-resolve');
 
-  return EnhancedResolve.create.sync(Object.assign({}, webpack2DefaultResolveConfig, resolveConfig));
+  return EnhancedResolve.create.sync(assign({}, webpack2DefaultResolveConfig, resolveConfig));
 }
 
 /**
  * webpack 1 defaults: https://webpack.github.io/docs/configuration.html#resolve-packagemains
- * @type {Array}
+ * @type {string[]}
  */
 const webpack1DefaultMains = [
-  'webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main',
+  'webpack',
+  'browser',
+  'web',
+  'browserify',
+  ['jam', 'main'],
+  'main',
 ];
 
 /* eslint-disable */
@@ -176,8 +177,9 @@ const webpack1DefaultMains = [
 function makeRootPlugin(ModulesInRootPlugin, name, root) {
   if (typeof root === 'string') {
     return new ModulesInRootPlugin(name, root);
-  } else if (Array.isArray(root)) {
-    return function() {
+  }
+  if (isArray(root)) {
+    return function () {
       root.forEach(function (root) {
         this.apply(new ModulesInRootPlugin(name, root));
       }, this);
@@ -236,7 +238,7 @@ function createWebpack1ResolveSync(webpackRequire, resolveConfig, plugins) {
       if (
         plugin.constructor
         && plugin.constructor.name === 'ResolverPlugin'
-        && Array.isArray(plugin.plugins)
+        && isArray(plugin.plugins)
       ) {
         resolvePlugins.push.apply(resolvePlugins, plugin.plugins);
       }
@@ -313,9 +315,9 @@ function getResolveSync(configPath, webpackConfig, cwd) {
  * Find the full path to 'source', given 'file' as a full reference path.
  *
  * resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js'
- * @param  {string} source - the module to resolve; i.e './some-module'
- * @param  {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js'
- * @param  {object} settings - the webpack config file name, as well as cwd
+ * @param {string} source - the module to resolve; i.e './some-module'
+ * @param {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js'
+ * @param {object} settings - the webpack config file name, as well as cwd
  * @example
  * options: {
  *  // Path to the webpack config
@@ -399,7 +401,7 @@ exports.resolve = function (source, file, settings) {
     webpackConfig = webpackConfig(env, argv);
   }
 
-  if (Array.isArray(webpackConfig)) {
+  if (isArray(webpackConfig)) {
     webpackConfig = webpackConfig.map((cfg) => {
       if (typeof cfg === 'function') {
         return cfg(env, argv);

From 98a0991aa248216fb904cc88d11aa9070ccb6249 Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Mon, 8 Apr 2024 20:50:56 +0300
Subject: [PATCH 688/767] [New] [Refactor] `no-cycle`: use scc algorithm to
 optimize; add `skipErrorMessagePath` for faster error messages

---
 CHANGELOG.md                |   2 +
 package.json                |   1 +
 src/rules/no-cycle.js       |  21 +++++
 src/scc.js                  |  86 +++++++++++++++++
 tests/src/rules/no-cycle.js |  28 +++++-
 tests/src/scc.js            | 179 ++++++++++++++++++++++++++++++++++++
 6 files changed, 316 insertions(+), 1 deletion(-)
 create mode 100644 src/scc.js
 create mode 100644 tests/src/scc.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1d2a3425b..0ba781c235 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - [`no-extraneous-dependencies`]: allow wrong path ([#3012], thanks [@chabb])
+- [`no-cycle`]: use scc algorithm to optimize ([#2998], thanks [@soryy708])
 
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
@@ -1123,6 +1124,7 @@ for info on changes for earlier releases.
 [#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
 [#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
 [#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
+[#2998]: https://github.com/import-js/eslint-plugin-import/pull/2998
 [#2991]: https://github.com/import-js/eslint-plugin-import/pull/2991
 [#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
 [#2987]: https://github.com/import-js/eslint-plugin-import/pull/2987
diff --git a/package.json b/package.json
index de0055a09a..2aaa786538 100644
--- a/package.json
+++ b/package.json
@@ -105,6 +105,7 @@
     "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
   },
   "dependencies": {
+    "@rtsao/scc": "^1.1.0",
     "array-includes": "^3.1.8",
     "array.prototype.findlastindex": "^1.2.5",
     "array.prototype.flat": "^1.3.2",
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index e65ff11a49..be8c288dd4 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -5,6 +5,7 @@
 
 import resolve from 'eslint-module-utils/resolve';
 import ExportMapBuilder from '../exportMap/builder';
+import StronglyConnectedComponentsBuilder from '../scc';
 import { isExternalModule } from '../core/importType';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
@@ -47,6 +48,11 @@ module.exports = {
         type: 'boolean',
         default: false,
       },
+      disableScc: {
+        description: 'When true, don\'t calculate a strongly-connected-components graph. SCC is used to reduce the time-complexity of cycle detection, but adds overhead.',
+        type: 'boolean',
+        default: false,
+      },
     })],
   },
 
@@ -62,6 +68,8 @@ module.exports = {
       context,
     );
 
+    const scc = options.disableScc ? {} : StronglyConnectedComponentsBuilder.get(myPath, context);
+
     function checkSourceValue(sourceNode, importer) {
       if (ignoreModule(sourceNode.value)) {
         return; // ignore external modules
@@ -98,6 +106,16 @@ module.exports = {
         return;  // no-self-import territory
       }
 
+      /* If we're in the same Strongly Connected Component,
+       * Then there exists a path from each node in the SCC to every other node in the SCC,
+       * Then there exists at least one path from them to us and from us to them,
+       * Then we have a cycle between us.
+       */
+      const hasDependencyCycle = options.disableScc || scc[myPath] === scc[imported.path];
+      if (!hasDependencyCycle) {
+        return;
+      }
+
       const untraversed = [{ mget: () => imported, route: [] }];
       function detectCycle({ mget, route }) {
         const m = mget();
@@ -106,6 +124,9 @@ module.exports = {
         traversed.add(m.path);
 
         for (const [path, { getter, declarations }] of m.imports) {
+          // If we're in different SCCs, we can't have a circular dependency
+          if (!options.disableScc && scc[myPath] !== scc[path]) { continue; }
+
           if (traversed.has(path)) { continue; }
           const toTraverse = [...declarations].filter(({ source, isOnlyImportingTypes }) => !ignoreModule(source.value)
             // Ignore only type imports
diff --git a/src/scc.js b/src/scc.js
new file mode 100644
index 0000000000..44c818bbe1
--- /dev/null
+++ b/src/scc.js
@@ -0,0 +1,86 @@
+import calculateScc from '@rtsao/scc';
+import { hashObject } from 'eslint-module-utils/hash';
+import resolve from 'eslint-module-utils/resolve';
+import ExportMapBuilder from './exportMap/builder';
+import childContext from './exportMap/childContext';
+
+let cache = new Map();
+
+export default class StronglyConnectedComponentsBuilder {
+  static clearCache() {
+    cache = new Map();
+  }
+
+  static get(source, context) {
+    const path = resolve(source, context);
+    if (path == null) { return null; }
+    return StronglyConnectedComponentsBuilder.for(childContext(path, context));
+  }
+
+  static for(context) {
+    const cacheKey = context.cacheKey || hashObject(context).digest('hex');
+    if (cache.has(cacheKey)) {
+      return cache.get(cacheKey);
+    }
+    const scc = StronglyConnectedComponentsBuilder.calculate(context);
+    cache.set(cacheKey, scc);
+    return scc;
+  }
+
+  static calculate(context) {
+    const exportMap = ExportMapBuilder.for(context);
+    const adjacencyList = this.exportMapToAdjacencyList(exportMap);
+    const calculatedScc = calculateScc(adjacencyList);
+    return StronglyConnectedComponentsBuilder.calculatedSccToPlainObject(calculatedScc);
+  }
+
+  /** @returns {Map<string, Set<string>>} for each dep, what are its direct deps */
+  static exportMapToAdjacencyList(initialExportMap) {
+    const adjacencyList = new Map();
+    // BFS
+    function visitNode(exportMap) {
+      if (!exportMap) {
+        return;
+      }
+      exportMap.imports.forEach((v, importedPath) => {
+        const from = exportMap.path;
+        const to = importedPath;
+
+        // Ignore type-only imports, because we care only about SCCs of value imports
+        const toTraverse = [...v.declarations].filter(({ isOnlyImportingTypes }) => !isOnlyImportingTypes);
+        if (toTraverse.length === 0) { return; }
+
+        if (!adjacencyList.has(from)) {
+          adjacencyList.set(from, new Set());
+        }
+
+        if (adjacencyList.get(from).has(to)) {
+          return; // prevent endless loop
+        }
+        adjacencyList.get(from).add(to);
+        visitNode(v.getter());
+      });
+    }
+    visitNode(initialExportMap);
+    // Fill gaps
+    adjacencyList.forEach((values) => {
+      values.forEach((value) => {
+        if (!adjacencyList.has(value)) {
+          adjacencyList.set(value, new Set());
+        }
+      });
+    });
+    return adjacencyList;
+  }
+
+  /** @returns {Record<string, number>} for each key, its SCC's index */
+  static calculatedSccToPlainObject(sccs) {
+    const obj = {};
+    sccs.forEach((scc, index) => {
+      scc.forEach((node) => {
+        obj[node] = index;
+      });
+    });
+    return obj;
+  }
+}
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index d2adbf61f9..efc0fb6eb9 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -17,7 +17,7 @@ const testVersion = (specifier, t) => _testVersion(specifier, () => Object.assig
 
 const testDialects = ['es6'];
 
-ruleTester.run('no-cycle', rule, {
+const cases = {
   valid: [].concat(
     // this rule doesn't care if the cycle length is 0
     test({ code: 'import foo from "./foo.js"' }),
@@ -290,4 +290,30 @@ ruleTester.run('no-cycle', rule, {
       ],
     }),
   ),
+};
+
+ruleTester.run('no-cycle', rule, {
+  valid: flatMap(cases.valid, (testCase) => [
+    testCase,
+    {
+      ...testCase,
+      code: `${testCase.code} // disableScc=true`,
+      options: [{
+        ...testCase.options && testCase.options[0] || {},
+        disableScc: true,
+      }],
+    },
+  ]),
+
+  invalid: flatMap(cases.invalid, (testCase) => [
+    testCase,
+    {
+      ...testCase,
+      code: `${testCase.code} // disableScc=true`,
+      options: [{
+        ...testCase.options && testCase.options[0] || {},
+        disableScc: true,
+      }],
+    },
+  ]),
 });
diff --git a/tests/src/scc.js b/tests/src/scc.js
new file mode 100644
index 0000000000..376b783ce1
--- /dev/null
+++ b/tests/src/scc.js
@@ -0,0 +1,179 @@
+import sinon from 'sinon';
+import { expect } from 'chai';
+import StronglyConnectedComponentsBuilder from '../../src/scc';
+import ExportMapBuilder from '../../src/exportMap/builder';
+
+function exportMapFixtureBuilder(path, imports, isOnlyImportingTypes = false) {
+  return {
+    path,
+    imports: new Map(imports.map((imp) => [imp.path, { getter: () => imp, declarations: [{ isOnlyImportingTypes }] }])),
+  };
+}
+
+describe('Strongly Connected Components Builder', () => {
+  afterEach(() => ExportMapBuilder.for.restore());
+  afterEach(() => StronglyConnectedComponentsBuilder.clearCache());
+
+  describe('When getting an SCC', () => {
+    const source = '';
+    const context = {
+      settings: {},
+      parserOptions: {},
+      parserPath: '',
+    };
+
+    describe('Given two files', () => {
+      describe('When they don\'t value-cycle', () => {
+        it('Should return foreign SCCs', () => {
+          sinon.stub(ExportMapBuilder, 'for').returns(
+            exportMapFixtureBuilder('foo.js', [exportMapFixtureBuilder('bar.js', [])]),
+          );
+          const actual = StronglyConnectedComponentsBuilder.for(source, context);
+          expect(actual).to.deep.equal({ 'foo.js': 1, 'bar.js': 0 });
+        });
+      });
+
+      describe('When they do value-cycle', () => {
+        it('Should return same SCC', () => {
+          sinon.stub(ExportMapBuilder, 'for').returns(
+            exportMapFixtureBuilder('foo.js', [
+              exportMapFixtureBuilder('bar.js', [
+                exportMapFixtureBuilder('foo.js', [exportMapFixtureBuilder('bar.js', [])]),
+              ]),
+            ]),
+          );
+          const actual = StronglyConnectedComponentsBuilder.for(source, context);
+          expect(actual).to.deep.equal({ 'foo.js': 0, 'bar.js': 0 });
+        });
+      });
+
+      describe('When they type-cycle', () => {
+        it('Should return foreign SCCs', () => {
+          sinon.stub(ExportMapBuilder, 'for').returns(
+            exportMapFixtureBuilder('foo.js', [
+              exportMapFixtureBuilder('bar.js', [
+                exportMapFixtureBuilder('foo.js', []),
+              ], true),
+            ]),
+          );
+          const actual = StronglyConnectedComponentsBuilder.for(source, context);
+          expect(actual).to.deep.equal({ 'foo.js': 1, 'bar.js': 0 });
+        });
+      });
+    });
+
+    describe('Given three files', () => {
+      describe('When they form a line', () => {
+        describe('When A -> B -> C', () => {
+          it('Should return foreign SCCs', () => {
+            sinon.stub(ExportMapBuilder, 'for').returns(
+              exportMapFixtureBuilder('foo.js', [
+                exportMapFixtureBuilder('bar.js', [
+                  exportMapFixtureBuilder('buzz.js', []),
+                ]),
+              ]),
+            );
+            const actual = StronglyConnectedComponentsBuilder.for(source, context);
+            expect(actual).to.deep.equal({ 'foo.js': 2, 'bar.js': 1, 'buzz.js': 0 });
+          });
+        });
+
+        describe('When A -> B <-> C', () => {
+          it('Should return 2 SCCs, A on its own', () => {
+            sinon.stub(ExportMapBuilder, 'for').returns(
+              exportMapFixtureBuilder('foo.js', [
+                exportMapFixtureBuilder('bar.js', [
+                  exportMapFixtureBuilder('buzz.js', [
+                    exportMapFixtureBuilder('bar.js', []),
+                  ]),
+                ]),
+              ]),
+            );
+            const actual = StronglyConnectedComponentsBuilder.for(source, context);
+            expect(actual).to.deep.equal({ 'foo.js': 1, 'bar.js': 0, 'buzz.js': 0 });
+          });
+        });
+
+        describe('When A <-> B -> C', () => {
+          it('Should return 2 SCCs, C on its own', () => {
+            sinon.stub(ExportMapBuilder, 'for').returns(
+              exportMapFixtureBuilder('foo.js', [
+                exportMapFixtureBuilder('bar.js', [
+                  exportMapFixtureBuilder('buzz.js', []),
+                  exportMapFixtureBuilder('foo.js', []),
+                ]),
+              ]),
+            );
+            const actual = StronglyConnectedComponentsBuilder.for(source, context);
+            expect(actual).to.deep.equal({ 'foo.js': 1, 'bar.js': 1, 'buzz.js': 0 });
+          });
+        });
+
+        describe('When A <-> B <-> C', () => {
+          it('Should return same SCC', () => {
+            sinon.stub(ExportMapBuilder, 'for').returns(
+              exportMapFixtureBuilder('foo.js', [
+                exportMapFixtureBuilder('bar.js', [
+                  exportMapFixtureBuilder('foo.js', []),
+                  exportMapFixtureBuilder('buzz.js', [
+                    exportMapFixtureBuilder('bar.js', []),
+                  ]),
+                ]),
+              ]),
+            );
+            const actual = StronglyConnectedComponentsBuilder.for(source, context);
+            expect(actual).to.deep.equal({ 'foo.js': 0, 'bar.js': 0, 'buzz.js': 0 });
+          });
+        });
+      });
+
+      describe('When they form a loop', () => {
+        it('Should return same SCC', () => {
+          sinon.stub(ExportMapBuilder, 'for').returns(
+            exportMapFixtureBuilder('foo.js', [
+              exportMapFixtureBuilder('bar.js', [
+                exportMapFixtureBuilder('buzz.js', [
+                  exportMapFixtureBuilder('foo.js', []),
+                ]),
+              ]),
+            ]),
+          );
+          const actual = StronglyConnectedComponentsBuilder.for(source, context);
+          expect(actual).to.deep.equal({ 'foo.js': 0, 'bar.js': 0, 'buzz.js': 0 });
+        });
+      });
+
+      describe('When they form a Y', () => {
+        it('Should return 3 distinct SCCs', () => {
+          sinon.stub(ExportMapBuilder, 'for').returns(
+            exportMapFixtureBuilder('foo.js', [
+              exportMapFixtureBuilder('bar.js', []),
+              exportMapFixtureBuilder('buzz.js', []),
+            ]),
+          );
+          const actual = StronglyConnectedComponentsBuilder.for(source, context);
+          expect(actual).to.deep.equal({ 'foo.js': 2, 'bar.js': 0, 'buzz.js': 1 });
+        });
+      });
+
+      describe('When they form a Mercedes', () => {
+        it('Should return 1 SCC', () => {
+          sinon.stub(ExportMapBuilder, 'for').returns(
+            exportMapFixtureBuilder('foo.js', [
+              exportMapFixtureBuilder('bar.js', [
+                exportMapFixtureBuilder('foo.js', []),
+                exportMapFixtureBuilder('buzz.js', []),
+              ]),
+              exportMapFixtureBuilder('buzz.js', [
+                exportMapFixtureBuilder('foo.js', []),
+                exportMapFixtureBuilder('bar.js', []),
+              ]),
+            ]),
+          );
+          const actual = StronglyConnectedComponentsBuilder.for(source, context);
+          expect(actual).to.deep.equal({ 'foo.js': 0, 'bar.js': 0, 'buzz.js': 0 });
+        });
+      });
+    });
+  });
+});

From 4bdf61af182dc1793e229d6f0da2a0e7472f86e6 Mon Sep 17 00:00:00 2001
From: yesl-kim <yesl00k624@gmail.com>
Date: Sun, 11 Aug 2024 17:34:29 +0900
Subject: [PATCH 689/767] [Fix] `no-duplicates`: Removing duplicates breaks in
 TypeScript

Fixes #3016. Fixes #2792.
---
 CHANGELOG.md                     |  3 +++
 src/rules/no-duplicates.js       | 16 ++++++++++++++--
 tests/src/rules/no-duplicates.js | 18 ++++++++++++++++++
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ba781c235..667d9fffb3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [`no-extraneous-dependencies`]: allow wrong path ([#3012], thanks [@chabb])
 - [`no-cycle`]: use scc algorithm to optimize ([#2998], thanks [@soryy708])
+- [`no-duplicates`]: Removing duplicates breaks in TypeScript ([#3033], thanks [@yesl-kim])
 
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
@@ -1121,6 +1122,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3033]: https://github.com/import-js/eslint-plugin-import/pull/3033
 [#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
 [#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
 [#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
@@ -1962,6 +1964,7 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xM8WVqaG]: https://github.com/xM8WVqaG
 [@xpl]: https://github.com/xpl
+[@yesl-kim]: https://github.com/yesl-kim
 [@yndajas]: https://github.com/yndajas
 [@yordis]: https://github.com/yordis
 [@Zamiell]: https://github.com/Zamiell
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 033e854e03..d9fb1a1309 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -132,6 +132,7 @@ function getFix(first, rest, sourceCode, context) {
   const shouldAddDefault = getDefaultImportName(first) == null && defaultImportNames.size === 1;
   const shouldAddSpecifiers = specifiers.length > 0;
   const shouldRemoveUnnecessary = unnecessaryImports.length > 0;
+  const preferInline = context.options[0] && context.options[0]['prefer-inline'];
 
   if (!(shouldAddDefault || shouldAddSpecifiers || shouldRemoveUnnecessary)) {
     return undefined;
@@ -157,8 +158,7 @@ function getFix(first, rest, sourceCode, context) {
       ([result, needsComma, existingIdentifiers], specifier) => {
         const isTypeSpecifier = specifier.importNode.importKind === 'type';
 
-        const preferInline = context.options[0] && context.options[0]['prefer-inline'];
-        // a user might set prefer-inline but not have a supporting TypeScript version.  Flow does not support inline types so this should fail in that case as well.
+        // a user might set prefer-inline but not have a supporting TypeScript version. Flow does not support inline types so this should fail in that case as well.
         if (preferInline && (!typescriptPkg || !semver.satisfies(typescriptPkg.version, '>= 4.5'))) {
           throw new Error('Your version of TypeScript does not support inline type imports.');
         }
@@ -186,6 +186,18 @@ function getFix(first, rest, sourceCode, context) {
 
     const fixes = [];
 
+    if (shouldAddSpecifiers && preferInline && first.importKind === 'type') {
+      // `import type {a} from './foo'` → `import {type a} from './foo'`
+      const typeIdentifierToken = tokens.find((token) => token.type === 'Identifier' && token.value === 'type');
+      fixes.push(fixer.removeRange([typeIdentifierToken.range[0], typeIdentifierToken.range[1] + 1]));
+
+      tokens
+        .filter((token) => firstExistingIdentifiers.has(token.value))
+        .forEach((identifier) => {
+          fixes.push(fixer.replaceTextRange([identifier.range[0], identifier.range[1]], `type ${identifier.value}`));
+        });
+    }
+
     if (shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
       // `import './foo'` → `import def, {...} from './foo'`
       fixes.push(
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index f83221105a..e682f22354 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -704,6 +704,24 @@ context('TypeScript', function () {
             },
           ],
         }),
+        test({
+          code: "import type {x} from 'foo'; import {type y} from 'foo'",
+          ...parserConfig,
+          options: [{ 'prefer-inline': true }],
+          output: `import {type x,type y} from 'foo'; `,
+          errors: [
+            {
+              line: 1,
+              column: 22,
+              message: "'foo' imported multiple times.",
+            },
+            {
+              line: 1,
+              column: 50,
+              message: "'foo' imported multiple times.",
+            },
+          ],
+        }),
         test({
           code: "import {type x} from 'foo'; import type {y} from 'foo'",
           ...parserConfig,

From 6407c1ce2ad16f6116bd8927fc4ba1d2fef56880 Mon Sep 17 00:00:00 2001
From: Bryan Lee <38807139+liby@users.noreply.github.com>
Date: Tue, 28 Sep 2021 11:26:25 +0800
Subject: [PATCH 690/767] [Docs] `order`: update the description of the
 `pathGroupsExcludedImportTypes` option

---
 CHANGELOG.md        |  2 ++
 docs/rules/order.md | 26 ++------------------------
 2 files changed, 4 insertions(+), 24 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 667d9fffb3..7752473019 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [actions] migrate OSX tests to GHA ([ljharb#37], thanks [@aks-])
 - [Refactor] `exportMapBuilder`: avoid hoisting ([#2989], thanks [@soryy708])
 - [Refactor] `ExportMap`: extract "builder" logic to separate files ([#2991], thanks [@soryy708])
+- [Docs] [`order`]: update the description of the `pathGroupsExcludedImportTypes` option ([#3036], thanks [@liby])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1122,6 +1123,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
 [#3033]: https://github.com/import-js/eslint-plugin-import/pull/3033
 [#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
 [#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 24692f2d21..67849bb7ed 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -193,7 +193,7 @@ Example:
 ### `pathGroupsExcludedImportTypes: [array]`
 
 This defines import types that are not handled by configured pathGroups.
-This is mostly needed when you want to handle path groups that look like external imports.
+If you have added path groups with patterns that look like `"builtin"` or `"external"` imports, you have to remove this group (`"builtin"` and/or `"external"`) from the default exclusion list (e.g., `["builtin", "external", "object"]`, etc) to sort these path groups correctly.
 
 Example:
 
@@ -212,29 +212,7 @@ Example:
 }
 ```
 
-You can also use `patterns`(e.g., `react`, `react-router-dom`, etc).
-
-Example:
-
-```json
-{
-  "import/order": [
-    "error",
-    {
-      "pathGroups": [
-        {
-          "pattern": "react",
-          "group": "builtin",
-          "position": "before"
-        }
-      ],
-      "pathGroupsExcludedImportTypes": ["react"]
-    }
-  ]
-}
-```
-
-The default value is `["builtin", "external", "object"]`.
+[Import Type](https://github.com/import-js/eslint-plugin-import/blob/HEAD/src/core/importType.js#L90) is resolved as a fixed string in predefined set, it can't be a `patterns`(e.g., `react`, `react-router-dom`, etc). See [#2156] for details.
 
 ### `newlines-between: [ignore|always|always-and-inside-groups|never]`
 

From b340f1f321f1804f6db9d024e42d743f96f48126 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 29 Aug 2024 10:32:30 -0700
Subject: [PATCH 691/767] [meta] no need to ship contrib docs

---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index 2aaa786538..b0ddaf8168 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
   },
   "files": [
     "*.md",
+    "!{CONTRIBUTING,RELEASE}.md",
     "LICENSE",
     "docs",
     "lib",

From 806e3c2ccc65456a2d8532d575c9f443355bda82 Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Tue, 18 Jun 2024 07:10:18 -0500
Subject: [PATCH 692/767] [New] add support for Flat Config

This change adds support for ESLint's new Flat config system.  It maintains backwards compatibility with `eslintrc`-style configs as well.

To achieve this, we're now dynamically creating flat configs on a new `flatConfigs` export.

Usage

```js
import importPlugin from 'eslint-plugin-import';
import js from '@eslint/js';
import tsParser from '@typescript-eslint/parser';

export default [
  js.configs.recommended,
  importPlugin.flatConfigs.recommended,
  importPlugin.flatConfigs.react,
  importPlugin.flatConfigs.typescript,
  {
    files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
    languageOptions: {
      parser: tsParser,
      ecmaVersion: 'latest',
      sourceType: 'module',
    },
    ignores: ['eslint.config.js'],
    rules: {
      'no-unused-vars': 'off',
      'import/no-dynamic-require': 'warn',
      'import/no-nodejs-modules': 'warn',
    },
  },
];
```
---
 .editorconfig                         |   1 +
 .eslintignore                         |   1 +
 CHANGELOG.md                          |   3 +
 README.md                             |  31 +++-
 config/flat/errors.js                 |  14 ++
 config/flat/react.js                  |  19 +++
 config/flat/recommended.js            |  26 ++++
 config/flat/warnings.js               |  11 ++
 config/react.js                       |   2 -
 config/typescript.js                  |   2 +-
 examples/flat/eslint.config.mjs       |  25 +++
 examples/flat/package.json            |  17 +++
 examples/flat/src/exports-unused.ts   |  12 ++
 examples/flat/src/exports.ts          |  12 ++
 examples/flat/src/imports.ts          |   7 +
 examples/flat/src/jsx.tsx             |   3 +
 examples/flat/tsconfig.json           |  14 ++
 examples/legacy/.eslintrc.cjs         |  24 +++
 examples/legacy/package.json          |  16 ++
 examples/legacy/src/exports-unused.ts |  12 ++
 examples/legacy/src/exports.ts        |  12 ++
 examples/legacy/src/imports.ts        |   7 +
 examples/legacy/src/jsx.tsx           |   3 +
 examples/legacy/tsconfig.json         |  14 ++
 package.json                          |   3 +
 src/core/fsWalk.js                    |  48 ++++++
 src/index.js                          |  31 ++++
 src/rules/no-unused-modules.js        | 210 ++++++++++++++++++++------
 utils/ignore.js                       |  10 +-
 29 files changed, 541 insertions(+), 49 deletions(-)
 create mode 100644 config/flat/errors.js
 create mode 100644 config/flat/react.js
 create mode 100644 config/flat/recommended.js
 create mode 100644 config/flat/warnings.js
 create mode 100644 examples/flat/eslint.config.mjs
 create mode 100644 examples/flat/package.json
 create mode 100644 examples/flat/src/exports-unused.ts
 create mode 100644 examples/flat/src/exports.ts
 create mode 100644 examples/flat/src/imports.ts
 create mode 100644 examples/flat/src/jsx.tsx
 create mode 100644 examples/flat/tsconfig.json
 create mode 100644 examples/legacy/.eslintrc.cjs
 create mode 100644 examples/legacy/package.json
 create mode 100644 examples/legacy/src/exports-unused.ts
 create mode 100644 examples/legacy/src/exports.ts
 create mode 100644 examples/legacy/src/imports.ts
 create mode 100644 examples/legacy/src/jsx.tsx
 create mode 100644 examples/legacy/tsconfig.json
 create mode 100644 src/core/fsWalk.js

diff --git a/.editorconfig b/.editorconfig
index e2bfac523f..b7b8d09991 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -7,3 +7,4 @@ insert_final_newline = true
 indent_style = space
 indent_size = 2
 end_of_line = lf
+quote_type = single
diff --git a/.eslintignore b/.eslintignore
index 9d22006820..3516f09b9c 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -7,6 +7,7 @@ tests/files/with-syntax-error
 tests/files/just-json-files/invalid.json
 tests/files/typescript-d-ts/
 resolvers/webpack/test/files
+examples
 # we want to ignore "tests/files" here, but unfortunately doing so would
 # interfere with unit test and fail it for some reason.
 # tests/files
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7752473019..05d623f410 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`dynamic-import-chunkname`]: add `allowEmpty` option to allow empty leading comments ([#2942], thanks [@JiangWeixian])
 - [`dynamic-import-chunkname`]: Allow empty chunk name when webpackMode: 'eager' is set; add suggestions to remove name in eager mode ([#3004], thanks [@amsardesai])
 - [`no-unused-modules`]: Add `ignoreUnusedTypeExports` option ([#3011], thanks [@silverwind])
+- add support for Flat Config ([#3018], thanks [@michaelfaith])
 
 ### Fixed
 - [`no-extraneous-dependencies`]: allow wrong path ([#3012], thanks [@chabb])
@@ -1125,6 +1126,7 @@ for info on changes for earlier releases.
 
 [#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
 [#3033]: https://github.com/import-js/eslint-plugin-import/pull/3033
+[#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
 [#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
 [#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
 [#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
@@ -1874,6 +1876,7 @@ for info on changes for earlier releases.
 [@meowtec]: https://github.com/meowtec
 [@mgwalker]: https://github.com/mgwalker
 [@mhmadhamster]: https://github.com/MhMadHamster
+[@michaelfaith]: https://github.com/michaelfaith
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@minervabot]: https://github.com/minervabot
 [@mpint]: https://github.com/mpint
diff --git a/README.md b/README.md
index 1fd113c7d0..bf563f4d7b 100644
--- a/README.md
+++ b/README.md
@@ -106,6 +106,8 @@ The maintainers of `eslint-plugin-import` and thousands of other packages are wo
 npm install eslint-plugin-import --save-dev
 ```
 
+### Config - Legacy (`.eslintrc`)
+
 All rules are off by default. However, you may configure them manually
 in your `.eslintrc.(yml|json|js)`, or extend one of the canned configs:
 
@@ -123,7 +125,7 @@ plugins:
   - import
 
 rules:
-  import/no-unresolved: [2, {commonjs: true, amd: true}]
+  import/no-unresolved: [2, { commonjs: true, amd: true }]
   import/named: 2
   import/namespace: 2
   import/default: 2
@@ -131,6 +133,33 @@ rules:
   # etc...
 ```
 
+### Config - Flat (`eslint.config.js`)
+
+All rules are off by default. However, you may configure them manually
+in your `eslint.config.(js|cjs|mjs)`, or extend one of the canned configs:
+
+```js
+import importPlugin from 'eslint-plugin-import';
+import js from '@eslint/js';
+
+export default [
+  js.configs.recommended,
+  importPlugin.flatConfigs.recommended,
+  {
+    files: ['**/*.{js,mjs,cjs}'],
+    languageOptions: {
+      ecmaVersion: 'latest',
+      sourceType: 'module',
+    },
+    rules: {
+      'no-unused-vars': 'off',
+      'import/no-dynamic-require': 'warn',
+      'import/no-nodejs-modules': 'warn',
+    },
+  },
+];
+```
+
 ## TypeScript
 
 You may use the following snippet or assemble your own config using the granular settings described below it.
diff --git a/config/flat/errors.js b/config/flat/errors.js
new file mode 100644
index 0000000000..98c19f824d
--- /dev/null
+++ b/config/flat/errors.js
@@ -0,0 +1,14 @@
+/**
+ * unopinionated config. just the things that are necessarily runtime errors
+ * waiting to happen.
+ * @type {Object}
+ */
+module.exports = {
+  rules: {
+    'import/no-unresolved': 2,
+    'import/named': 2,
+    'import/namespace': 2,
+    'import/default': 2,
+    'import/export': 2,
+  },
+};
diff --git a/config/flat/react.js b/config/flat/react.js
new file mode 100644
index 0000000000..0867471422
--- /dev/null
+++ b/config/flat/react.js
@@ -0,0 +1,19 @@
+/**
+ * Adds `.jsx` as an extension, and enables JSX parsing.
+ *
+ * Even if _you_ aren't using JSX (or .jsx) directly, if your dependencies
+ * define jsnext:main and have JSX internally, you may run into problems
+ * if you don't enable these settings at the top level.
+ */
+module.exports = {
+  settings: {
+    'import/extensions': ['.js', '.jsx', '.mjs', '.cjs'],
+  },
+  languageOptions: {
+    parserOptions: {
+      ecmaFeatures: {
+        jsx: true,
+      },
+    },
+  },
+};
diff --git a/config/flat/recommended.js b/config/flat/recommended.js
new file mode 100644
index 0000000000..11bc1f52a4
--- /dev/null
+++ b/config/flat/recommended.js
@@ -0,0 +1,26 @@
+/**
+ * The basics.
+ * @type {Object}
+ */
+module.exports = {
+  rules: {
+    // analysis/correctness
+    'import/no-unresolved': 'error',
+    'import/named': 'error',
+    'import/namespace': 'error',
+    'import/default': 'error',
+    'import/export': 'error',
+
+    // red flags (thus, warnings)
+    'import/no-named-as-default': 'warn',
+    'import/no-named-as-default-member': 'warn',
+    'import/no-duplicates': 'warn',
+  },
+
+  // need all these for parsing dependencies (even if _your_ code doesn't need
+  // all of them)
+  languageOptions: {
+    ecmaVersion: 2018,
+    sourceType: 'module',
+  },
+};
diff --git a/config/flat/warnings.js b/config/flat/warnings.js
new file mode 100644
index 0000000000..e788ff9cde
--- /dev/null
+++ b/config/flat/warnings.js
@@ -0,0 +1,11 @@
+/**
+ * more opinionated config.
+ * @type {Object}
+ */
+module.exports = {
+  rules: {
+    'import/no-named-as-default': 1,
+    'import/no-named-as-default-member': 1,
+    'import/no-duplicates': 1,
+  },
+};
diff --git a/config/react.js b/config/react.js
index 68555512d7..1ae8e1a51a 100644
--- a/config/react.js
+++ b/config/react.js
@@ -6,7 +6,6 @@
  * if you don't enable these settings at the top level.
  */
 module.exports = {
-
   settings: {
     'import/extensions': ['.js', '.jsx'],
   },
@@ -14,5 +13,4 @@ module.exports = {
   parserOptions: {
     ecmaFeatures: { jsx: true },
   },
-
 };
diff --git a/config/typescript.js b/config/typescript.js
index ff7d0795c8..d5eb57a465 100644
--- a/config/typescript.js
+++ b/config/typescript.js
@@ -9,7 +9,7 @@
 // `.ts`/`.tsx`/`.js`/`.jsx` implementation.
 const typeScriptExtensions = ['.ts', '.cts', '.mts', '.tsx'];
 
-const allExtensions = [...typeScriptExtensions, '.js', '.jsx'];
+const allExtensions = [...typeScriptExtensions, '.js', '.jsx', '.mjs', '.cjs'];
 
 module.exports = {
   settings: {
diff --git a/examples/flat/eslint.config.mjs b/examples/flat/eslint.config.mjs
new file mode 100644
index 0000000000..370514a65b
--- /dev/null
+++ b/examples/flat/eslint.config.mjs
@@ -0,0 +1,25 @@
+import importPlugin from 'eslint-plugin-import';
+import js from '@eslint/js';
+import tsParser from '@typescript-eslint/parser';
+
+export default [
+  js.configs.recommended,
+  importPlugin.flatConfigs.recommended,
+  importPlugin.flatConfigs.react,
+  importPlugin.flatConfigs.typescript,
+  {
+    files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
+    languageOptions: {
+      parser: tsParser,
+      ecmaVersion: 'latest',
+      sourceType: 'module',
+    },
+    ignores: ['eslint.config.mjs', '**/exports-unused.ts'],
+    rules: {
+      'no-unused-vars': 'off',
+      'import/no-dynamic-require': 'warn',
+      'import/no-nodejs-modules': 'warn',
+      'import/no-unused-modules': ['warn', { unusedExports: true }],
+    },
+  },
+];
diff --git a/examples/flat/package.json b/examples/flat/package.json
new file mode 100644
index 0000000000..0894d29f28
--- /dev/null
+++ b/examples/flat/package.json
@@ -0,0 +1,17 @@
+{
+  "name": "flat",
+  "version": "1.0.0",
+  "main": "index.js",
+  "scripts": {
+    "lint": "cross-env ESLINT_USE_FLAT_CONFIG=true eslint src --report-unused-disable-directives"
+  },
+  "devDependencies": {
+    "@eslint/js": "^9.5.0",
+    "@types/node": "^20.14.5",
+    "@typescript-eslint/parser": "^7.13.1",
+    "cross-env": "^7.0.3",
+    "eslint": "^8.57.0",
+    "eslint-plugin-import": "file:../..",
+    "typescript": "^5.4.5"
+  }
+}
diff --git a/examples/flat/src/exports-unused.ts b/examples/flat/src/exports-unused.ts
new file mode 100644
index 0000000000..af8061ec2b
--- /dev/null
+++ b/examples/flat/src/exports-unused.ts
@@ -0,0 +1,12 @@
+export type ScalarType = string | number;
+export type ObjType = {
+  a: ScalarType;
+  b: ScalarType;
+};
+
+export const a = 13;
+export const b = 18;
+
+const defaultExport: ObjType = { a, b };
+
+export default defaultExport;
diff --git a/examples/flat/src/exports.ts b/examples/flat/src/exports.ts
new file mode 100644
index 0000000000..af8061ec2b
--- /dev/null
+++ b/examples/flat/src/exports.ts
@@ -0,0 +1,12 @@
+export type ScalarType = string | number;
+export type ObjType = {
+  a: ScalarType;
+  b: ScalarType;
+};
+
+export const a = 13;
+export const b = 18;
+
+const defaultExport: ObjType = { a, b };
+
+export default defaultExport;
diff --git a/examples/flat/src/imports.ts b/examples/flat/src/imports.ts
new file mode 100644
index 0000000000..643219ae42
--- /dev/null
+++ b/examples/flat/src/imports.ts
@@ -0,0 +1,7 @@
+//import c from './exports';
+import { a, b } from './exports';
+import type { ScalarType, ObjType } from './exports';
+
+import path from 'path';
+import fs from 'node:fs';
+import console from 'console';
diff --git a/examples/flat/src/jsx.tsx b/examples/flat/src/jsx.tsx
new file mode 100644
index 0000000000..970d53cb84
--- /dev/null
+++ b/examples/flat/src/jsx.tsx
@@ -0,0 +1,3 @@
+const Components = () => {
+  return <></>;
+};
diff --git a/examples/flat/tsconfig.json b/examples/flat/tsconfig.json
new file mode 100644
index 0000000000..e100bfc980
--- /dev/null
+++ b/examples/flat/tsconfig.json
@@ -0,0 +1,14 @@
+{
+  "compilerOptions": {
+    "jsx": "react-jsx",
+    "lib": ["ESNext"],
+    "target": "ESNext",
+    "module": "ESNext",
+    "rootDir": "./",
+    "moduleResolution": "Bundler",
+    "esModuleInterop": true,
+    "forceConsistentCasingInFileNames": true,
+    "strict": true,
+    "skipLibCheck": true
+  }
+}
diff --git a/examples/legacy/.eslintrc.cjs b/examples/legacy/.eslintrc.cjs
new file mode 100644
index 0000000000..e3cec097f0
--- /dev/null
+++ b/examples/legacy/.eslintrc.cjs
@@ -0,0 +1,24 @@
+module.exports = {
+  root: true,
+  env: { es2022: true },
+  extends: [
+    'eslint:recommended',
+    'plugin:import/recommended',
+    'plugin:import/react',
+    'plugin:import/typescript',
+  ],
+  settings: {},
+  ignorePatterns: ['.eslintrc.cjs', '**/exports-unused.ts'],
+  parser: '@typescript-eslint/parser',
+  parserOptions: {
+    ecmaVersion: 'latest',
+    sourceType: 'module',
+  },
+  plugins: ['import'],
+  rules: {
+    'no-unused-vars': 'off',
+    'import/no-dynamic-require': 'warn',
+    'import/no-nodejs-modules': 'warn',
+    'import/no-unused-modules': ['warn', { unusedExports: true }],
+  },
+};
diff --git a/examples/legacy/package.json b/examples/legacy/package.json
new file mode 100644
index 0000000000..e3ca094887
--- /dev/null
+++ b/examples/legacy/package.json
@@ -0,0 +1,16 @@
+{
+  "name": "legacy",
+  "version": "1.0.0",
+  "main": "index.js",
+  "scripts": {
+    "lint": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint src --ext js,jsx,ts,tsx --report-unused-disable-directives"
+  },
+  "devDependencies": {
+    "@types/node": "^20.14.5",
+    "@typescript-eslint/parser": "^7.13.1",
+    "cross-env": "^7.0.3",
+    "eslint": "^8.57.0",
+    "eslint-plugin-import": "file:../..",
+    "typescript": "^5.4.5"
+  }
+}
diff --git a/examples/legacy/src/exports-unused.ts b/examples/legacy/src/exports-unused.ts
new file mode 100644
index 0000000000..af8061ec2b
--- /dev/null
+++ b/examples/legacy/src/exports-unused.ts
@@ -0,0 +1,12 @@
+export type ScalarType = string | number;
+export type ObjType = {
+  a: ScalarType;
+  b: ScalarType;
+};
+
+export const a = 13;
+export const b = 18;
+
+const defaultExport: ObjType = { a, b };
+
+export default defaultExport;
diff --git a/examples/legacy/src/exports.ts b/examples/legacy/src/exports.ts
new file mode 100644
index 0000000000..af8061ec2b
--- /dev/null
+++ b/examples/legacy/src/exports.ts
@@ -0,0 +1,12 @@
+export type ScalarType = string | number;
+export type ObjType = {
+  a: ScalarType;
+  b: ScalarType;
+};
+
+export const a = 13;
+export const b = 18;
+
+const defaultExport: ObjType = { a, b };
+
+export default defaultExport;
diff --git a/examples/legacy/src/imports.ts b/examples/legacy/src/imports.ts
new file mode 100644
index 0000000000..643219ae42
--- /dev/null
+++ b/examples/legacy/src/imports.ts
@@ -0,0 +1,7 @@
+//import c from './exports';
+import { a, b } from './exports';
+import type { ScalarType, ObjType } from './exports';
+
+import path from 'path';
+import fs from 'node:fs';
+import console from 'console';
diff --git a/examples/legacy/src/jsx.tsx b/examples/legacy/src/jsx.tsx
new file mode 100644
index 0000000000..970d53cb84
--- /dev/null
+++ b/examples/legacy/src/jsx.tsx
@@ -0,0 +1,3 @@
+const Components = () => {
+  return <></>;
+};
diff --git a/examples/legacy/tsconfig.json b/examples/legacy/tsconfig.json
new file mode 100644
index 0000000000..e100bfc980
--- /dev/null
+++ b/examples/legacy/tsconfig.json
@@ -0,0 +1,14 @@
+{
+  "compilerOptions": {
+    "jsx": "react-jsx",
+    "lib": ["ESNext"],
+    "target": "ESNext",
+    "module": "ESNext",
+    "rootDir": "./",
+    "moduleResolution": "Bundler",
+    "esModuleInterop": true,
+    "forceConsistentCasingInFileNames": true,
+    "strict": true,
+    "skipLibCheck": true
+  }
+}
diff --git a/package.json b/package.json
index b0ddaf8168..f9a95fabb4 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,9 @@
     "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
     "test-all": "node --require babel-register ./scripts/testAll",
+    "test-examples": "npm run build && npm run test-example:legacy && npm run test-example:flat",
+    "test-example:legacy": "cd examples/legacy && npm install && npm run lint",
+    "test-example:flat": "cd examples/flat && npm install && npm run lint",
     "prepublishOnly": "safe-publish-latest && npm run build",
     "prepublish": "not-in-publish || npm run prepublishOnly",
     "preupdate:eslint-docs": "npm run build",
diff --git a/src/core/fsWalk.js b/src/core/fsWalk.js
new file mode 100644
index 0000000000..fa112590f1
--- /dev/null
+++ b/src/core/fsWalk.js
@@ -0,0 +1,48 @@
+/**
+ * This is intended to provide similar capability as the sync api from @nodelib/fs.walk, until `eslint-plugin-import`
+ * is willing to modernize and update their minimum node version to at least v16.  I intentionally made the
+ * shape of the API (for the part we're using) the same as @nodelib/fs.walk so that that can be swapped in
+ * when the repo is ready for it.
+ */
+
+import path from 'path';
+import { readdirSync } from 'fs';
+
+/** @typedef {{ name: string, path: string, dirent: import('fs').Dirent }} Entry */
+
+/**
+ * Do a comprehensive walk of the provided src directory, and collect all entries.  Filter out
+ * any directories or entries using the optional filter functions.
+ * @param {string} root - path to the root of the folder we're walking
+ * @param {{ deepFilter?: (entry: Entry) => boolean, entryFilter?: (entry: Entry) => boolean }} options
+ * @param {Entry} currentEntry - entry for the current directory we're working in
+ * @param {Entry[]} existingEntries - list of all entries so far
+ * @returns {Entry[]} an array of directory entries
+ */
+export function walkSync(root, options, currentEntry, existingEntries) {
+  // Extract the filter functions. Default to evaluating true, if no filter passed in.
+  const { deepFilter = () => true, entryFilter = () => true } = options;
+
+  let entryList = existingEntries || [];
+  const currentRelativePath = currentEntry ? currentEntry.path : '.';
+  const fullPath = currentEntry ? path.join(root, currentEntry.path) : root;
+
+  const dirents = readdirSync(fullPath, { withFileTypes: true });
+  dirents.forEach((dirent) => {
+    /** @type {Entry} */
+    const entry = {
+      name: dirent.name,
+      path: path.join(currentRelativePath, dirent.name),
+      dirent,
+    };
+
+    if (dirent.isDirectory() && deepFilter(entry)) {
+      entryList.push(entry);
+      entryList = walkSync(root, options, entry, entryList);
+    } else if (dirent.isFile() && entryFilter(entry)) {
+      entryList.push(entry);
+    }
+  });
+
+  return entryList;
+}
diff --git a/src/index.js b/src/index.js
index feafba9003..0ab82ebee8 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,3 +1,5 @@
+import { name, version } from '../package.json';
+
 export const rules = {
   'no-unresolved': require('./rules/no-unresolved'),
   named: require('./rules/named'),
@@ -69,3 +71,32 @@ export const configs = {
   electron: require('../config/electron'),
   typescript: require('../config/typescript'),
 };
+
+// Base Plugin Object
+const importPlugin = {
+  meta: { name, version },
+  rules,
+};
+
+// Create flat configs (Only ones that declare plugins and parser options need to be different from the legacy config)
+const createFlatConfig = (baseConfig, configName) => ({
+  ...baseConfig,
+  name: `import/${configName}`,
+  plugins: { import: importPlugin },
+});
+
+export const flatConfigs = {
+  recommended: createFlatConfig(
+    require('../config/flat/recommended'),
+    'recommended',
+  ),
+
+  errors: createFlatConfig(require('../config/flat/errors'), 'errors'),
+  warnings: createFlatConfig(require('../config/flat/warnings'), 'warnings'),
+
+  // useful stuff for folks using various environments
+  react: require('../config/flat/react'),
+  'react-native': configs['react-native'],
+  electron: configs.electron,
+  typescript: configs.typescript,
+};
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 46fc93bfe0..702f2f8899 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -7,61 +7,177 @@
 import { getFileExtensions } from 'eslint-module-utils/ignore';
 import resolve from 'eslint-module-utils/resolve';
 import visit from 'eslint-module-utils/visit';
-import { dirname, join } from 'path';
+import { dirname, join, resolve as resolvePath } from 'path';
 import readPkgUp from 'eslint-module-utils/readPkgUp';
 import values from 'object.values';
 import includes from 'array-includes';
 import flatMap from 'array.prototype.flatmap';
 
+import { walkSync } from '../core/fsWalk';
 import ExportMapBuilder from '../exportMap/builder';
 import recursivePatternCapture from '../exportMap/patternCapture';
 import docsUrl from '../docsUrl';
 
-let FileEnumerator;
-let listFilesToProcess;
+/**
+ * Attempt to load the internal `FileEnumerator` class, which has existed in a couple
+ * of different places, depending on the version of `eslint`.  Try requiring it from both
+ * locations.
+ * @returns Returns the `FileEnumerator` class if its requirable, otherwise `undefined`.
+ */
+function requireFileEnumerator() {
+  let FileEnumerator;
 
-try {
-  ({ FileEnumerator } = require('eslint/use-at-your-own-risk'));
-} catch (e) {
+  // Try getting it from the eslint private / deprecated api
   try {
-    // has been moved to eslint/lib/cli-engine/file-enumerator in version 6
-    ({ FileEnumerator } = require('eslint/lib/cli-engine/file-enumerator'));
+    ({ FileEnumerator } = require('eslint/use-at-your-own-risk'));
   } catch (e) {
+    // Absorb this if it's MODULE_NOT_FOUND
+    if (e.code !== 'MODULE_NOT_FOUND') {
+      throw e;
+    }
+
+    // If not there, then try getting it from eslint/lib/cli-engine/file-enumerator (moved there in v6)
     try {
-      // eslint/lib/util/glob-util has been moved to eslint/lib/util/glob-utils with version 5.3
-      const { listFilesToProcess: originalListFilesToProcess } = require('eslint/lib/util/glob-utils');
-
-      // Prevent passing invalid options (extensions array) to old versions of the function.
-      // https://github.com/eslint/eslint/blob/v5.16.0/lib/util/glob-utils.js#L178-L280
-      // https://github.com/eslint/eslint/blob/v5.2.0/lib/util/glob-util.js#L174-L269
-      listFilesToProcess = function (src, extensions) {
-        return originalListFilesToProcess(src, {
-          extensions,
-        });
-      };
+      ({ FileEnumerator } = require('eslint/lib/cli-engine/file-enumerator'));
     } catch (e) {
-      const { listFilesToProcess: originalListFilesToProcess } = require('eslint/lib/util/glob-util');
+      // Absorb this if it's MODULE_NOT_FOUND
+      if (e.code !== 'MODULE_NOT_FOUND') {
+        throw e;
+      }
+    }
+  }
+  return FileEnumerator;
+}
+
+/**
+ *
+ * @param FileEnumerator the `FileEnumerator` class from `eslint`'s internal api
+ * @param {string} src path to the src root
+ * @param {string[]} extensions list of supported extensions
+ * @returns {{ filename: string, ignored: boolean }[]} list of files to operate on
+ */
+function listFilesUsingFileEnumerator(FileEnumerator, src, extensions) {
+  const e = new FileEnumerator({
+    extensions,
+  });
+
+  return Array.from(
+    e.iterateFiles(src),
+    ({ filePath, ignored }) => ({ filename: filePath, ignored }),
+  );
+}
 
-      listFilesToProcess = function (src, extensions) {
-        const patterns = src.concat(flatMap(src, (pattern) => extensions.map((extension) => (/\*\*|\*\./).test(pattern) ? pattern : `${pattern}/**/*${extension}`)));
+/**
+ * Attempt to require old versions of the file enumeration capability from v6 `eslint` and earlier, and use
+ * those functions to provide the list of files to operate on
+ * @param {string} src path to the src root
+ * @param {string[]} extensions list of supported extensions
+ * @returns {string[]} list of files to operate on
+ */
+function listFilesWithLegacyFunctions(src, extensions) {
+  try {
+    // eslint/lib/util/glob-util has been moved to eslint/lib/util/glob-utils with version 5.3
+    const { listFilesToProcess: originalListFilesToProcess } = require('eslint/lib/util/glob-utils');
+    // Prevent passing invalid options (extensions array) to old versions of the function.
+    // https://github.com/eslint/eslint/blob/v5.16.0/lib/util/glob-utils.js#L178-L280
+    // https://github.com/eslint/eslint/blob/v5.2.0/lib/util/glob-util.js#L174-L269
 
-        return originalListFilesToProcess(patterns);
-      };
+    return originalListFilesToProcess(src, {
+      extensions,
+    });
+  } catch (e) {
+    // Absorb this if it's MODULE_NOT_FOUND
+    if (e.code !== 'MODULE_NOT_FOUND') {
+      throw e;
     }
+
+    // Last place to try (pre v5.3)
+    const {
+      listFilesToProcess: originalListFilesToProcess,
+    } = require('eslint/lib/util/glob-util');
+    const patterns = src.concat(
+      flatMap(
+        src,
+        (pattern) => extensions.map((extension) => (/\*\*|\*\./).test(pattern) ? pattern : `${pattern}/**/*${extension}`),
+      ),
+    );
+
+    return originalListFilesToProcess(patterns);
   }
 }
 
-if (FileEnumerator) {
-  listFilesToProcess = function (src, extensions) {
-    const e = new FileEnumerator({
-      extensions,
+/**
+ * Given a source root and list of supported extensions, use fsWalk and the
+ * new `eslint` `context.session` api to build the list of files we want to operate on
+ * @param {string[]} srcPaths array of source paths (for flat config this should just be a singular root (e.g. cwd))
+ * @param {string[]} extensions list of supported extensions
+ * @param {{ isDirectoryIgnored: (path: string) => boolean, isFileIgnored: (path: string) => boolean }} session eslint context session object
+ * @returns {string[]} list of files to operate on
+ */
+function listFilesWithModernApi(srcPaths, extensions, session) {
+  /** @type {string[]} */
+  const files = [];
+
+  for (let i = 0; i < srcPaths.length; i++) {
+    const src = srcPaths[i];
+    // Use walkSync along with the new session api to gather the list of files
+    const entries = walkSync(src, {
+      deepFilter(entry) {
+        const fullEntryPath = resolvePath(src, entry.path);
+
+        // Include the directory if it's not marked as ignore by eslint
+        return !session.isDirectoryIgnored(fullEntryPath);
+      },
+      entryFilter(entry) {
+        const fullEntryPath = resolvePath(src, entry.path);
+
+        // Include the file if it's not marked as ignore by eslint and its extension is included in our list
+        return (
+          !session.isFileIgnored(fullEntryPath)
+          && extensions.find((extension) => entry.path.endsWith(extension))
+        );
+      },
     });
 
-    return Array.from(e.iterateFiles(src), ({ filePath, ignored }) => ({
-      ignored,
-      filename: filePath,
-    }));
-  };
+    // Filter out directories and map entries to their paths
+    files.push(
+      ...entries
+        .filter((entry) => !entry.dirent.isDirectory())
+        .map((entry) => entry.path),
+    );
+  }
+  return files;
+}
+
+/**
+ * Given a src pattern and list of supported extensions, return a list of files to process
+ * with this rule.
+ * @param {string} src - file, directory, or glob pattern of files to act on
+ * @param {string[]} extensions - list of supported file extensions
+ * @param {import('eslint').Rule.RuleContext} context - the eslint context object
+ * @returns {string[] | { filename: string, ignored: boolean }[]} the list of files that this rule will evaluate.
+ */
+function listFilesToProcess(src, extensions, context) {
+  // If the context object has the new session functions, then prefer those
+  // Otherwise, fallback to using the deprecated `FileEnumerator` for legacy support.
+  // https://github.com/eslint/eslint/issues/18087
+  if (
+    context.session
+    && context.session.isFileIgnored
+    && context.session.isDirectoryIgnored
+  ) {
+    return listFilesWithModernApi(src, extensions, context.session);
+  }
+
+  // Fallback to og FileEnumerator
+  const FileEnumerator = requireFileEnumerator();
+
+  // If we got the FileEnumerator, then let's go with that
+  if (FileEnumerator) {
+    return listFilesUsingFileEnumerator(FileEnumerator, src, extensions);
+  }
+  // If not, then we can try even older versions of this capability (listFilesToProcess)
+  return listFilesWithLegacyFunctions(src, extensions);
 }
 
 const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration';
@@ -163,6 +279,7 @@ const exportList = new Map();
 
 const visitorKeyMap = new Map();
 
+/** @type {Set<string>} */
 const ignoredFiles = new Set();
 const filesOutsideSrc = new Set();
 
@@ -172,22 +289,30 @@ const isNodeModule = (path) => (/\/(node_modules)\//).test(path);
  * read all files matching the patterns in src and ignoreExports
  *
  * return all files matching src pattern, which are not matching the ignoreExports pattern
+ * @type {(src: string, ignoreExports: string, context: import('eslint').Rule.RuleContext) => Set<string>}
  */
-const resolveFiles = (src, ignoreExports, context) => {
+function resolveFiles(src, ignoreExports, context) {
   const extensions = Array.from(getFileExtensions(context.settings));
 
-  const srcFileList = listFilesToProcess(src, extensions);
+  const srcFileList = listFilesToProcess(src, extensions, context);
 
   // prepare list of ignored files
-  const ignoredFilesList = listFilesToProcess(ignoreExports, extensions);
-  ignoredFilesList.forEach(({ filename }) => ignoredFiles.add(filename));
+  const ignoredFilesList = listFilesToProcess(ignoreExports, extensions, context);
+
+  // The modern api will return a list of file paths, rather than an object
+  if (ignoredFilesList.length && typeof ignoredFilesList[0] === 'string') {
+    ignoredFilesList.forEach((filename) => ignoredFiles.add(filename));
+  } else {
+    ignoredFilesList.forEach(({ filename }) => ignoredFiles.add(filename));
+  }
 
   // prepare list of source files, don't consider files from node_modules
+  const resolvedFiles = srcFileList.length && typeof srcFileList[0] === 'string'
+    ? srcFileList.filter((filePath) => !isNodeModule(filePath))
+    : flatMap(srcFileList, ({ filename }) => isNodeModule(filename) ? [] : filename);
 
-  return new Set(
-    flatMap(srcFileList, ({ filename }) => isNodeModule(filename) ? [] : filename),
-  );
-};
+  return new Set(resolvedFiles);
+}
 
 /**
  * parse all source files and build up 2 maps containing the existing imports and exports
@@ -226,7 +351,7 @@ const prepareImportsAndExports = (srcFiles, context) => {
         } else {
           exports.set(key, { whereUsed: new Set() });
         }
-        const reexport =  value.getImport();
+        const reexport = value.getImport();
         if (!reexport) {
           return;
         }
@@ -329,6 +454,7 @@ const getSrc = (src) => {
  * prepare the lists of existing imports and exports - should only be executed once at
  * the start of a new eslint run
  */
+/** @type {Set<string>} */
 let srcFiles;
 let lastPrepareKey;
 const doPreparation = (src, ignoreExports, context) => {
diff --git a/utils/ignore.js b/utils/ignore.js
index 56f2ef7239..a42d4ceb1f 100644
--- a/utils/ignore.js
+++ b/utils/ignore.js
@@ -14,7 +14,7 @@ const log = require('debug')('eslint-plugin-import:utils:ignore');
 function makeValidExtensionSet(settings) {
   // start with explicit JS-parsed extensions
   /** @type {Set<import('./types').Extension>} */
-  const exts = new Set(settings['import/extensions'] || ['.js']);
+  const exts = new Set(settings['import/extensions'] || ['.js', '.mjs', '.cjs']);
 
   // all alternate parser extensions are also valid
   if ('import/parsers' in settings) {
@@ -52,9 +52,13 @@ exports.hasValidExtension = hasValidExtension;
 /** @type {import('./ignore').default} */
 exports.default = function ignore(path, context) {
   // check extension whitelist first (cheap)
-  if (!hasValidExtension(path, context)) { return true; }
+  if (!hasValidExtension(path, context)) {
+    return true;
+  }
 
-  if (!('import/ignore' in context.settings)) { return false; }
+  if (!('import/ignore' in context.settings)) {
+    return false;
+  }
   const ignoreStrings = context.settings['import/ignore'];
 
   for (let i = 0; i < ignoreStrings.length; i++) {

From ee1ea025a6843fe4380927832a31761f1f4ae339 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=89=E1=85=A1=E1=86=BC?=
 =?UTF-8?q?=E1=84=83=E1=85=AE?= <puki4416@gmail.com>
Date: Sat, 13 Jan 2024 01:42:54 +0900
Subject: [PATCH 693/767] [Fix] `newline-after-import`: fix considerComments
 option when require

---
 CHANGELOG.md                            |  3 ++
 src/rules/newline-after-import.js       | 20 +++++++++----
 tests/src/rules/newline-after-import.js | 38 +++++++++++++++++++++----
 3 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 05d623f410..2d0ff1a912 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-extraneous-dependencies`]: allow wrong path ([#3012], thanks [@chabb])
 - [`no-cycle`]: use scc algorithm to optimize ([#2998], thanks [@soryy708])
 - [`no-duplicates`]: Removing duplicates breaks in TypeScript ([#3033], thanks [@yesl-kim])
+- [`newline-after-import`]: fix considerComments option when require ([#2952], thanks [@developer-bandi])
 
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
@@ -1136,6 +1137,7 @@ for info on changes for earlier releases.
 [#2987]: https://github.com/import-js/eslint-plugin-import/pull/2987
 [#2985]: https://github.com/import-js/eslint-plugin-import/pull/2985
 [#2982]: https://github.com/import-js/eslint-plugin-import/pull/2982
+[#2952]: https://github.com/import-js/eslint-plugin-import/pull/2952
 [#2944]: https://github.com/import-js/eslint-plugin-import/pull/2944
 [#2942]: https://github.com/import-js/eslint-plugin-import/pull/2942
 [#2919]: https://github.com/import-js/eslint-plugin-import/pull/2919
@@ -1742,6 +1744,7 @@ for info on changes for earlier releases.
 [@bicstone]: https://github.com/bicstone
 [@Blasz]: https://github.com/Blasz
 [@bmish]: https://github.com/bmish
+[@developer-bandi]: https://github.com/developer-bandi
 [@borisyankov]: https://github.com/borisyankov
 [@bradennapier]: https://github.com/bradennapier
 [@bradzacher]: https://github.com/bradzacher
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index a33bb615b9..d10b87d78c 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -124,7 +124,7 @@ module.exports = {
       }
     }
 
-    function commentAfterImport(node, nextComment) {
+    function commentAfterImport(node, nextComment, type) {
       const lineDifference = getLineDifference(node, nextComment);
       const EXPECTED_LINE_DIFFERENCE = options.count + 1;
 
@@ -140,7 +140,7 @@ module.exports = {
             line: node.loc.end.line,
             column,
           },
-          message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} after import statement not followed by another import.`,
+          message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} after ${type} statement not followed by another ${type}.`,
           fix: options.exactCount && EXPECTED_LINE_DIFFERENCE < lineDifference ? undefined : (fixer) => fixer.insertTextAfter(
             node,
             '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference),
@@ -178,7 +178,7 @@ module.exports = {
       }
 
       if (nextComment && typeof nextComment !== 'undefined') {
-        commentAfterImport(node, nextComment);
+        commentAfterImport(node, nextComment, 'import');
       } else if (nextNode && nextNode.type !== 'ImportDeclaration' && (nextNode.type !== 'TSImportEqualsDeclaration' || nextNode.isExport)) {
         checkForNewLine(node, nextNode, 'import');
       }
@@ -215,8 +215,18 @@ module.exports = {
               || !containsNodeOrEqual(nextStatement, nextRequireCall)
             )
           ) {
-
-            checkForNewLine(statementWithRequireCall, nextStatement, 'require');
+            let nextComment;
+            if (typeof statementWithRequireCall.parent.comments !== 'undefined' && options.considerComments) {
+              const endLine = node.loc.end.line;
+              nextComment = statementWithRequireCall.parent.comments.find((o) => o.loc.start.line >= endLine && o.loc.start.line <= endLine + options.count + 1);
+            }
+
+            if (nextComment && typeof nextComment !== 'undefined') {
+
+              commentAfterImport(statementWithRequireCall, nextComment, 'require');
+            } else {
+              checkForNewLine(statementWithRequireCall, nextStatement, 'require');
+            }
           }
         });
       },
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 6a8fb83e40..b78e891a35 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -8,6 +8,7 @@ import { getTSParsers, parsers, testVersion } from '../utils';
 const IMPORT_ERROR_MESSAGE = 'Expected 1 empty line after import statement not followed by another import.';
 const IMPORT_ERROR_MESSAGE_MULTIPLE = (count) => `Expected ${count} empty lines after import statement not followed by another import.`;
 const REQUIRE_ERROR_MESSAGE = 'Expected 1 empty line after require statement not followed by another require.';
+const REQUIRE_ERROR_MESSAGE_MULTIPLE = (count) => `Expected ${count} empty lines after require statement not followed by another require.`;
 
 const ruleTester = new RuleTester();
 
@@ -202,7 +203,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       options: [{ count: 4, exactCount: true }],
     },
     {
-      code: `var foo = require('foo-module');\n\n\n\n// Some random comment\nvar foo = 'bar';`,
+      code: `var foo = require('foo-module');\n\n\n\n\n// Some random comment\nvar foo = 'bar';`,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ count: 4, exactCount: true, considerComments: true }],
     },
@@ -394,6 +395,19 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       `,
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
+    {
+      code: `var foo = require('foo-module');\n\n\n// Some random comment\nvar foo = 'bar';`,
+      options: [{ count: 2, considerComments: true }],
+    },
+    {
+      code: `var foo = require('foo-module');\n\n\n/**\n * Test comment\n */\nvar foo = 'bar';`,
+      options: [{ count: 2, considerComments: true }],
+    },
+    {
+      code: `const foo = require('foo');\n\n\n// some random comment\nconst bar = function() {};`,
+      options: [{ count: 2, exactCount: true, considerComments: true }],
+      parserOptions: { ecmaVersion: 2015 },
+    },
   ),
 
   invalid: [].concat(
@@ -825,7 +839,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       errors: [{
         line: 1,
         column: 1,
-        message: 'Expected 2 empty lines after require statement not followed by another require.',
+        message: REQUIRE_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015 },
     },
@@ -836,7 +850,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       errors: [{
         line: 1,
         column: 1,
-        message: 'Expected 2 empty lines after require statement not followed by another require.',
+        message: REQUIRE_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015 },
     },
@@ -852,14 +866,26 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       parserOptions: { ecmaVersion: 2015, considerComments: true, sourceType: 'module' },
     },
     {
-      code: `const foo = require('foo');\n\n\n// some random comment\nconst bar = function() {};`,
-      options: [{ count: 2, exactCount: true, considerComments: true }],
+      code: `var foo = require('foo-module');\nvar foo = require('foo-module');\n\n// Some random comment\nvar foo = 'bar';`,
+      output: `var foo = require('foo-module');\nvar foo = require('foo-module');\n\n\n// Some random comment\nvar foo = 'bar';`,
+      errors: [{
+        line: 2,
+        column: 1,
+        message: REQUIRE_ERROR_MESSAGE_MULTIPLE(2),
+      }],
+      parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
+      options: [{ considerComments: true, count: 2 }],
+    },
+    {
+      code: `var foo = require('foo-module');\n\n/**\n * Test comment\n */\nvar foo = 'bar';`,
+      output: `var foo = require('foo-module');\n\n\n/**\n * Test comment\n */\nvar foo = 'bar';`,
       errors: [{
         line: 1,
         column: 1,
-        message: 'Expected 2 empty lines after require statement not followed by another require.',
+        message: REQUIRE_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015 },
+      options: [{ considerComments: true, count: 2 }],
     },
   ),
 });

From 32a2b8986961639cc9c19ebac1f1f0640fb78ef5 Mon Sep 17 00:00:00 2001
From: Mihkel Eidast <mihkel_eidast@trimble.com>
Date: Tue, 26 Sep 2023 14:13:04 +0300
Subject: [PATCH 694/767] [Fix] `order`: do not compare first path segment for
 relative paths (#2682)

---
 CHANGELOG.md             |  4 ++++
 src/rules/order.js       |  6 ++++++
 tests/src/rules/order.js | 28 ++++++++++++++++++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d0ff1a912..92431a1563 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-cycle`]: use scc algorithm to optimize ([#2998], thanks [@soryy708])
 - [`no-duplicates`]: Removing duplicates breaks in TypeScript ([#3033], thanks [@yesl-kim])
 - [`newline-after-import`]: fix considerComments option when require ([#2952], thanks [@developer-bandi])
+- [`order`]: do not compare first path segment for relative paths ([#2682]) ([#2885], thanks [@mihkeleidast])
 
 ### Changed
 - [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
@@ -1141,6 +1142,7 @@ for info on changes for earlier releases.
 [#2944]: https://github.com/import-js/eslint-plugin-import/pull/2944
 [#2942]: https://github.com/import-js/eslint-plugin-import/pull/2942
 [#2919]: https://github.com/import-js/eslint-plugin-import/pull/2919
+[#2885]: https://github.com/import-js/eslint-plugin-import/pull/2885
 [#2884]: https://github.com/import-js/eslint-plugin-import/pull/2884
 [#2866]: https://github.com/import-js/eslint-plugin-import/pull/2866
 [#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854
@@ -1486,6 +1488,7 @@ for info on changes for earlier releases.
 [#2930]: https://github.com/import-js/eslint-plugin-import/issues/2930
 [#2687]: https://github.com/import-js/eslint-plugin-import/issues/2687
 [#2684]: https://github.com/import-js/eslint-plugin-import/issues/2684
+[#2682]: https://github.com/import-js/eslint-plugin-import/issues/2682
 [#2674]: https://github.com/import-js/eslint-plugin-import/issues/2674
 [#2668]: https://github.com/import-js/eslint-plugin-import/issues/2668
 [#2666]: https://github.com/import-js/eslint-plugin-import/issues/2666
@@ -1880,6 +1883,7 @@ for info on changes for earlier releases.
 [@mgwalker]: https://github.com/mgwalker
 [@mhmadhamster]: https://github.com/MhMadHamster
 [@michaelfaith]: https://github.com/michaelfaith
+[@mihkeleidast]: https://github.com/mihkeleidast
 [@MikeyBeLike]: https://github.com/MikeyBeLike
 [@minervabot]: https://github.com/minervabot
 [@mpint]: https://github.com/mpint
diff --git a/src/rules/order.js b/src/rules/order.js
index 7071513bf3..1b25273c65 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -302,6 +302,12 @@ function getSorter(alphabetizeOptions) {
       const b = B.length;
 
       for (let i = 0; i < Math.min(a, b); i++) {
+        // Skip comparing the first path segment, if they are relative segments for both imports
+        if (i === 0 && ((A[i] === '.' || A[i] === '..') && (B[i] === '.' || B[i] === '..'))) {
+          // If one is sibling and the other parent import, no need to compare at all, since the paths belong in different groups
+          if (A[i] !== B[i]) { break; }
+          continue;
+        }
         result = compareString(A[i], B[i]);
         if (result) { break; }
       }
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index a6a8735a6f..c2d659f839 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -169,6 +169,34 @@ ruleTester.run('order', rule, {
         ['sibling', 'parent', 'external'],
       ] }],
     }),
+    // Grouping import types and alphabetize
+    test({
+      code: `
+        import async from 'async';
+        import fs from 'fs';
+        import path from 'path';
+
+        import index from '.';
+        import relParent3 from '../';
+        import relParent1 from '../foo';
+        import sibling from './foo';
+      `,
+      options: [{ groups: [
+        ['builtin', 'external'],
+      ], alphabetize: { order: 'asc', caseInsensitive: true } }],
+    }),
+    test({
+      code: `
+      import { fooz } from '../baz.js'
+      import { foo } from './bar.js'
+      `,
+      options: [{
+        alphabetize: { order: 'asc', caseInsensitive: true },
+        groups: ['builtin', 'external', 'internal', ['parent', 'sibling', 'index'], 'object'],
+        'newlines-between': 'always',
+        warnOnUnassignedImports: true,
+      }],
+    }),
     // Omitted types should implicitly be considered as the last type
     test({
       code: `

From 038c26cade3c85c823ba2eafd52bb91ae458f2b2 Mon Sep 17 00:00:00 2001
From: jwbth <33615628+jwbth@users.noreply.github.com>
Date: Thu, 28 Mar 2024 22:38:13 +0400
Subject: [PATCH 695/767] [readme] Clarify how to install the plugin

The markup was misleading, as it put several alternatives into one block of code while not making it clear where the alternatives begin and end, forcing the reader to think hard about it.

Also converted most yaml examples to jsonc.

Co-authored-by: jwbth <33615628+jwbth@users.noreply.github.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
---
 CHANGELOG.md |   3 +
 README.md    | 176 ++++++++++++++++++++++++++++++++-------------------
 2 files changed, 115 insertions(+), 64 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92431a1563..9022dc887b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Refactor] `exportMapBuilder`: avoid hoisting ([#2989], thanks [@soryy708])
 - [Refactor] `ExportMap`: extract "builder" logic to separate files ([#2991], thanks [@soryy708])
 - [Docs] [`order`]: update the description of the `pathGroupsExcludedImportTypes` option ([#3036], thanks [@liby])
+- [readme] Clarify how to install the plugin ([#2993], thanks [@jwbth])
 
 ## [2.29.1] - 2023-12-14
 
@@ -1133,6 +1134,7 @@ for info on changes for earlier releases.
 [#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
 [#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
 [#2998]: https://github.com/import-js/eslint-plugin-import/pull/2998
+[#2993]: https://github.com/import-js/eslint-plugin-import/pull/2993
 [#2991]: https://github.com/import-js/eslint-plugin-import/pull/2991
 [#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
 [#2987]: https://github.com/import-js/eslint-plugin-import/pull/2987
@@ -1835,6 +1837,7 @@ for info on changes for earlier releases.
 [@jseminck]: https://github.com/jseminck
 [@julien1619]: https://github.com/julien1619
 [@justinanastos]: https://github.com/justinanastos
+[@jwbth]: https://github.com/jwbth
 [@k15a]: https://github.com/k15a
 [@kentcdodds]: https://github.com/kentcdodds
 [@kevin940726]: https://github.com/kevin940726
diff --git a/README.md b/README.md
index bf563f4d7b..8cc723423f 100644
--- a/README.md
+++ b/README.md
@@ -108,35 +108,37 @@ npm install eslint-plugin-import --save-dev
 
 ### Config - Legacy (`.eslintrc`)
 
-All rules are off by default. However, you may configure them manually
-in your `.eslintrc.(yml|json|js)`, or extend one of the canned configs:
+All rules are off by default. However, you may extend one of the preset configs, or configure them manually in your `.eslintrc.(yml|json|js)`.
 
-```yaml
----
-extends:
-  - eslint:recommended
-  - plugin:import/recommended
-  # alternatively, 'recommended' is the combination of these two rule sets:
-  - plugin:import/errors
-  - plugin:import/warnings
-
-# or configure manually:
-plugins:
-  - import
-
-rules:
-  import/no-unresolved: [2, { commonjs: true, amd: true }]
-  import/named: 2
-  import/namespace: 2
-  import/default: 2
-  import/export: 2
-  # etc...
+ - Extending a preset config:
+
+```jsonc
+{
+  "extends": [
+     "eslint:recommended",
+     "plugin:import/recommended",
+  ],
+}
+```
+
+ - Configuring manually:
+
+```jsonc
+{
+  "rules": {
+    "import/no-unresolved": ["error", { "commonjs": true, "amd": true }]
+    "import/named": "error",
+    "import/namespace": "error",
+    "import/default": "error",
+    "import/export": "error",
+    // etc...
+  },
+},
 ```
 
 ### Config - Flat (`eslint.config.js`)
 
-All rules are off by default. However, you may configure them manually
-in your `eslint.config.(js|cjs|mjs)`, or extend one of the canned configs:
+All rules are off by default. However, you may configure them manually in your `eslint.config.(js|cjs|mjs)`, or extend one of the preset configs:
 
 ```js
 import importPlugin from 'eslint-plugin-import';
@@ -166,18 +168,23 @@ You may use the following snippet or assemble your own config using the granular
 
 Make sure you have installed [`@typescript-eslint/parser`] and [`eslint-import-resolver-typescript`] which are used in the following configuration.
 
-```yaml
-extends:
-  - eslint:recommended
-  - plugin:import/recommended
-# the following lines do the trick
-  - plugin:import/typescript
-settings:
-  import/resolver:
-    # You will also need to install and configure the TypeScript resolver
-    # See also https://github.com/import-js/eslint-import-resolver-typescript#configuration
-    typescript: true
-    node: true
+```jsonc
+{
+  "extends": [
+    "eslint:recommended",
+    "plugin:import/recommended",
+// the following lines do the trick
+    "plugin:import/typescript",
+  ],
+  "settings": {
+    "import/resolver": {
+      // You will also need to install and configure the TypeScript resolver
+      // See also https://github.com/import-js/eslint-import-resolver-typescript#configuration
+      "typescript": true,
+      "node": true,
+    },
+  },
+}
 ```
 
 [`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser
@@ -206,6 +213,16 @@ You can reference resolvers in several ways (in order of precedence):
 
  - as a conventional `eslint-import-resolver` name, like `eslint-import-resolver-foo`:
 
+ ```jsonc
+// .eslintrc
+{
+  "settings": {
+    // uses 'eslint-import-resolver-foo':
+    "import/resolver": "foo",
+  },
+}
+```
+
 ```yaml
 # .eslintrc.yml
 settings:
@@ -226,6 +243,15 @@ module.exports = {
 
  - with a full npm module name, like `my-awesome-npm-module`:
 
+```jsonc
+// .eslintrc
+{
+  "settings": {
+    "import/resolver": "my-awesome-npm-module",
+  },
+}
+```
+
 ```yaml
 # .eslintrc.yml
 settings:
@@ -321,11 +347,15 @@ In practice, this means rules other than [`no-unresolved`](./docs/rules/no-unres
 
 `no-unresolved` has its own [`ignore`](./docs/rules/no-unresolved.md#ignore) setting.
 
-```yaml
-settings:
-  import/ignore:
-    - \.coffee$          # fraught with parse errors
-    - \.(scss|less|css)$ # can't parse unprocessed CSS modules, either
+```jsonc
+{
+  "settings": {
+    "import/ignore": [
+      "\.coffee$", // fraught with parse errors
+      "\.(scss|less|css)$", // can't parse unprocessed CSS modules, either
+    ],
+  },
+}
 ```
 
 ### `import/core-modules`
@@ -344,10 +374,13 @@ import 'electron'  // without extra config, will be flagged as unresolved!
 that would otherwise be unresolved. To avoid this, you may provide `electron` as a
 core module:
 
-```yaml
-# .eslintrc.yml
-settings:
-  import/core-modules: [ electron ]
+```jsonc
+// .eslintrc
+{
+  "settings": {
+    "import/core-modules": ["electron"],
+  },
+}
 ```
 
 In Electron's specific case, there is a shared config named `electron`
@@ -380,11 +413,15 @@ dependency parser will require and use the map key as the parser instead of the
 configured ESLint parser. This is useful if you're inter-op-ing with TypeScript
 directly using webpack, for example:
 
-```yaml
-# .eslintrc.yml
-settings:
-  import/parsers:
-    "@typescript-eslint/parser": [ .ts, .tsx ]
+```jsonc
+// .eslintrc
+{
+  "settings": {
+    "import/parsers": {
+      "@typescript-eslint/parser": [".ts", ".tsx"],
+    },
+  },
+}
 ```
 
 In this case, [`@typescript-eslint/parser`](https://www.npmjs.com/package/@typescript-eslint/parser)
@@ -414,20 +451,28 @@ For long-lasting processes, like [`eslint_d`] or [`eslint-loader`], however, it'
 
 If you never use [`eslint_d`] or [`eslint-loader`], you may set the cache lifetime to `Infinity` and everything should be fine:
 
-```yaml
-# .eslintrc.yml
-settings:
-  import/cache:
-    lifetime: ∞  # or Infinity
+```jsonc
+// .eslintrc
+{
+  "settings": {
+    "import/cache": {
+      "lifetime": "∞", // or Infinity, in a JS config
+    },
+  },
+}
 ```
 
 Otherwise, set some integer, and cache entries will be evicted after that many seconds have elapsed:
 
-```yaml
-# .eslintrc.yml
-settings:
-  import/cache:
-    lifetime: 5  # 30 is the default
+```jsonc
+// .eslintrc
+{
+  "settings": {
+    "import/cache": {
+      "lifetime": 5, // 30 is the default
+    },
+  },
+}
 ```
 
 [`eslint_d`]: https://www.npmjs.com/package/eslint_d
@@ -441,10 +486,13 @@ By default, any package referenced from [`import/external-module-folders`](#impo
 
 For example, if your packages in a monorepo are all in `@scope`, you can configure `import/internal-regex` like this
 
-```yaml
-# .eslintrc.yml
-settings:
-  import/internal-regex: ^@scope/
+```jsonc
+// .eslintrc
+{
+  "settings": {
+    "import/internal-regex": "^@scope/",
+  },
+}
 ```
 
 ## SublimeLinter-eslint

From 8bdb32bc8be5364f4adeb781b2321ea62c9ab46e Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Tue, 3 Sep 2024 08:27:44 +1200
Subject: [PATCH 696/767] [Test] add explicit marker for trailing whitespace in
 cases

---
 tests/src/rules/dynamic-import-chunkname.js |  4 ++--
 tests/src/rules/no-duplicates.js            | 10 +++++-----
 tests/src/rules/no-import-module-exports.js |  6 +++---
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index 6afd834ab0..81e018af76 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -1001,7 +1001,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
           {
             desc: 'Remove webpackChunkName',
             output: `import(
-        
+        ${''}
         /* webpackMode: "eager" */
         'someModule'
       )`,
@@ -1010,7 +1010,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
             desc: 'Remove webpackMode',
             output: `import(
         /* webpackChunkName: "someModule" */
-        
+        ${''}
         'someModule'
       )`,
           },
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index e682f22354..c46f9df85d 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -455,28 +455,28 @@ import {x,y} from './foo'
         import {
           BULK_ACTIONS_ENABLED
         } from '../constants';
-        
+        ${''}
         const TestComponent = () => {
           return <div>
           </div>;
         }
-        
+        ${''}
         export default TestComponent;
       `,
       output: `
         import {
           DEFAULT_FILTER_KEYS,
           BULK_DISABLED,
-        
+        ${''}
           BULK_ACTIONS_ENABLED
         } from '../constants';
         import React from 'react';
-                
+                ${''}
         const TestComponent = () => {
           return <div>
           </div>;
         }
-        
+        ${''}
         export default TestComponent;
       `,
       errors: ["'../constants' imported multiple times.", "'../constants' imported multiple times."],
diff --git a/tests/src/rules/no-import-module-exports.js b/tests/src/rules/no-import-module-exports.js
index c2bf7ed132..aa927857e0 100644
--- a/tests/src/rules/no-import-module-exports.js
+++ b/tests/src/rules/no-import-module-exports.js
@@ -74,13 +74,13 @@ ruleTester.run('no-import-module-exports', rule, {
         import fs from 'fs/promises';
 
         const subscriptions = new Map();
-        
+        ${''}
         export default async (client) => {
             /**
              * loads all modules and their subscriptions
              */
             const modules = await fs.readdir('./src/modules');
-        
+        ${''}
             await Promise.all(
                 modules.map(async (moduleName) => {
                     // Loads the module
@@ -97,7 +97,7 @@ ruleTester.run('no-import-module-exports', rule, {
                     }
                 })
             );
-        
+        ${''}
             /**
              * Setting up all events.
              * binds all events inside the subscriptions map to call all functions provided

From a3015ebd1bb6251990aee79e292d7116e9f191ff Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Tue, 3 Sep 2024 13:19:35 +1200
Subject: [PATCH 697/767] [Test] `namespace`: ensure valid case is actually
 included

---
 tests/src/rules/namespace.js | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 1475ae9b7d..3f768a5717 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -336,10 +336,10 @@ const invalid = [].concat(
     test({ parser, code: `import { b } from "./${folder}/a"; console.log(b.c.d.e)` }),
     test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.c.d.e.f)` }),
     test({ parser, code: `import * as a from "./${folder}/a"; var {b:{c:{d:{e}}}} = a` }),
-    test({ parser, code: `import { b } from "./${folder}/a"; var {c:{d:{e}}} = b` }));
-
-  // deep namespaces should include explicitly exported defaults
-  test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.default)` }),
+    test({ parser, code: `import { b } from "./${folder}/a"; var {c:{d:{e}}} = b` }),
+    // deep namespaces should include explicitly exported defaults
+    test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.default)` }),
+  );
 
   invalid.push(
     test({
@@ -371,7 +371,8 @@ const invalid = [].concat(
       parser,
       code: `import * as a from "./${folder}/a"; var {b:{c:{ e }}} = a`,
       errors: ["'e' not found in deeply imported namespace 'a.b.c'."],
-    }));
+    }),
+  );
 });
 
 ruleTester.run('namespace', rule, { valid, invalid });

From 0a58d7572c8267203182043608d56ead1c50f4ce Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 2 Sep 2024 23:05:07 -0700
Subject: [PATCH 698/767] [resolvers/webpack] v0.13.9

---
 resolvers/webpack/CHANGELOG.md | 3 +++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index cd49cc3f4e..79b2837e3d 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -5,7 +5,10 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## 0.13.9 - 2024-09-02
 - [refactor] simplify loop ([#3029], thanks [@fregante])
+- [meta] add `repository.directory` field
+- [refactor] avoid hoisting, misc cleanup
 
 ## 0.13.8 - 2023-10-22
  - [refactor] use `hasown` instead of `has`
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 38465bcdee..60e5c900f0 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.8",
+  "version": "0.13.9",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 9d194a6e4690cc8afed68cb7736a81dd3a919135 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 2 Sep 2024 23:07:55 -0700
Subject: [PATCH 699/767] [utils] v2.9.0

---
 utils/CHANGELOG.md | 7 +++++++
 utils/package.json | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 43bd0e022b..27102bc73a 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.9.0 - 2024-09-02
+
+### New
+- add support for Flat Config ([#3018], thanks [@michaelfaith])
+
 ## v2.8.2 - 2024-08-25
 
 ### Fixed
@@ -151,6 +156,7 @@ Yanked due to critical issue with cache key resulting from #839.
 - `unambiguous.test()` regex is now properly in multiline mode
 
 [#3039]: https://github.com/import-js/eslint-plugin-import/pull/3039
+[#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
 [#2963]: https://github.com/import-js/eslint-plugin-import/pull/2963
 [#2755]: https://github.com/import-js/eslint-plugin-import/pull/2755
 [#2714]: https://github.com/import-js/eslint-plugin-import/pull/2714
@@ -197,6 +203,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@manuth]: https://github.com/manuth
 [@maxkomarychev]: https://github.com/maxkomarychev
 [@mgwalker]: https://github.com/mgwalker
+[@michaelfaith]: https://github.com/michaelfaith
 [@Mysak0CZ]: https://github.com/Mysak0CZ
 [@nicolo-ribaudo]: https://github.com/nicolo-ribaudo
 [@pmcelhaney]: https://github.com/pmcelhaney
diff --git a/utils/package.json b/utils/package.json
index 6d69e2414a..fe3541ada3 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.8.2",
+  "version": "2.9.0",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From 990229879c6790d64f3673ac59b0c9a9736f79fe Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 2 Sep 2024 23:09:11 -0700
Subject: [PATCH 700/767] [Deps] update `eslint-module-utils`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index f9a95fabb4..72c4a8259a 100644
--- a/package.json
+++ b/package.json
@@ -117,7 +117,7 @@
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
-    "eslint-module-utils": "^2.8.2",
+    "eslint-module-utils": "^2.9.0",
     "hasown": "^2.0.2",
     "is-core-module": "^2.15.1",
     "is-glob": "^4.0.3",

From 18787d3e6966028983af81a878d1a505893932d4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 2 Sep 2024 23:09:39 -0700
Subject: [PATCH 701/767] Bump to 2.30.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9022dc887b..cf97fff94d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.30.0] - 2024-09-02
+
 ### Added
 - [`dynamic-import-chunkname`]: add `allowEmpty` option to allow empty leading comments ([#2942], thanks [@JiangWeixian])
 - [`dynamic-import-chunkname`]: Allow empty chunk name when webpackMode: 'eager' is set; add suggestions to remove name in eager mode ([#3004], thanks [@amsardesai])
@@ -1615,7 +1617,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.1...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.30.0...HEAD
+[2.30.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.1...v2.30.0
 [2.29.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.0...v2.29.1
 [2.29.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.1...v2.29.0
 [2.28.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.0...v2.28.1
diff --git a/package.json b/package.json
index 72c4a8259a..be150064d6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.29.1",
+  "version": "2.30.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 186f248357437ef46889f3eab7fda8e6030ba874 Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Thu, 5 Sep 2024 06:29:19 -0500
Subject: [PATCH 702/767] [Fix] `ExportMap` / flat config: include
 `languageOptions` in context

This change fixes a bug with flat config support.
There is a function called `childContext` that's used by the ExportBuilder to "cleanse" the context object.
This function wasn't including the new `languageOptions` object, which contains the parser.
So by the time this cleansed context made it to the parse function, `languageOptions` wasn't there anymore.

Since `parserPath` was still being included in non-flat config scenarios, the parse function made it through ok and used `parserPath`.
However, once you shift to flat config, `parserPath` is no longer defined, and the actual parser object needs to be there.

Fixes #3051
---
 CHANGELOG.md                        |  4 +++
 src/exportMap/childContext.js       |  3 +-
 tests/src/exportMap/childContext.js | 51 +++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+), 1 deletion(-)
 create mode 100644 tests/src/exportMap/childContext.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf97fff94d..4efcdb5bc0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Fixed
+- `ExportMap` / flat config: include `languageOptions` in context ([#3052], thanks [@michaelfaith])
+
 ## [2.30.0] - 2024-09-02
 
 ### Added
@@ -1129,6 +1132,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3052]: https://github.com/import-js/eslint-plugin-import/pull/3052
 [#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
 [#3033]: https://github.com/import-js/eslint-plugin-import/pull/3033
 [#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
diff --git a/src/exportMap/childContext.js b/src/exportMap/childContext.js
index 5f82b8e575..3534c59138 100644
--- a/src/exportMap/childContext.js
+++ b/src/exportMap/childContext.js
@@ -10,7 +10,7 @@ let prevSettings = '';
  * also calculate a cacheKey, where parts of the cacheKey hash are memoized
  */
 export default function childContext(path, context) {
-  const { settings, parserOptions, parserPath } = context;
+  const { settings, parserOptions, parserPath, languageOptions } = context;
 
   if (JSON.stringify(settings) !== prevSettings) {
     settingsHash = hashObject({ settings }).digest('hex');
@@ -28,5 +28,6 @@ export default function childContext(path, context) {
     parserOptions,
     parserPath,
     path,
+    languageOptions,
   };
 }
diff --git a/tests/src/exportMap/childContext.js b/tests/src/exportMap/childContext.js
new file mode 100644
index 0000000000..06fa04afec
--- /dev/null
+++ b/tests/src/exportMap/childContext.js
@@ -0,0 +1,51 @@
+import { expect } from 'chai';
+
+import childContext from '../../../src/exportMap/childContext';
+
+describe('childContext', () => {
+  const settings = {
+    setting1: true,
+    setting2: false,
+  };
+  const parserOptions = {
+    ecmaVersion: 'latest',
+    sourceType: 'module',
+  };
+  const parserPath = 'path/to/parser';
+  const path = 'path/to/src/file';
+  const languageOptions = {
+    ecmaVersion: 2024,
+    sourceType: 'module',
+    parser: {},
+  };
+
+  // https://github.com/import-js/eslint-plugin-import/issues/3051
+  it('should pass context properties through, if present', () => {
+    const mockContext = {
+      settings,
+      parserOptions,
+      parserPath,
+      languageOptions,
+    };
+
+    const result = childContext(path, mockContext);
+
+    expect(result.settings).to.deep.equal(settings);
+    expect(result.parserOptions).to.deep.equal(parserOptions);
+    expect(result.parserPath).to.equal(parserPath);
+    expect(result.languageOptions).to.deep.equal(languageOptions);
+  });
+
+  it('should add path and cacheKey to context', () => {
+    const mockContext = {
+      settings,
+      parserOptions,
+      parserPath,
+    };
+
+    const result = childContext(path, mockContext);
+
+    expect(result.path).to.equal(path);
+    expect(result.cacheKey).to.be.a('string');
+  });
+});

From 6012bd7f3eddb84aed4be9c3a95b3827f6ef9540 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 5 Sep 2024 11:18:52 -0700
Subject: [PATCH 703/767] [meta] fix links in old changelog entries

---
 CHANGELOG.md | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4efcdb5bc0..88fd1dbc27 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -65,7 +65,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-duplicates`]: remove duplicate identifiers in duplicate imports ([#2577], thanks [@joe-matsec])
 - [`consistent-type-specifier-style`]: fix accidental removal of comma in certain cases ([#2754], thanks [@bradzacher])
 - [Perf] `ExportMap`: Improve `ExportMap.for` performance on larger codebases ([#2756], thanks [@leipert])
-- [`no-extraneous-dependencies`]/TypeScript: do not error when importing inline type from dev dependencies ([#1820], thanks [@andyogo])
+- [`no-extraneous-dependencies`]/TypeScript: do not error when importing inline type from dev dependencies ([#2735], thanks [@andyogo])
 - [`newline-after-import`]/TypeScript: do not error when re-exporting a namespaced import ([#2832], thanks [@laurens-dg])
 - [`order`]: partial fix for [#2687] (thanks [@ljharb])
 - [`no-duplicates`]: Detect across type and regular imports ([#2835], thanks [@benkrejci])
@@ -321,7 +321,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-webpack-loader-syntax`]/TypeScript: avoid crash on missing name ([#1947], thanks [@leonardodino])
 - [`no-extraneous-dependencies`]: Add package.json cache ([#1948], thanks [@fa93hws])
 - [`prefer-default-export`]: handle empty array destructuring ([#1965], thanks [@ljharb])
-- [`no-unused-modules`]: make type imports mark a module as used (fixes #1924) ([#1974], thanks [@cherryblossom000])
+- [`no-unused-modules`]: make type imports mark a module as used (fixes [#1924]) ([#1974], thanks [@cherryblossom000])
 - [`no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
 - [`first`]: fix handling of `import = require` ([#1963], thanks [@MatthiasKunnen])
 - [`no-cycle`]/[`extensions`]: fix isExternalModule usage ([#1696], thanks [@paztis])
@@ -349,7 +349,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`dynamic-import-chunkname`]: allow single quotes to match Webpack support ([#1848], thanks [@straub])
 
 ### Changed
-- [`export`]: add tests for a name collision with `export * from` ([#1704], thanks @tomprats)
+- [`export`]: add tests for a name collision with `export * from` ([#1704], thanks [@tomprats])
 
 ## [2.22.0] - 2020-06-26
 
@@ -1473,10 +1473,7 @@ for info on changes for earlier releases.
 [#297]: https://github.com/import-js/eslint-plugin-import/pull/297
 [#296]: https://github.com/import-js/eslint-plugin-import/pull/296
 [#290]: https://github.com/import-js/eslint-plugin-import/pull/290
-[#289]: https://github.com/import-js/eslint-plugin-import/pull/289
 [#288]: https://github.com/import-js/eslint-plugin-import/pull/288
-[#287]: https://github.com/import-js/eslint-plugin-import/pull/287
-[#278]: https://github.com/import-js/eslint-plugin-import/pull/278
 [#261]: https://github.com/import-js/eslint-plugin-import/pull/261
 [#256]: https://github.com/import-js/eslint-plugin-import/pull/256
 [#254]: https://github.com/import-js/eslint-plugin-import/pull/254
@@ -1488,7 +1485,6 @@ for info on changes for earlier releases.
 [#239]: https://github.com/import-js/eslint-plugin-import/pull/239
 [#228]: https://github.com/import-js/eslint-plugin-import/pull/228
 [#211]: https://github.com/import-js/eslint-plugin-import/pull/211
-[#164]: https://github.com/import-js/eslint-plugin-import/pull/164
 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157
 
 [ljharb#37]: https://github.com/ljharb/eslint-plugin-import/pull/37
@@ -1601,7 +1597,6 @@ for info on changes for earlier releases.
 [#313]: https://github.com/import-js/eslint-plugin-import/issues/313
 [#311]: https://github.com/import-js/eslint-plugin-import/issues/311
 [#306]: https://github.com/import-js/eslint-plugin-import/issues/306
-[#286]: https://github.com/import-js/eslint-plugin-import/issues/286
 [#283]: https://github.com/import-js/eslint-plugin-import/issues/283
 [#281]: https://github.com/import-js/eslint-plugin-import/issues/281
 [#275]: https://github.com/import-js/eslint-plugin-import/issues/275
@@ -1651,10 +1646,9 @@ for info on changes for earlier releases.
 [2.22.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.21.1...v2.22.0
 [2.21.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.21.1...v2.21.2
 [2.21.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.21.0...v2.21.1
-[2.21.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.20.2...v2.21.0
-[2.20.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.20.1...v2.20.2
-[2.20.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.20.0...v2.20.1
-[2.19.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.19.1...v2.20.0
+[2.21.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.20.1...v2.21.0
+[2.20.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.20.0...v2.20.1
+[2.20.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.19.1...v2.20.0
 [2.19.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.19.0...v2.19.1
 [2.19.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.18.2...v2.19.0
 [2.18.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.18.1...v2.18.2
@@ -1966,7 +1960,6 @@ for info on changes for earlier releases.
 [@sveyret]: https://github.com/sveyret
 [@swernerx]: https://github.com/swernerx
 [@syymza]: https://github.com/syymza
-[@taion]: https://github.com/taion
 [@TakeScoop]: https://github.com/TakeScoop
 [@tapayne88]: https://github.com/tapayne88
 [@Taranys]: https://github.com/Taranys

From 1079e70f36a73c65ea0e69d079654656bf5cc4ba Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Wed, 4 Sep 2024 04:03:47 -0500
Subject: [PATCH 704/767] [utils] [new] add context compatibility helpers

This change adds helper functions to `eslint-module-utils` in order to add eslint v9 support to `eslint-plugin-import` in a backwards compatible way.

Contributes to #2996
---
 utils/CHANGELOG.md       |  4 +++
 utils/contextCompat.d.ts | 38 +++++++++++++++++++++
 utils/contextCompat.js   | 72 ++++++++++++++++++++++++++++++++++++++++
 utils/package.json       |  1 +
 utils/resolve.js         |  3 +-
 5 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 utils/contextCompat.d.ts
 create mode 100644 utils/contextCompat.js

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 27102bc73a..df6b727ad4 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### New
+- add context compatibility helpers ([#3049], thanks [@michaelfaith])
+
 ## v2.9.0 - 2024-09-02
 
 ### New
@@ -155,6 +158,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#3049]: https://github.com/import-js/eslint-plugin-import/pull/3049
 [#3039]: https://github.com/import-js/eslint-plugin-import/pull/3039
 [#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
 [#2963]: https://github.com/import-js/eslint-plugin-import/pull/2963
diff --git a/utils/contextCompat.d.ts b/utils/contextCompat.d.ts
new file mode 100644
index 0000000000..43fe0a91b8
--- /dev/null
+++ b/utils/contextCompat.d.ts
@@ -0,0 +1,38 @@
+import { Scope, SourceCode, Rule } from 'eslint';
+import * as ESTree from 'estree';
+
+type LegacyContext = {
+  getFilename: () => string,
+  getPhysicalFilename: () => string,
+  getSourceCode: () => SourceCode,
+  getScope: never,
+  getAncestors: never,
+  getDeclaredVariables: never,
+};
+
+type NewContext = {
+  filename: string,
+  sourceCode: SourceCode,
+  getPhysicalFilename?: () => string,
+  getScope: () => Scope.Scope,
+  getAncestors: () => ESTree.Node[],
+  getDeclaredVariables: (node: ESTree.Node) => Scope.Variable[],
+};
+
+export type Context = LegacyContext | NewContext | Rule.RuleContext;
+
+declare function getAncestors(context: Context, node: ESTree.Node): ESTree.Node[];
+declare function getDeclaredVariables(context: Context, node: ESTree.Node): Scope.Variable[];
+declare function getFilename(context: Context): string;
+declare function getPhysicalFilename(context: Context): string;
+declare function getScope(context: Context, node: ESTree.Node): Scope.Scope;
+declare function getSourceCode(context: Context): SourceCode;
+
+export {
+  getAncestors,
+  getDeclaredVariables,
+  getFilename,
+  getPhysicalFilename,
+  getScope,
+  getSourceCode,
+};
diff --git a/utils/contextCompat.js b/utils/contextCompat.js
new file mode 100644
index 0000000000..b1bdc598ef
--- /dev/null
+++ b/utils/contextCompat.js
@@ -0,0 +1,72 @@
+'use strict';
+
+exports.__esModule = true;
+
+/** @type {import('./contextCompat').getAncestors} */
+function getAncestors(context, node) {
+  const sourceCode = getSourceCode(context);
+
+  if (sourceCode && sourceCode.getAncestors) {
+    return sourceCode.getAncestors(node);
+  }
+
+  return context.getAncestors();
+}
+
+/** @type {import('./contextCompat').getDeclaredVariables} */
+function getDeclaredVariables(context, node) {
+  const sourceCode = getSourceCode(context);
+
+  if (sourceCode && sourceCode.getDeclaredVariables) {
+    return sourceCode.getDeclaredVariables(node);
+  }
+
+  return context.getDeclaredVariables(node);
+}
+
+/** @type {import('./contextCompat').getFilename} */
+function getFilename(context) {
+  if ('filename' in context) {
+    return context.filename;
+  }
+
+  return context.getFilename();
+}
+
+/** @type {import('./contextCompat').getPhysicalFilename} */
+function getPhysicalFilename(context) {
+  if (context.getPhysicalFilename) {
+    return context.getPhysicalFilename();
+  }
+
+  return getFilename(context);
+}
+
+/** @type {import('./contextCompat').getScope} */
+function getScope(context, node) {
+  const sourceCode = getSourceCode(context);
+
+  if (sourceCode && sourceCode.getScope) {
+    return sourceCode.getScope(node);
+  }
+
+  return context.getScope();
+}
+
+/** @type {import('./contextCompat').getSourceCode} */
+function getSourceCode(context) {
+  if ('sourceCode' in context) {
+    return context.sourceCode;
+  }
+
+  return context.getSourceCode();
+}
+
+module.exports = {
+  getAncestors,
+  getDeclaredVariables,
+  getFilename,
+  getPhysicalFilename,
+  getScope,
+  getSourceCode,
+};
diff --git a/utils/package.json b/utils/package.json
index fe3541ada3..d5968f7e9d 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -7,6 +7,7 @@
   },
   "main": false,
   "exports": {
+    "./contextCompat": "./contextCompat.js",
     "./ModuleCache": "./ModuleCache.js",
     "./ModuleCache.js": "./ModuleCache.js",
     "./declaredScope": "./declaredScope.js",
diff --git a/utils/resolve.js b/utils/resolve.js
index 5a3084351e..b332d2ec2c 100644
--- a/utils/resolve.js
+++ b/utils/resolve.js
@@ -5,6 +5,7 @@ exports.__esModule = true;
 const fs = require('fs');
 const Module = require('module');
 const path = require('path');
+const { getPhysicalFilename } = require('./contextCompat');
 
 const hashObject = require('./hash').hashObject;
 const ModuleCache = require('./ModuleCache').default;
@@ -229,7 +230,7 @@ const erroredContexts = new Set();
  */
 function resolve(p, context) {
   try {
-    return relative(p, context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(), context.settings);
+    return relative(p, getPhysicalFilename(context), context.settings);
   } catch (err) {
     if (!erroredContexts.has(context)) {
       // The `err.stack` string starts with `err.name` followed by colon and `err.message`.

From 756fe8e3c8d776ba0f395665e122e28c3b90fbf6 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 5 Sep 2024 15:52:35 -0700
Subject: [PATCH 705/767] [utils] v2.10.0

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index df6b727ad4..089219e7d6 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.10.0 - 2024-09-05
+
 ### New
 - add context compatibility helpers ([#3049], thanks [@michaelfaith])
 
diff --git a/utils/package.json b/utils/package.json
index d5968f7e9d..f7afde88f9 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.9.0",
+  "version": "2.10.0",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From a7b43480ca3802b8be104717c81dbd57c766cf93 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 5 Sep 2024 14:19:37 -0700
Subject: [PATCH 706/767] [Refactor] use `contextCompat` helpers

---
 package.json                                 |  2 +-
 src/core/packagePath.js                      |  3 ++-
 src/rules/consistent-type-specifier-style.js |  4 +++-
 src/rules/dynamic-import-chunkname.js        |  4 +++-
 src/rules/first.js                           |  6 ++++--
 src/rules/named.js                           |  6 ++++--
 src/rules/newline-after-import.js            |  4 +++-
 src/rules/no-absolute-path.js                |  5 +++--
 src/rules/no-amd.js                          |  4 +++-
 src/rules/no-commonjs.js                     |  6 ++++--
 src/rules/no-cycle.js                        |  6 ++++--
 src/rules/no-default-export.js               |  6 ++++--
 src/rules/no-duplicates.js                   |  3 ++-
 src/rules/no-empty-named-blocks.js           |  4 +++-
 src/rules/no-extraneous-dependencies.js      |  8 ++++---
 src/rules/no-import-module-exports.js        |  7 ++++---
 src/rules/no-mutable-exports.js              |  6 ++++--
 src/rules/no-namespace.js                    |  6 ++++--
 src/rules/no-relative-packages.js            |  3 ++-
 src/rules/no-relative-parent-imports.js      |  7 ++++---
 src/rules/no-restricted-paths.js             |  7 ++++---
 src/rules/no-self-import.js                  |  4 +++-
 src/rules/no-unassigned-import.js            |  3 ++-
 src/rules/no-unused-modules.js               |  3 ++-
 src/rules/no-useless-path-segments.js        |  3 ++-
 src/rules/order.js                           | 22 +++++++++++++-------
 26 files changed, 93 insertions(+), 49 deletions(-)

diff --git a/package.json b/package.json
index be150064d6..90b9df4da8 100644
--- a/package.json
+++ b/package.json
@@ -117,7 +117,7 @@
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
-    "eslint-module-utils": "^2.9.0",
+    "eslint-module-utils": "^2.10.0",
     "hasown": "^2.0.2",
     "is-core-module": "^2.15.1",
     "is-glob": "^4.0.3",
diff --git a/src/core/packagePath.js b/src/core/packagePath.js
index 142f44aa4d..f45f543260 100644
--- a/src/core/packagePath.js
+++ b/src/core/packagePath.js
@@ -1,4 +1,5 @@
 import { dirname } from 'path';
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 import pkgUp from 'eslint-module-utils/pkgUp';
 import readPkgUp from 'eslint-module-utils/readPkgUp';
 
@@ -8,7 +9,7 @@ export function getFilePackagePath(filePath) {
 }
 
 export function getContextPackagePath(context) {
-  return getFilePackagePath(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
+  return getFilePackagePath(getPhysicalFilename(context));
 }
 
 export function getFilePackageName(filePath) {
diff --git a/src/rules/consistent-type-specifier-style.js b/src/rules/consistent-type-specifier-style.js
index 9119976b19..ee5ff9fbc6 100644
--- a/src/rules/consistent-type-specifier-style.js
+++ b/src/rules/consistent-type-specifier-style.js
@@ -1,3 +1,5 @@
+import { getSourceCode } from 'eslint-module-utils/contextCompat';
+
 import docsUrl from '../docsUrl';
 
 function isComma(token) {
@@ -55,7 +57,7 @@ module.exports = {
   },
 
   create(context) {
-    const sourceCode = context.getSourceCode();
+    const sourceCode = getSourceCode(context);
 
     if (context.options[0] === 'prefer-inline') {
       return {
diff --git a/src/rules/dynamic-import-chunkname.js b/src/rules/dynamic-import-chunkname.js
index a72b04d123..12a7650082 100644
--- a/src/rules/dynamic-import-chunkname.js
+++ b/src/rules/dynamic-import-chunkname.js
@@ -1,4 +1,6 @@
+import { getSourceCode } from 'eslint-module-utils/contextCompat';
 import vm from 'vm';
+
 import docsUrl from '../docsUrl';
 
 module.exports = {
@@ -43,7 +45,7 @@ module.exports = {
     const eagerModeRegex = new RegExp(eagerModeFormat);
 
     function run(node, arg) {
-      const sourceCode = context.getSourceCode();
+      const sourceCode = getSourceCode(context);
       const leadingComments = sourceCode.getCommentsBefore
         ? sourceCode.getCommentsBefore(arg) // This method is available in ESLint >= 4.
         : sourceCode.getComments(arg).leading; // This method is deprecated in ESLint 7.
diff --git a/src/rules/first.js b/src/rules/first.js
index f8cc273a31..e7df26ac92 100644
--- a/src/rules/first.js
+++ b/src/rules/first.js
@@ -1,3 +1,5 @@
+import { getDeclaredVariables, getSourceCode } from 'eslint-module-utils/contextCompat';
+
 import docsUrl from '../docsUrl';
 
 function getImportValue(node) {
@@ -38,7 +40,7 @@ module.exports = {
         }
         const absoluteFirst = context.options[0] === 'absolute-first';
         const message = 'Import in body of module; reorder to top.';
-        const sourceCode = context.getSourceCode();
+        const sourceCode = getSourceCode(context);
         const originSourceCode = sourceCode.getText();
         let nonImportCount = 0;
         let anyExpressions = false;
@@ -66,7 +68,7 @@ module.exports = {
               }
             }
             if (nonImportCount > 0) {
-              for (const variable of context.getDeclaredVariables(node)) {
+              for (const variable of getDeclaredVariables(context, node)) {
                 if (!shouldSort) { break; }
                 const references = variable.references;
                 if (references.length) {
diff --git a/src/rules/named.js b/src/rules/named.js
index ed7e5e018b..ab5f3103f2 100644
--- a/src/rules/named.js
+++ b/src/rules/named.js
@@ -1,4 +1,6 @@
 import * as path from 'path';
+import { getFilename, getPhysicalFilename } from 'eslint-module-utils/contextCompat';
+
 import ExportMapBuilder from '../exportMap/builder';
 import docsUrl from '../docsUrl';
 
@@ -67,7 +69,7 @@ module.exports = {
         if (!deepLookup.found) {
           if (deepLookup.path.length > 1) {
             const deepPath = deepLookup.path
-              .map((i) => path.relative(path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename()), i.path))
+              .map((i) => path.relative(path.dirname(getPhysicalFilename(context)), i.path))
               .join(' -> ');
 
             context.report(im[key], `${name} not found via ${deepPath}`);
@@ -121,7 +123,7 @@ module.exports = {
         if (!deepLookup.found) {
           if (deepLookup.path.length > 1) {
             const deepPath = deepLookup.path
-              .map((i) => path.relative(path.dirname(context.getFilename()), i.path))
+              .map((i) => path.relative(path.dirname(getFilename(context)), i.path))
               .join(' -> ');
 
             context.report(im.key, `${im.key.name} not found via ${deepPath}`);
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index d10b87d78c..bf550bad95 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -3,6 +3,8 @@
  * @author Radek Benkel
  */
 
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
+
 import isStaticRequire from '../core/staticRequire';
 import docsUrl from '../docsUrl';
 
@@ -193,7 +195,7 @@ module.exports = {
         }
       },
       'Program:exit'() {
-        log('exit processing for', context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
+        log('exit processing for', getPhysicalFilename(context));
         const scopeBody = getScopeBody(context.getScope());
         log('got scope:', scopeBody);
 
diff --git a/src/rules/no-absolute-path.js b/src/rules/no-absolute-path.js
index 04f67383f2..0dbd8cb86c 100644
--- a/src/rules/no-absolute-path.js
+++ b/src/rules/no-absolute-path.js
@@ -1,5 +1,7 @@
 import path from 'path';
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
+
 import { isAbsolute } from '../core/importType';
 import docsUrl from '../docsUrl';
 
@@ -22,9 +24,8 @@ module.exports = {
           node: source,
           message: 'Do not import modules using an absolute path',
           fix(fixer) {
-            const resolvedContext = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
             // node.js and web imports work with posix style paths ("/")
-            let relativePath = path.posix.relative(path.dirname(resolvedContext), source.value);
+            let relativePath = path.posix.relative(path.dirname(getPhysicalFilename(context)), source.value);
             if (!relativePath.startsWith('.')) {
               relativePath = `./${relativePath}`;
             }
diff --git a/src/rules/no-amd.js b/src/rules/no-amd.js
index 5edfe3e698..05ed0a5210 100644
--- a/src/rules/no-amd.js
+++ b/src/rules/no-amd.js
@@ -3,6 +3,8 @@
  * @author Jamund Ferguson
  */
 
+import { getScope } from 'eslint-module-utils/contextCompat';
+
 import docsUrl from '../docsUrl';
 
 //------------------------------------------------------------------------------
@@ -23,7 +25,7 @@ module.exports = {
   create(context) {
     return {
       CallExpression(node) {
-        if (context.getScope().type !== 'module') { return; }
+        if (getScope(context, node).type !== 'module') { return; }
 
         if (node.callee.type !== 'Identifier') { return; }
         if (node.callee.name !== 'require' && node.callee.name !== 'define') { return; }
diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js
index dde509222b..33b77da597 100644
--- a/src/rules/no-commonjs.js
+++ b/src/rules/no-commonjs.js
@@ -3,6 +3,8 @@
  * @author Jamund Ferguson
  */
 
+import { getScope } from 'eslint-module-utils/contextCompat';
+
 import docsUrl from '../docsUrl';
 
 const EXPORT_MESSAGE = 'Expected "export" or "export default"';
@@ -107,7 +109,7 @@ module.exports = {
 
         // exports.
         if (node.object.name === 'exports') {
-          const isInScope = context.getScope()
+          const isInScope = getScope(context, node)
             .variables
             .some((variable) => variable.name === 'exports');
           if (!isInScope) {
@@ -117,7 +119,7 @@ module.exports = {
 
       },
       CallExpression(call) {
-        if (!validateScope(context.getScope())) { return; }
+        if (!validateScope(getScope(context, call))) { return; }
 
         if (call.callee.type !== 'Identifier') { return; }
         if (call.callee.name !== 'require') { return; }
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index be8c288dd4..d7c748d807 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -3,11 +3,13 @@
  * @author Ben Mosher
  */
 
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
+import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import resolve from 'eslint-module-utils/resolve';
+
 import ExportMapBuilder from '../exportMap/builder';
 import StronglyConnectedComponentsBuilder from '../scc';
 import { isExternalModule } from '../core/importType';
-import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import docsUrl from '../docsUrl';
 
 const traversed = new Set();
@@ -57,7 +59,7 @@ module.exports = {
   },
 
   create(context) {
-    const myPath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+    const myPath = getPhysicalFilename(context);
     if (myPath === '<text>') { return {}; } // can't cycle-check a non-file
 
     const options = context.options[0] || {};
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index dabbae543a..fcb4f1b2fd 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -1,3 +1,5 @@
+import { getSourceCode } from 'eslint-module-utils/contextCompat';
+
 import docsUrl from '../docsUrl';
 
 module.exports = {
@@ -22,7 +24,7 @@ module.exports = {
 
     return {
       ExportDefaultDeclaration(node) {
-        const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {};
+        const { loc } = getSourceCode(context).getFirstTokens(node)[1] || {};
         context.report({ node, message: preferNamed, loc });
       },
 
@@ -30,7 +32,7 @@ module.exports = {
         node.specifiers
           .filter((specifier) => (specifier.exported.name || specifier.exported.value) === 'default')
           .forEach((specifier) => {
-            const { loc } = context.getSourceCode().getFirstTokens(node)[1] || {};
+            const { loc } = getSourceCode(context).getFirstTokens(node)[1] || {};
             if (specifier.type === 'ExportDefaultSpecifier') {
               context.report({ node, message: preferNamed, loc });
             } else if (specifier.type === 'ExportSpecifier') {
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index d9fb1a1309..32557802fa 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -1,3 +1,4 @@
+import { getSourceCode } from 'eslint-module-utils/contextCompat';
 import resolve from 'eslint-module-utils/resolve';
 import semver from 'semver';
 import flatMap from 'array.prototype.flatmap';
@@ -260,7 +261,7 @@ function checkImports(imported, context) {
     if (nodes.length > 1) {
       const message = `'${module}' imported multiple times.`;
       const [first, ...rest] = nodes;
-      const sourceCode = context.getSourceCode();
+      const sourceCode = getSourceCode(context);
       const fix = getFix(first, rest, sourceCode, context);
 
       context.report({
diff --git a/src/rules/no-empty-named-blocks.js b/src/rules/no-empty-named-blocks.js
index 3ec1501b8f..d68ecee38b 100644
--- a/src/rules/no-empty-named-blocks.js
+++ b/src/rules/no-empty-named-blocks.js
@@ -1,3 +1,5 @@
+import { getSourceCode } from 'eslint-module-utils/contextCompat';
+
 import docsUrl from '../docsUrl';
 
 function getEmptyBlockRange(tokens, index) {
@@ -72,7 +74,7 @@ module.exports = {
                       fix(fixer) {
                         // Remove the empty block and the 'from' token, leaving the import only for its side
                         // effects, e.g. `import 'mod'`
-                        const sourceCode = context.getSourceCode();
+                        const sourceCode = getSourceCode(context);
                         const fromToken = program.tokens.find((t) => t.value === 'from');
                         const importToken = program.tokens.find((t) => t.value === 'import');
                         const hasSpaceAfterFrom = sourceCode.isSpaceBetween(fromToken, sourceCode.getTokenAfter(fromToken));
diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js
index 0fe42f56f8..bf0a1ed477 100644
--- a/src/rules/no-extraneous-dependencies.js
+++ b/src/rules/no-extraneous-dependencies.js
@@ -1,9 +1,11 @@
 import path from 'path';
 import fs from 'fs';
-import pkgUp from 'eslint-module-utils/pkgUp';
 import minimatch from 'minimatch';
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
+import pkgUp from 'eslint-module-utils/pkgUp';
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
+
 import importType from '../core/importType';
 import { getFilePackageName } from '../core/packagePath';
 import docsUrl from '../docsUrl';
@@ -84,7 +86,7 @@ function getDependencies(context, packageDir) {
       });
     } else {
       const packageJsonPath = pkgUp({
-        cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename(),
+        cwd: getPhysicalFilename(context),
         normalize: false,
       });
 
@@ -283,7 +285,7 @@ module.exports = {
 
   create(context) {
     const options = context.options[0] || {};
-    const filename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+    const filename = getPhysicalFilename(context);
     const deps = getDependencies(context, options.packageDir) || extractDepFields({});
 
     const depsOptions = {
diff --git a/src/rules/no-import-module-exports.js b/src/rules/no-import-module-exports.js
index bc4605c39d..bf6fba61bd 100644
--- a/src/rules/no-import-module-exports.js
+++ b/src/rules/no-import-module-exports.js
@@ -1,9 +1,10 @@
 import minimatch from 'minimatch';
 import path from 'path';
+import { getPhysicalFilename, getSourceCode } from 'eslint-module-utils/contextCompat';
 import pkgUp from 'eslint-module-utils/pkgUp';
 
 function getEntryPoint(context) {
-  const pkgPath = pkgUp({ cwd: context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename() });
+  const pkgPath = pkgUp({ cwd: getPhysicalFilename(context) });
   try {
     return require.resolve(path.dirname(pkgPath));
   } catch (error) {
@@ -14,7 +15,7 @@ function getEntryPoint(context) {
 }
 
 function findScope(context, identifier) {
-  const { scopeManager } = context.getSourceCode();
+  const { scopeManager } = getSourceCode(context);
 
   return scopeManager && scopeManager.scopes.slice().reverse().find((scope) => scope.variables.some((variable) => variable.identifiers.some((node) => node.name === identifier)));
 }
@@ -50,7 +51,7 @@ module.exports = {
     let alreadyReported = false;
 
     function report(node) {
-      const fileName = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+      const fileName = getPhysicalFilename(context);
       const isEntryPoint = entryPoint === fileName;
       const isIdentifier = node.object.type === 'Identifier';
       const hasKeywords = (/^(module|exports)$/).test(node.object.name);
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index 433d64e167..c3d18b2c99 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -1,3 +1,5 @@
+import { getScope } from 'eslint-module-utils/contextCompat';
+
 import docsUrl from '../docsUrl';
 
 module.exports = {
@@ -32,7 +34,7 @@ module.exports = {
     }
 
     function handleExportDefault(node) {
-      const scope = context.getScope();
+      const scope = getScope(context, node);
 
       if (node.declaration.name) {
         checkDeclarationsInScope(scope, node.declaration.name);
@@ -40,7 +42,7 @@ module.exports = {
     }
 
     function handleExportNamed(node) {
-      const scope = context.getScope();
+      const scope = getScope(context, node);
 
       if (node.declaration)  {
         checkDeclaration(node.declaration);
diff --git a/src/rules/no-namespace.js b/src/rules/no-namespace.js
index 3c6617a41c..7ab60bd215 100644
--- a/src/rules/no-namespace.js
+++ b/src/rules/no-namespace.js
@@ -4,6 +4,8 @@
  */
 
 import minimatch from 'minimatch';
+import { getScope, getSourceCode } from 'eslint-module-utils/contextCompat';
+
 import docsUrl from '../docsUrl';
 
 /**
@@ -108,7 +110,7 @@ module.exports = {
           return;
         }
 
-        const scopeVariables = context.getScope().variables;
+        const scopeVariables = getScope(context, node).variables;
         const namespaceVariable = scopeVariables.find((variable) => variable.defs[0].node === node);
         const namespaceReferences = namespaceVariable.references;
         const namespaceIdentifiers = namespaceReferences.map((reference) => reference.identifier);
@@ -118,7 +120,7 @@ module.exports = {
           node,
           message: `Unexpected namespace import.`,
           fix: canFix && ((fixer) => {
-            const scopeManager = context.getSourceCode().scopeManager;
+            const { scopeManager } = getSourceCode(context);
             const fixes = [];
 
             // Pass 1: Collect variable names that are already in scope for each reference we want
diff --git a/src/rules/no-relative-packages.js b/src/rules/no-relative-packages.js
index 1d215519fd..ebc280ff9b 100644
--- a/src/rules/no-relative-packages.js
+++ b/src/rules/no-relative-packages.js
@@ -1,6 +1,7 @@
 import path from 'path';
 import readPkgUp from 'eslint-module-utils/readPkgUp';
 
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import importType from '../core/importType';
@@ -26,7 +27,7 @@ function checkImportForRelativePackage(context, importPath, node) {
   }
 
   const resolvedImport = resolve(importPath, context);
-  const resolvedContext = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+  const resolvedContext = getPhysicalFilename(context);
 
   if (!resolvedImport || !resolvedContext) {
     return;
diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js
index decd2ef7d2..94972d3ddf 100644
--- a/src/rules/no-relative-parent-imports.js
+++ b/src/rules/no-relative-parent-imports.js
@@ -1,9 +1,10 @@
-import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
-import docsUrl from '../docsUrl';
 import { basename, dirname, relative } from 'path';
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
+import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
 import resolve from 'eslint-module-utils/resolve';
 
 import importType from '../core/importType';
+import docsUrl from '../docsUrl';
 
 module.exports = {
   meta: {
@@ -17,7 +18,7 @@ module.exports = {
   },
 
   create: function noRelativePackages(context) {
-    const myPath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+    const myPath = getPhysicalFilename(context);
     if (myPath === '<text>') { return {}; } // can't check a non-file
 
     function checkSourceValue(sourceNode) {
diff --git a/src/rules/no-restricted-paths.js b/src/rules/no-restricted-paths.js
index 75952dd058..2e1bc608c6 100644
--- a/src/rules/no-restricted-paths.js
+++ b/src/rules/no-restricted-paths.js
@@ -1,11 +1,12 @@
 import path from 'path';
-
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import isGlob from 'is-glob';
 import { Minimatch } from 'minimatch';
-import docsUrl from '../docsUrl';
+
 import importType from '../core/importType';
+import docsUrl from '../docsUrl';
 
 const containsPath = (filepath, target) => {
   const relative = path.relative(target, filepath);
@@ -85,7 +86,7 @@ module.exports = {
     const options = context.options[0] || {};
     const restrictedPaths = options.zones || [];
     const basePath = options.basePath || process.cwd();
-    const currentFilename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+    const currentFilename = getPhysicalFilename(context);
     const matchingZones = restrictedPaths.filter(
       (zone) => [].concat(zone.target)
         .map((target) => path.resolve(basePath, target))
diff --git a/src/rules/no-self-import.js b/src/rules/no-self-import.js
index 0ba0f66694..99c5342709 100644
--- a/src/rules/no-self-import.js
+++ b/src/rules/no-self-import.js
@@ -3,12 +3,14 @@
  * @author Gio d'Amelio
  */
 
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 import resolve from 'eslint-module-utils/resolve';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
+
 import docsUrl from '../docsUrl';
 
 function isImportingSelf(context, node, requireName) {
-  const filePath = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+  const filePath = getPhysicalFilename(context);
 
   // If the input is from stdin, this test can't fail
   if (filePath !== '<text>' && filePath === resolve(requireName, context)) {
diff --git a/src/rules/no-unassigned-import.js b/src/rules/no-unassigned-import.js
index 0af9f2e9f3..fec232afef 100644
--- a/src/rules/no-unassigned-import.js
+++ b/src/rules/no-unassigned-import.js
@@ -1,5 +1,6 @@
 import path from 'path';
 import minimatch from 'minimatch';
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 
 import isStaticRequire from '../core/staticRequire';
 import docsUrl from '../docsUrl';
@@ -31,7 +32,7 @@ function testIsAllow(globs, filename, source) {
 
 function create(context) {
   const options = context.options[0] || {};
-  const filename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+  const filename = getPhysicalFilename(context);
   const isAllow = (source) => testIsAllow(options.allow, filename, source);
 
   return {
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 702f2f8899..358726299d 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -4,6 +4,7 @@
  * @author René Fermann
  */
 
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 import { getFileExtensions } from 'eslint-module-utils/ignore';
 import resolve from 'eslint-module-utils/resolve';
 import visit from 'eslint-module-utils/visit';
@@ -609,7 +610,7 @@ module.exports = {
       doPreparation(src, ignoreExports, context);
     }
 
-    const file = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
+    const file = getPhysicalFilename(context);
 
     const checkExportPresence = (node) => {
       if (!missingExports) {
diff --git a/src/rules/no-useless-path-segments.js b/src/rules/no-useless-path-segments.js
index 390a7546d3..2d8dd35269 100644
--- a/src/rules/no-useless-path-segments.js
+++ b/src/rules/no-useless-path-segments.js
@@ -3,6 +3,7 @@
  * @author Thomas Grainger
  */
 
+import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 import { getFileExtensions } from 'eslint-module-utils/ignore';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
 import resolve from 'eslint-module-utils/resolve';
@@ -60,7 +61,7 @@ module.exports = {
   },
 
   create(context) {
-    const currentDir = path.dirname(context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
+    const currentDir = path.dirname(getPhysicalFilename(context));
     const options = context.options[0];
 
     function checkSourceValue(source) {
diff --git a/src/rules/order.js b/src/rules/order.js
index 1b25273c65..23821830ff 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -3,6 +3,7 @@
 import minimatch from 'minimatch';
 import includes from 'array-includes';
 import groupBy from 'object.groupby';
+import { getSourceCode } from 'eslint-module-utils/contextCompat';
 
 import importType from '../core/importType';
 import isStaticRequire from '../core/staticRequire';
@@ -199,7 +200,7 @@ function makeImportDescription(node) {
 }
 
 function fixOutOfOrder(context, firstNode, secondNode, order) {
-  const sourceCode = context.getSourceCode();
+  const sourceCode = getSourceCode(context);
 
   const firstRoot = findRootNode(firstNode.node);
   const firstRootStart = findStartOfLineWithComments(sourceCode, firstRoot);
@@ -499,7 +500,10 @@ function convertPathGroupsForRanks(pathGroups) {
 function fixNewLineAfterImport(context, previousImport) {
   const prevRoot = findRootNode(previousImport.node);
   const tokensToEndOfLine = takeTokensAfterWhile(
-    context.getSourceCode(), prevRoot, commentOnSameLineAs(prevRoot));
+    getSourceCode(context),
+    prevRoot,
+    commentOnSameLineAs(prevRoot),
+  );
 
   let endOfLine = prevRoot.range[1];
   if (tokensToEndOfLine.length > 0) {
@@ -509,7 +513,7 @@ function fixNewLineAfterImport(context, previousImport) {
 }
 
 function removeNewLineAfterImport(context, currentImport, previousImport) {
-  const sourceCode = context.getSourceCode();
+  const sourceCode = getSourceCode(context);
   const prevRoot = findRootNode(previousImport.node);
   const currRoot = findRootNode(currentImport.node);
   const rangeToRemove = [
@@ -524,7 +528,7 @@ function removeNewLineAfterImport(context, currentImport, previousImport) {
 
 function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, distinctGroup) {
   const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
-    const linesBetweenImports = context.getSourceCode().lines.slice(
+    const linesBetweenImports = getSourceCode(context).lines.slice(
       previousImport.node.loc.end.line,
       currentImport.node.loc.start.line - 1,
     );
@@ -720,22 +724,24 @@ module.exports = {
         }
       },
       TSImportEqualsDeclaration: function handleImports(node) {
-        let displayName;
-        let value;
-        let type;
         // skip "export import"s
         if (node.isExport) {
           return;
         }
+
+        let displayName;
+        let value;
+        let type;
         if (node.moduleReference.type === 'TSExternalModuleReference') {
           value = node.moduleReference.expression.value;
           displayName = value;
           type = 'import';
         } else {
           value = '';
-          displayName = context.getSourceCode().getText(node.moduleReference);
+          displayName = getSourceCode(context).getText(node.moduleReference);
           type = 'import:object';
         }
+
         registerNode(
           context,
           {

From c02518b0a8fd7ae2400591e80f079ad9fcc4ad6e Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 6 Sep 2024 12:37:27 +1200
Subject: [PATCH 707/767] [Refactor] migrate some more places to contextCompat
 helpers

---
 src/importDeclaration.js                | 6 ++++--
 src/rules/namespace.js                  | 2 +-
 src/rules/newline-after-import.js       | 6 +++---
 src/rules/no-named-as-default-member.js | 2 +-
 src/rules/no-named-as-default.js        | 2 +-
 5 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/importDeclaration.js b/src/importDeclaration.js
index 0d5e1870a7..49446b2603 100644
--- a/src/importDeclaration.js
+++ b/src/importDeclaration.js
@@ -1,4 +1,6 @@
-export default function importDeclaration(context) {
-  const ancestors = context.getAncestors();
+import { getAncestors } from 'eslint-module-utils/contextCompat';
+
+export default function importDeclaration(context, node) {
+  const ancestors = getAncestors(context, node);
   return ancestors[ancestors.length - 1];
 }
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 60a4220de2..6feee0d23a 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -87,7 +87,7 @@ module.exports = {
 
       // same as above, but does not add names to local map
       ExportNamespaceSpecifier(namespace) {
-        const declaration = importDeclaration(context);
+        const declaration = importDeclaration(context, namespace);
 
         const imports = ExportMapBuilder.get(declaration.source.value, context);
         if (imports == null) { return null; }
diff --git a/src/rules/newline-after-import.js b/src/rules/newline-after-import.js
index bf550bad95..c645d2bc6f 100644
--- a/src/rules/newline-after-import.js
+++ b/src/rules/newline-after-import.js
@@ -3,7 +3,7 @@
  * @author Radek Benkel
  */
 
-import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
+import { getPhysicalFilename, getScope } from 'eslint-module-utils/contextCompat';
 
 import isStaticRequire from '../core/staticRequire';
 import docsUrl from '../docsUrl';
@@ -194,9 +194,9 @@ module.exports = {
           requireCalls.push(node);
         }
       },
-      'Program:exit'() {
+      'Program:exit'(node) {
         log('exit processing for', getPhysicalFilename(context));
-        const scopeBody = getScopeBody(context.getScope());
+        const scopeBody = getScopeBody(getScope(context, node));
         log('got scope:', scopeBody);
 
         requireCalls.forEach((node, index) => {
diff --git a/src/rules/no-named-as-default-member.js b/src/rules/no-named-as-default-member.js
index 54bec64a2a..c6abc46a81 100644
--- a/src/rules/no-named-as-default-member.js
+++ b/src/rules/no-named-as-default-member.js
@@ -35,7 +35,7 @@ module.exports = {
 
     return {
       ImportDefaultSpecifier(node) {
-        const declaration = importDeclaration(context);
+        const declaration = importDeclaration(context, node);
         const exportMap = ExportMapBuilder.get(declaration.source.value, context);
         if (exportMap == null) { return; }
 
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index 5b24f8e883..c5adc7afe8 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -18,7 +18,7 @@ module.exports = {
       // #566: default is a valid specifier
       if (defaultSpecifier[nameKey].name === 'default') { return; }
 
-      const declaration = importDeclaration(context);
+      const declaration = importDeclaration(context, defaultSpecifier);
 
       const imports = ExportMapBuilder.get(declaration.source.value, context);
       if (imports == null) { return; }

From df9f33377dddda118a3fa5f77b2825f30eff7e41 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 6 Sep 2024 12:37:27 +1200
Subject: [PATCH 708/767] [Tests] `no-empty-named-blocks`: add a `message`

---
 tests/src/rules/no-empty-named-blocks.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/src/rules/no-empty-named-blocks.js b/tests/src/rules/no-empty-named-blocks.js
index f65e5a2045..87965a1407 100644
--- a/tests/src/rules/no-empty-named-blocks.js
+++ b/tests/src/rules/no-empty-named-blocks.js
@@ -10,6 +10,7 @@ function generateSuggestionsTestCases(cases, parser) {
     code,
     parser,
     errors: [{
+      message: 'Unexpected empty named import block',
       suggestions: [
         {
           desc: 'Remove unused import',

From 5d507c7876d3fc9d64c55ba6612dc45fb3ec3dfe Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 6 Sep 2024 13:27:26 +1200
Subject: [PATCH 709/767] [Tests] remove more duplicates

---
 tests/src/rules/no-cycle.js                   | 10 ----------
 tests/src/rules/no-extraneous-dependencies.js | 11 -----------
 tests/src/rules/no-unresolved.js              |  9 ---------
 3 files changed, 30 deletions(-)

diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index efc0fb6eb9..d005727e31 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -232,16 +232,6 @@ const cases = {
         errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
         parser: parsers.BABEL_OLD,
       }),
-      test({
-        code: `import { foo } from "./${testDialect}/depth-two"`,
-        options: [{ maxDepth: Infinity }],
-        errors: [error(`Dependency cycle via ./depth-one:1`)],
-      }),
-      test({
-        code: `import { foo } from "./${testDialect}/depth-two"`,
-        options: [{ maxDepth: '∞' }],
-        errors: [error(`Dependency cycle via ./depth-one:1`)],
-      }),
       test({
         code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 5`,
         errors: [error(`Dependency cycle detected.`)],
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index 4b221de353..dd01c141d3 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -43,11 +43,9 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       test({ code: `export { foo } from "${pkg}"` }),
       test({ code: `export * from "${pkg}"` }),
     ]),
-    test({ code: 'import "eslint"' }),
     test({ code: 'import "eslint/lib/api"' }),
     test({ code: 'import "fs"' }),
     test({ code: 'import "./foo"' }),
-    test({ code: 'import "@org/package"' }),
 
     test({ code: 'import "electron"', settings: { 'import/core-modules': ['electron'] } }),
     test({
@@ -386,15 +384,6 @@ ruleTester.run('no-extraneous-dependencies', rule, {
       }],
     }),
 
-    test({
-      code: 'import "not-a-dependency"',
-      filename: path.join(packageDirMonoRepoRoot, 'foo.js'),
-      options: [{ packageDir: packageDirMonoRepoRoot }],
-      errors: [{
-        message: `'not-a-dependency' should be listed in the project's dependencies. Run 'npm i -S not-a-dependency' to add it`,
-      }],
-    }),
-
     test({
       code: 'import "esm-package-not-in-pkg-json/esm-module";',
       errors: [{
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 04a53d887b..9bf1a42d4a 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -136,15 +136,6 @@ function runResolverTests(resolver) {
         ],
       }),
 
-      rest({
-        code: "import bar from './baz';",
-        errors: [
-          {
-            message: "Unable to resolve path to module './baz'.",
-            type: 'Literal',
-          },
-        ],
-      }),
       rest({
         code: "import bar from './baz';",
         errors: [

From 4944f2830bcd0345e89da25c809d726d6c98b7f0 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 6 Sep 2024 17:28:04 +1200
Subject: [PATCH 710/767] [utils] [new] `declaredScope`: take a `node` for
 modern eslint versions

---
 utils/CHANGELOG.md       | 3 +++
 utils/declaredScope.d.ts | 4 +++-
 utils/declaredScope.js   | 6 ++++--
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 089219e7d6..00067e1867 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### New
+- `declaredScope`: take a `node` for modern eslint versions (thanks [@michaelfaith])
+
 ## v2.10.0 - 2024-09-05
 
 ### New
diff --git a/utils/declaredScope.d.ts b/utils/declaredScope.d.ts
index e37200d870..90053e8e70 100644
--- a/utils/declaredScope.d.ts
+++ b/utils/declaredScope.d.ts
@@ -1,8 +1,10 @@
 import { Rule, Scope } from 'eslint';
+import * as ESTree from 'estree';
 
 declare function declaredScope(
     context: Rule.RuleContext,
-    name: string
+    name: string,
+    node?: ESTree.Node,
 ): Scope.Scope['type'] | undefined;
 
 export default declaredScope;
diff --git a/utils/declaredScope.js b/utils/declaredScope.js
index 0f0a3d9458..aa3e38b47a 100644
--- a/utils/declaredScope.js
+++ b/utils/declaredScope.js
@@ -2,9 +2,11 @@
 
 exports.__esModule = true;
 
+const { getScope } = require('./contextCompat');
+
 /** @type {import('./declaredScope').default} */
-exports.default = function declaredScope(context, name) {
-  const references = context.getScope().references;
+exports.default = function declaredScope(context, name, node) {
+  const references = (node ? getScope(context, node) : context.getScope()).references;
   const reference = references.find((x) => x.identifier.name === name);
   if (!reference || !reference.resolved) { return undefined; }
   return reference.resolved.scope.type;

From 107e30dd3a048c189d601958a0b6005ba6695319 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 5 Sep 2024 22:41:26 -0700
Subject: [PATCH 711/767] [utils] v2.11.0

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 00067e1867..6b2a5e5e19 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.11.0 - 2024-09-05
+
 ### New
 - `declaredScope`: take a `node` for modern eslint versions (thanks [@michaelfaith])
 
diff --git a/utils/package.json b/utils/package.json
index f7afde88f9..df63ac1683 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.10.0",
+  "version": "2.11.0",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From a9018a86b78dc1e539269b77f1b14d93315b343c Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 6 Sep 2024 14:35:41 +1200
Subject: [PATCH 712/767] [Refactor] `namespace`, `no-deprecated`: update
 `declaredScope` to use new `getScope` when possible

---
 package.json               | 2 +-
 src/rules/namespace.js     | 4 ++--
 src/rules/no-deprecated.js | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index 90b9df4da8..5888c28eaa 100644
--- a/package.json
+++ b/package.json
@@ -117,7 +117,7 @@
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
-    "eslint-module-utils": "^2.10.0",
+    "eslint-module-utils": "^2.11.0",
     "hasown": "^2.0.2",
     "is-core-module": "^2.15.1",
     "is-glob": "^4.0.3",
diff --git a/src/rules/namespace.js b/src/rules/namespace.js
index 6feee0d23a..b2de7f225f 100644
--- a/src/rules/namespace.js
+++ b/src/rules/namespace.js
@@ -110,7 +110,7 @@ module.exports = {
       MemberExpression(dereference) {
         if (dereference.object.type !== 'Identifier') { return; }
         if (!namespaces.has(dereference.object.name)) { return; }
-        if (declaredScope(context, dereference.object.name) !== 'module') { return; }
+        if (declaredScope(context, dereference.object.name, dereference) !== 'module') { return; }
 
         if (dereference.parent.type === 'AssignmentExpression' && dereference.parent.left === dereference) {
           context.report(
@@ -158,7 +158,7 @@ module.exports = {
         if (!namespaces.has(init.name)) { return; }
 
         // check for redefinition in intermediate scopes
-        if (declaredScope(context, init.name) !== 'module') { return; }
+        if (declaredScope(context, init.name, init) !== 'module') { return; }
 
         // DFS traverse child namespaces
         function testKey(pattern, namespace, path = [init.name]) {
diff --git a/src/rules/no-deprecated.js b/src/rules/no-deprecated.js
index b4299a51d4..9559046b98 100644
--- a/src/rules/no-deprecated.js
+++ b/src/rules/no-deprecated.js
@@ -98,7 +98,7 @@ module.exports = {
 
         if (!deprecated.has(node.name)) { return; }
 
-        if (declaredScope(context, node.name) !== 'module') { return; }
+        if (declaredScope(context, node.name, node) !== 'module') { return; }
         context.report({
           node,
           message: message(deprecated.get(node.name)),
@@ -109,7 +109,7 @@ module.exports = {
         if (dereference.object.type !== 'Identifier') { return; }
         if (!namespaces.has(dereference.object.name)) { return; }
 
-        if (declaredScope(context, dereference.object.name) !== 'module') { return; }
+        if (declaredScope(context, dereference.object.name, dereference) !== 'module') { return; }
 
         // go deep
         let namespace = namespaces.get(dereference.object.name);

From 95849c88d798de5166252de7254b41f9735e8d6b Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Fri, 30 Aug 2024 18:19:23 +0200
Subject: [PATCH 713/767] [New] `order`: allow validating named imports

---
 CHANGELOG.md             |   4 +
 docs/rules/order.md      |  72 +++++++
 package.json             |   1 +
 src/rules/order.js       | 409 ++++++++++++++++++++++++++++++++----
 tests/src/rules/order.js | 438 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 880 insertions(+), 44 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88fd1dbc27..89c752b4ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Added
+- [`order`]: allow validating named imports ([#3043], thanks [@manuth])
+
 ### Fixed
 - `ExportMap` / flat config: include `languageOptions` in context ([#3052], thanks [@michaelfaith])
 
@@ -1133,6 +1136,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#3052]: https://github.com/import-js/eslint-plugin-import/pull/3052
+[#3043]: https://github.com/import-js/eslint-plugin-import/pull/3043
 [#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
 [#3033]: https://github.com/import-js/eslint-plugin-import/pull/3033
 [#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 67849bb7ed..6762799534 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -285,6 +285,78 @@ import index from './';
 import sibling from './foo';
 ```
 
+### `named: true|false|{ enabled: true|false, import: true|false, export: true|false, require: true|false, cjsExports: true|false, types: mixed|types-first|types-last }`
+
+Enforce ordering of names within imports and exports:
+
+ - If set to `true`, named imports must be ordered according to the `alphabetize` options
+ - If set to `false`, named imports can occur in any order
+
+`enabled` enables the named ordering for all expressions by default.
+Use `import`, `export` and `require` and `cjsExports` to override the enablement for the following kind of expressions:
+
+ - `import`:
+
+   ```ts
+   import { Readline } from "readline";
+   ```
+
+ - `export`:
+
+   ```ts
+   export { Readline };
+   // and
+   export { Readline } from "readline";
+   ```
+
+ - `require`
+
+   ```ts
+   const { Readline } = require("readline");
+   ```
+
+ - `cjsExports`
+
+   ```ts
+   module.exports.Readline = Readline;
+   // and
+   module.exports = { Readline };
+   ```
+
+The `types` option allows you to specify the order of `import`s and `export`s of `type` specifiers.
+Following values are possible:
+
+ - `types-first`: forces `type` specifiers to occur first
+ - `types-last`: forces value specifiers to occur first
+ - `mixed`: sorts all specifiers in alphabetical order
+
+The default value is `false`.
+
+Example setting:
+
+```ts
+{
+  named: true,
+  alphabetize: {
+    order: 'asc'
+  }
+}
+```
+
+This will fail the rule check:
+
+```ts
+/* eslint import/order: ["error", {"named": true, "alphabetize": {"order": "asc"}}] */
+import { compose, apply } from 'xcompose';
+```
+
+While this will pass:
+
+```ts
+/* eslint import/order: ["error", {"named": true, "alphabetize": {"order": "asc"}}] */
+import { apply, compose } from 'xcompose';
+```
+
 ### `alphabetize: {order: asc|desc|ignore, orderImportKind: asc|desc|ignore, caseInsensitive: true|false}`
 
 Sort the order within each group in alphabetical manner based on **import path**:
diff --git a/package.json b/package.json
index 5888c28eaa..eda679b819 100644
--- a/package.json
+++ b/package.json
@@ -126,6 +126,7 @@
     "object.groupby": "^1.0.3",
     "object.values": "^1.2.0",
     "semver": "^6.3.1",
+    "string.prototype.trimend": "^1.0.8",
     "tsconfig-paths": "^3.15.0"
   }
 }
diff --git a/src/rules/order.js b/src/rules/order.js
index 23821830ff..d6f25ddd33 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -3,20 +3,25 @@
 import minimatch from 'minimatch';
 import includes from 'array-includes';
 import groupBy from 'object.groupby';
-import { getSourceCode } from 'eslint-module-utils/contextCompat';
+import { getScope, getSourceCode } from 'eslint-module-utils/contextCompat';
+import trimEnd from 'string.prototype.trimend';
 
 import importType from '../core/importType';
 import isStaticRequire from '../core/staticRequire';
 import docsUrl from '../docsUrl';
 
+const categories = {
+  named: 'named',
+  import: 'import',
+  exports: 'exports',
+};
+
 const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index'];
 
 // REPORTING AND FIXING
 
 function reverse(array) {
-  return array.map(function (v) {
-    return { ...v, rank: -v.rank };
-  }).reverse();
+  return array.map((v) => ({ ...v, rank: -v.rank })).reverse();
 }
 
 function getTokensOrCommentsAfter(sourceCode, node, count) {
@@ -131,6 +136,26 @@ function findStartOfLineWithComments(sourceCode, node) {
   return result;
 }
 
+function findSpecifierStart(sourceCode, node) {
+  let token;
+
+  do {
+    token = sourceCode.getTokenBefore(node);
+  } while (token.value !== ',' && token.value !== '{');
+
+  return token.range[1];
+}
+
+function findSpecifierEnd(sourceCode, node) {
+  let token;
+
+  do {
+    token = sourceCode.getTokenAfter(node);
+  } while (token.value !== ',' && token.value !== '}');
+
+  return token.range[0];
+}
+
 function isRequireExpression(expr) {
   return expr != null
     && expr.type === 'CallExpression'
@@ -170,6 +195,49 @@ function isPlainImportEquals(node) {
   return node.type === 'TSImportEqualsDeclaration' && node.moduleReference.expression;
 }
 
+function isCJSExports(context, node) {
+  if (
+    node.type === 'MemberExpression'
+    && node.object.type === 'Identifier'
+    && node.property.type === 'Identifier'
+    && node.object.name === 'module'
+    && node.property.name === 'exports'
+  ) {
+    return getScope(context, node).variables.findIndex((variable) => variable.name === 'module') === -1;
+  }
+  if (
+    node.type === 'Identifier'
+    && node.name === 'exports'
+  ) {
+    return getScope(context, node).variables.findIndex((variable) => variable.name === 'exports') === -1;
+  }
+}
+
+function getNamedCJSExports(context, node) {
+  if (node.type !== 'MemberExpression') {
+    return;
+  }
+  const result = [];
+  let root = node;
+  let parent = null;
+  while (root.type === 'MemberExpression') {
+    if (root.property.type !== 'Identifier') {
+      return;
+    }
+    result.unshift(root.property.name);
+    parent = root;
+    root = root.object;
+  }
+
+  if (isCJSExports(context, root)) {
+    return result;
+  }
+
+  if (isCJSExports(context, parent)) {
+    return result.slice(1);
+  }
+}
+
 function canCrossNodeWhileReorder(node) {
   return isSupportedRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node);
 }
@@ -190,6 +258,12 @@ function canReorderItems(firstNode, secondNode) {
 }
 
 function makeImportDescription(node) {
+  if (node.type === 'export') {
+    if (node.node.exportKind === 'type') {
+      return 'type export';
+    }
+    return 'export';
+  }
   if (node.node.importKind === 'type') {
     return 'type import';
   }
@@ -199,58 +273,123 @@ function makeImportDescription(node) {
   return 'import';
 }
 
-function fixOutOfOrder(context, firstNode, secondNode, order) {
+function fixOutOfOrder(context, firstNode, secondNode, order, category) {
+  const isNamed = category === categories.named;
+  const isExports = category === categories.exports;
   const sourceCode = getSourceCode(context);
 
-  const firstRoot = findRootNode(firstNode.node);
-  const firstRootStart = findStartOfLineWithComments(sourceCode, firstRoot);
-  const firstRootEnd = findEndOfLineWithComments(sourceCode, firstRoot);
+  const {
+    firstRoot,
+    secondRoot,
+  } = isNamed ? {
+    firstRoot: firstNode.node,
+    secondRoot: secondNode.node,
+  } : {
+    firstRoot: findRootNode(firstNode.node),
+    secondRoot: findRootNode(secondNode.node),
+  };
 
-  const secondRoot = findRootNode(secondNode.node);
-  const secondRootStart = findStartOfLineWithComments(sourceCode, secondRoot);
-  const secondRootEnd = findEndOfLineWithComments(sourceCode, secondRoot);
-  const canFix = canReorderItems(firstRoot, secondRoot);
+  const {
+    firstRootStart,
+    firstRootEnd,
+    secondRootStart,
+    secondRootEnd,
+  } = isNamed ? {
+    firstRootStart: findSpecifierStart(sourceCode, firstRoot),
+    firstRootEnd: findSpecifierEnd(sourceCode, firstRoot),
+    secondRootStart: findSpecifierStart(sourceCode, secondRoot),
+    secondRootEnd: findSpecifierEnd(sourceCode, secondRoot),
+  } : {
+    firstRootStart: findStartOfLineWithComments(sourceCode, firstRoot),
+    firstRootEnd: findEndOfLineWithComments(sourceCode, firstRoot),
+    secondRootStart: findStartOfLineWithComments(sourceCode, secondRoot),
+    secondRootEnd: findEndOfLineWithComments(sourceCode, secondRoot),
+  };
 
-  let newCode = sourceCode.text.substring(secondRootStart, secondRootEnd);
-  if (newCode[newCode.length - 1] !== '\n') {
-    newCode = `${newCode}\n`;
+  if (firstNode.displayName === secondNode.displayName) {
+    if (firstNode.alias) {
+      firstNode.displayName = `${firstNode.displayName} as ${firstNode.alias}`;
+    }
+    if (secondNode.alias) {
+      secondNode.displayName = `${secondNode.displayName} as ${secondNode.alias}`;
+    }
   }
 
   const firstImport = `${makeImportDescription(firstNode)} of \`${firstNode.displayName}\``;
   const secondImport = `\`${secondNode.displayName}\` ${makeImportDescription(secondNode)}`;
   const message = `${secondImport} should occur ${order} ${firstImport}`;
 
-  if (order === 'before') {
-    context.report({
-      node: secondNode.node,
-      message,
-      fix: canFix && ((fixer) => fixer.replaceTextRange(
-        [firstRootStart, secondRootEnd],
-        newCode + sourceCode.text.substring(firstRootStart, secondRootStart),
-      )),
-    });
-  } else if (order === 'after') {
-    context.report({
-      node: secondNode.node,
-      message,
-      fix: canFix && ((fixer) => fixer.replaceTextRange(
-        [secondRootStart, firstRootEnd],
-        sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode,
-      )),
-    });
+  if (isNamed) {
+    const firstCode = sourceCode.text.slice(firstRootStart, firstRoot.range[1]);
+    const firstTrivia = sourceCode.text.slice(firstRoot.range[1], firstRootEnd);
+    const secondCode = sourceCode.text.slice(secondRootStart, secondRoot.range[1]);
+    const secondTrivia = sourceCode.text.slice(secondRoot.range[1], secondRootEnd);
+
+    if (order === 'before') {
+      const trimmedTrivia = trimEnd(secondTrivia);
+      const gapCode = sourceCode.text.slice(firstRootEnd, secondRootStart - 1);
+      const whitespaces = secondTrivia.slice(trimmedTrivia.length);
+      context.report({
+        node: secondNode.node,
+        message,
+        fix: (fixer) => fixer.replaceTextRange(
+          [firstRootStart, secondRootEnd],
+          `${secondCode},${trimmedTrivia}${firstCode}${firstTrivia}${gapCode}${whitespaces}`,
+        ),
+      });
+    } else if (order === 'after') {
+      const trimmedTrivia = trimEnd(firstTrivia);
+      const gapCode = sourceCode.text.slice(secondRootEnd + 1, firstRootStart);
+      const whitespaces = firstTrivia.slice(trimmedTrivia.length);
+      context.report({
+        node: secondNode.node,
+        message,
+        fix: (fixes) => fixes.replaceTextRange(
+          [secondRootStart, firstRootEnd],
+          `${gapCode}${firstCode},${trimmedTrivia}${secondCode}${whitespaces}`,
+        ),
+      });
+    }
+  } else {
+    const canFix = isExports || canReorderItems(firstRoot, secondRoot);
+    let newCode = sourceCode.text.substring(secondRootStart, secondRootEnd);
+
+    if (newCode[newCode.length - 1] !== '\n') {
+      newCode = `${newCode}\n`;
+    }
+
+    if (order === 'before') {
+      context.report({
+        node: secondNode.node,
+        message,
+        fix: canFix && ((fixer) => fixer.replaceTextRange(
+          [firstRootStart, secondRootEnd],
+          newCode + sourceCode.text.substring(firstRootStart, secondRootStart),
+        )),
+      });
+    } else if (order === 'after') {
+      context.report({
+        node: secondNode.node,
+        message,
+        fix: canFix && ((fixer) => fixer.replaceTextRange(
+          [secondRootStart, firstRootEnd],
+          sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode,
+        )),
+      });
+    }
   }
 }
 
-function reportOutOfOrder(context, imported, outOfOrder, order) {
+function reportOutOfOrder(context, imported, outOfOrder, order, category) {
   outOfOrder.forEach(function (imp) {
     const found = imported.find(function hasHigherRank(importedItem) {
       return importedItem.rank > imp.rank;
     });
-    fixOutOfOrder(context, found, imp, order);
+    fixOutOfOrder(context, found, imp, order, category);
   });
 }
 
-function makeOutOfOrderReport(context, imported) {
+function makeOutOfOrderReport(context, imported, category) {
   const outOfOrder = findOutOfOrder(imported);
   if (!outOfOrder.length) {
     return;
@@ -260,10 +399,10 @@ function makeOutOfOrderReport(context, imported) {
   const reversedImported = reverse(imported);
   const reversedOrder = findOutOfOrder(reversedImported);
   if (reversedOrder.length < outOfOrder.length) {
-    reportOutOfOrder(context, reversedImported, reversedOrder, 'after');
+    reportOutOfOrder(context, reversedImported, reversedOrder, 'after', category);
     return;
   }
-  reportOutOfOrder(context, imported, outOfOrder, 'before');
+  reportOutOfOrder(context, imported, outOfOrder, 'before', category);
 }
 
 const compareString = (a, b) => {
@@ -642,6 +781,30 @@ module.exports = {
               'never',
             ],
           },
+          named: {
+            default: false,
+            oneOf: [{
+              type: 'boolean',
+            }, {
+              type: 'object',
+              properties: {
+                enabled: { type: 'boolean' },
+                import: { type: 'boolean' },
+                export: { type: 'boolean' },
+                require: { type: 'boolean' },
+                cjsExports: { type: 'boolean' },
+                types: {
+                  type: 'string',
+                  enum: [
+                    'mixed',
+                    'types-first',
+                    'types-last',
+                  ],
+                },
+              },
+              additionalProperties: false,
+            }],
+          },
           alphabetize: {
             type: 'object',
             properties: {
@@ -670,10 +833,28 @@ module.exports = {
     ],
   },
 
-  create: function importOrderRule(context) {
+  create(context) {
     const options = context.options[0] || {};
     const newlinesBetweenImports = options['newlines-between'] || 'ignore';
     const pathGroupsExcludedImportTypes = new Set(options.pathGroupsExcludedImportTypes || ['builtin', 'external', 'object']);
+
+    const named = {
+      types: 'mixed',
+      ...typeof options.named === 'object' ? {
+        ...options.named,
+        import: 'import' in options.named ? options.named.import : options.named.enabled,
+        export: 'export' in options.named ? options.named.export : options.named.enabled,
+        require: 'require' in options.named ? options.named.require : options.named.enabled,
+        cjsExports: 'cjsExports' in options.named ? options.named.cjsExports : options.named.enabled,
+      } : {
+        import: options.named,
+        export: options.named,
+        require: options.named,
+        cjsExports: options.named,
+      },
+    };
+
+    const namedGroups = named.types === 'mixed' ? [] : named.types === 'types-last' ? ['value'] : ['type'];
     const alphabetize = getAlphabetizeConfig(options);
     const distinctGroup = options.distinctGroup == null ? defaultDistinctGroup : !!options.distinctGroup;
     let ranks;
@@ -696,6 +877,7 @@ module.exports = {
       };
     }
     const importMap = new Map();
+    const exportMap = new Map();
 
     function getBlockImports(node) {
       if (!importMap.has(node)) {
@@ -704,8 +886,38 @@ module.exports = {
       return importMap.get(node);
     }
 
+    function getBlockExports(node) {
+      if (!exportMap.has(node)) {
+        exportMap.set(node, []);
+      }
+      return exportMap.get(node);
+    }
+
+    function makeNamedOrderReport(context, namedImports) {
+      if (namedImports.length > 1) {
+        const imports = namedImports.map(
+          (namedImport) => {
+            const kind = namedImport.kind || 'value';
+            const rank = namedGroups.findIndex((entry) => [].concat(entry).indexOf(kind) > -1);
+
+            return {
+              displayName: namedImport.value,
+              rank: rank === -1 ? namedGroups.length : rank,
+              ...namedImport,
+              value: `${namedImport.value}:${namedImport.alias || ''}`,
+            };
+          });
+
+        if (alphabetize.order !== 'ignore') {
+          mutateRanksToAlphabetize(imports, alphabetize);
+        }
+
+        makeOutOfOrderReport(context, imports, categories.named);
+      }
+    }
+
     return {
-      ImportDeclaration: function handleImports(node) {
+      ImportDeclaration(node) {
         // Ignoring unassigned imports unless warnOnUnassignedImports is set
         if (node.specifiers.length || options.warnOnUnassignedImports) {
           const name = node.source.value;
@@ -721,9 +933,27 @@ module.exports = {
             getBlockImports(node.parent),
             pathGroupsExcludedImportTypes,
           );
+
+          if (named.import) {
+            makeNamedOrderReport(
+              context,
+              node.specifiers.filter(
+                (specifier) => specifier.type === 'ImportSpecifier').map(
+                (specifier) => ({
+                  node: specifier,
+                  value: specifier.imported.name,
+                  type: 'import',
+                  kind: specifier.importKind,
+                  ...specifier.local.range[0] !== specifier.imported.range[0] && {
+                    alias: specifier.local.name,
+                  },
+                }),
+              ),
+            );
+          }
         }
       },
-      TSImportEqualsDeclaration: function handleImports(node) {
+      TSImportEqualsDeclaration(node) {
         // skip "export import"s
         if (node.isExport) {
           return;
@@ -755,7 +985,7 @@ module.exports = {
           pathGroupsExcludedImportTypes,
         );
       },
-      CallExpression: function handleRequires(node) {
+      CallExpression(node) {
         if (!isStaticRequire(node)) {
           return;
         }
@@ -777,7 +1007,90 @@ module.exports = {
           pathGroupsExcludedImportTypes,
         );
       },
-      'Program:exit': function reportAndReset() {
+      ...named.require && {
+        VariableDeclarator(node) {
+          if (node.id.type === 'ObjectPattern' && isRequireExpression(node.init)) {
+            for (let i = 0; i < node.id.properties.length; i++) {
+              if (
+                node.id.properties[i].key.type !== 'Identifier'
+                || node.id.properties[i].value.type !== 'Identifier'
+              ) {
+                return;
+              }
+            }
+            makeNamedOrderReport(
+              context,
+              node.id.properties.map((prop) => ({
+                node: prop,
+                value: prop.key.name,
+                type: 'require',
+                ...prop.key.range[0] !== prop.value.range[0] && {
+                  alias: prop.value.name,
+                },
+              })),
+            );
+          }
+        },
+      },
+      ...named.export && {
+        ExportNamedDeclaration(node) {
+          makeNamedOrderReport(
+            context,
+            node.specifiers.map((specifier) => ({
+              node: specifier,
+              value: specifier.local.name,
+              type: 'export',
+              kind: specifier.exportKind,
+              ...specifier.local.range[0] !== specifier.exported.range[0] && {
+                alias: specifier.exported.name,
+              },
+            })),
+          );
+        },
+      },
+      ...named.cjsExports && {
+        AssignmentExpression(node) {
+          if (node.parent.type === 'ExpressionStatement') {
+            if (isCJSExports(context, node.left)) {
+              if (node.right.type === 'ObjectExpression') {
+                for (let i = 0; i < node.right.properties.length; i++) {
+                  if (
+                    node.right.properties[i].key.type !== 'Identifier'
+                    || node.right.properties[i].value.type !== 'Identifier'
+                  ) {
+                    return;
+                  }
+                }
+
+                makeNamedOrderReport(
+                  context,
+                  node.right.properties.map((prop) => ({
+                    node: prop,
+                    value: prop.key.name,
+                    type: 'export',
+                    ...prop.key.range[0] !== prop.value.range[0] && {
+                      alias: prop.value.name,
+                    },
+                  })),
+                );
+              }
+            } else {
+              const nameParts = getNamedCJSExports(context, node.left);
+              if (nameParts && nameParts.length > 0) {
+                const name = nameParts.join('.');
+                getBlockExports(node.parent.parent).push({
+                  node,
+                  value: name,
+                  displayName: name,
+                  type: 'export',
+                  rank: 0,
+                });
+              }
+            }
+          }
+        },
+      },
+      'Program:exit'() {
         importMap.forEach((imported) => {
           if (newlinesBetweenImports !== 'ignore') {
             makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, distinctGroup);
@@ -787,10 +1100,18 @@ module.exports = {
             mutateRanksToAlphabetize(imported, alphabetize);
           }
 
-          makeOutOfOrderReport(context, imported);
+          makeOutOfOrderReport(context, imported, categories.import);
+        });
+
+        exportMap.forEach((exported) => {
+          if (alphabetize.order !== 'ignore') {
+            mutateRanksToAlphabetize(exported, alphabetize);
+            makeOutOfOrderReport(context, exported, categories.exports);
+          }
         });
 
         importMap.clear();
+        exportMap.clear();
       },
     };
   },
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index c2d659f839..978c8e34d0 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1133,6 +1133,140 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    // named import order
+    test({
+      code: `
+        import { a, B as C, Z } from './Z';
+        const { D, n: c, Y } = require('./Z');
+        export { C, D };
+        export { A, B, C as default } from "./Z";
+
+        const { ["ignore require-statements with non-identifier imports"]: z, d } = require("./Z");
+        exports = { ["ignore exports statements with non-identifiers"]: Z, D };
+      `,
+      options: [{
+        named: true,
+        alphabetize: { order: 'asc', caseInsensitive: true },
+      }],
+    }),
+    test({
+      code: `
+        const { b, A } = require('./Z');
+      `,
+      options: [{
+        named: true,
+        alphabetize: { order: 'desc' },
+      }],
+    }),
+    test({
+      code: `
+        import { A, B } from "./Z";
+        export { Z, A } from "./Z";
+        export { N, P } from "./Z";
+        const { X, Y } = require("./Z");
+      `,
+      options: [{
+        named: {
+          require: true,
+          import: true,
+          export: false,
+        },
+      }],
+    }),
+    test({
+      code: `
+        import { B, A } from "./Z";
+        const { D, C } = require("./Z");
+        export { B, A } from "./Z";
+      `,
+      options: [{
+        named: {
+          require: false,
+          import: false,
+          export: false,
+        },
+      }],
+    }),
+    test({
+      code: `
+        import { B, A, R } from "foo";
+        const { D, O, G } = require("tunes");
+        export { B, A, Z } from "foo";
+      `,
+      options: [{
+        named: { enabled: false },
+      }],
+    }),
+    test({
+      code: `
+        import { A as A, A as B, A as C } from "./Z";
+        const { a, a: b, a: c } = require("./Z");
+      `,
+      options: [{
+        named: true,
+      }],
+    }),
+    test({
+      code: `
+        import { A, B, C } from "./Z";
+        exports = { A, B, C };
+        module.exports = { a: A, b: B, c: C };
+      `,
+      options: [{
+        named: {
+          cjsExports: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+    }),
+    test({
+      code: `
+        module.exports.A = { };
+        module.exports.A.B = { };
+        module.exports.B = { };
+        exports.C = { };
+      `,
+      options: [{
+        named: {
+          cjsExports: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+    }),
+    // ensure other assignments are untouched
+    test({
+      code: `
+        var exports = null;
+        var module = null;
+        exports = { };
+        module = { };
+        module.exports = { };
+        module.exports.U = { };
+        module.exports.N = { };
+        module.exports.C = { };
+        exports.L = { };
+        exports.E = { };
+      `,
+      options: [{
+        named: {
+          cjsExports: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+    }),
+    test({
+      code: `
+        exports["B"] = { };
+        exports["C"] = { };
+        exports["A"] = { };
+      `,
+      options: [{
+        named: {
+          cjsExports: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+    }),
   ],
   invalid: [
     // builtin before external module (require)
@@ -2742,6 +2876,205 @@ ruleTester.run('order', rule, {
         message: 'There should be no empty line within import group',
       }],
     }),
+    // named import order
+    test({
+      code: `
+        var { B, A: R } = require("./Z");
+        import { O as G, D } from "./Z";
+        import { K, L, J } from "./Z";
+        export { Z, X, Y } from "./Z";
+      `,
+      output: `
+        var { A: R, B } = require("./Z");
+        import { D, O as G } from "./Z";
+        import { J, K, L } from "./Z";
+        export { X, Y, Z } from "./Z";
+      `,
+      options: [{
+        named: true,
+        alphabetize: { order: 'asc' },
+      }],
+      errors: [{
+        message: '`A` import should occur before import of `B`',
+      }, {
+        message: '`D` import should occur before import of `O`',
+      }, {
+        message: '`J` import should occur before import of `K`',
+      }, {
+        message: '`Z` export should occur after export of `Y`',
+      }],
+    }),
+    test({
+      code: `
+        import { D, C } from "./Z";
+        var { B, A } = require("./Z");
+        export { B, A };
+      `,
+      output: `
+        import { C, D } from "./Z";
+        var { B, A } = require("./Z");
+        export { A, B };
+      `,
+      options: [{
+        named: {
+          require: false,
+          import: true,
+          export: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+      errors: [{
+        message: '`C` import should occur before import of `D`',
+      }, {
+        message: '`A` export should occur before export of `B`',
+      }],
+    }),
+    test({
+      code: `
+        import { A as B, A as C, A } from "./Z";
+        export { A, A as D, A as B, A as C } from "./Z";
+        const { a: b, a: c, a } = require("./Z");
+      `,
+      output: `
+        import { A, A as B, A as C } from "./Z";
+        export { A, A as B, A as C, A as D } from "./Z";
+        const { a, a: b, a: c } = require("./Z");
+      `,
+      options: [{
+        named: true,
+        alphabetize: { order: 'asc' },
+      }],
+      errors: [{
+        message: '`A` import should occur before import of `A as B`',
+      }, {
+        message: '`A as D` export should occur after export of `A as C`',
+      }, {
+        message: '`a` import should occur before import of `a as b`',
+      }],
+    }),
+    test({
+      code: `
+        import { A, B, C } from "./Z";
+        exports = { B, C, A };
+        module.exports = { c: C, a: A, b: B };
+      `,
+      output: `
+        import { A, B, C } from "./Z";
+        exports = { A, B, C };
+        module.exports = { a: A, b: B, c: C };
+      `,
+      options: [{
+        named: {
+          cjsExports: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+      errors: [{
+        message: '`A` export should occur before export of `B`',
+      }, {
+        message: '`c` export should occur after export of `b`',
+      }],
+    }),
+    test({
+      code: `
+        exports.B = { };
+        module.exports.A = { };
+        module.exports.C = { };
+      `,
+      output: `
+        module.exports.A = { };
+        exports.B = { };
+        module.exports.C = { };
+      `,
+      options: [{
+        named: {
+          cjsExports: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+      errors: [{
+        message: '`A` export should occur before export of `B`',
+      }],
+    }),
+    test({
+      code: `
+        exports.A.C = { };
+        module.exports.A.A = { };
+        exports.A.B = { };
+      `,
+      output: `
+        module.exports.A.A = { };
+        exports.A.B = { };
+        exports.A.C = { };
+      `,
+      options: [{
+        named: {
+          cjsExports: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+      errors: [{
+        message: '`A.C` export should occur after export of `A.B`',
+      }],
+    }),
+    // multiline named specifiers & trailing commas
+    test({
+      code: `
+        const {
+          F: O,
+          O: B,
+          /* Hello World */
+          A: R
+        } = require("./Z");
+        import {
+          Y,
+          X,
+        } from "./Z";
+        export {
+          Z, A,
+          B
+        } from "./Z";
+        module.exports = {
+          a: A, o: O,
+          b: B
+        };
+      `,
+      output: `
+        const {
+          /* Hello World */
+          A: R,
+          F: O,
+          O: B
+        } = require("./Z");
+        import {
+          X,
+          Y,
+        } from "./Z";
+        export { A,
+          B,
+          Z
+        } from "./Z";
+        module.exports = {
+          a: A,
+          b: B, o: O
+        };
+      `,
+      options: [{
+        named: {
+          enabled: true,
+        },
+        alphabetize: { order: 'asc' },
+      }],
+      errors: [{
+        message: '`A` import should occur before import of `F`',
+      }, {
+        message: '`X` import should occur before import of `Y`',
+      }, {
+        message: '`Z` export should occur after export of `B`',
+      }, {
+        message: '`b` export should occur before export of `o`',
+      }],
+    }),
     // Alphabetize with require
     ...semver.satisfies(eslintPkg.version, '< 3.0.0') ? [] : [
       test({
@@ -2772,6 +3105,9 @@ context('TypeScript', function () {
     // Type-only imports were added in TypeScript ESTree 2.23.0
     .filter((parser) => parser !== parsers.TS_OLD)
     .forEach((parser) => {
+      const supportsTypeSpecifiers = semver.satisfies(require('@typescript-eslint/parser/package.json').version, '>= 5');
+      const supportsImportTypeSpecifiers = parser !== parsers.TS_NEW || supportsTypeSpecifiers;
+      const supportsExportTypeSpecifiers = parser === parsers.TS_NEW && supportsTypeSpecifiers;
       const parserConfig = {
         parser,
         settings: {
@@ -3238,6 +3574,108 @@ context('TypeScript', function () {
               },
             ],
           }),
+          // named import order
+          test({
+            code: `
+              import { type Z, A } from "./Z";
+              import type N, { E, D } from "./Z";
+              import type { L, G } from "./Z";
+            `,
+            output: `
+              import { A, type Z } from "./Z";
+              import type N, { D, E } from "./Z";
+              import type { G, L } from "./Z";
+            `,
+            ...parserConfig,
+            options: [{
+              named: true,
+              alphabetize: { order: 'asc' },
+            }],
+            errors: [
+              { message: `\`A\` import should occur before${supportsImportTypeSpecifiers ? ' type' : ''} import of \`Z\`` },
+              { message: '`D` import should occur before import of `E`' },
+              { message: '`G` import should occur before import of `L`' },
+            ],
+          }),
+          test({
+            code: `
+              const { B, /* Hello World */ A } = require("./Z");
+              export { B, A } from "./Z";
+            `,
+            output: `
+              const { /* Hello World */ A, B } = require("./Z");
+              export { A, B } from "./Z";
+            `,
+            ...parserConfig,
+            options: [{
+              named: true,
+              alphabetize: { order: 'asc' },
+            }],
+            errors: [{
+              message: '`A` import should occur before import of `B`',
+            }, {
+              message: '`A` export should occur before export of `B`',
+            }],
+          }),
+
+          supportsExportTypeSpecifiers ? [
+            test({
+              code: `
+                export { type B, A };
+              `,
+              output: `
+                export { A, type B };
+              `,
+              ...parserConfig,
+              options: [{
+                named: {
+                  enabled: true,
+                  types: 'mixed',
+                },
+                alphabetize: { order: 'asc' },
+              }],
+              errors: [{
+                message: '`A` export should occur before type export of `B`',
+              }],
+            }),
+            test({
+              code: `
+                import { type B, A, default as C } from "./Z";
+              `,
+              output: `
+                import { A, default as C, type B } from "./Z";
+              `,
+              ...parserConfig,
+              options: [{
+                named: {
+                  import: true,
+                  types: 'types-last',
+                },
+                alphabetize: { order: 'asc' },
+              }],
+              errors: [{
+                message: '`B` type import should occur after import of `default`',
+              }],
+            }),
+            test({
+              code: `
+                export { A, type Z } from "./Z";
+              `,
+              output: `
+                export { type Z, A } from "./Z";
+              `,
+              ...parserConfig,
+              options: [{
+                named: {
+                  enabled: true,
+                  types: 'types-first',
+                },
+              }],
+              errors: [
+                { message: '`Z` type export should occur before export of `A`' },
+              ],
+            }),
+          ] : [],
 
           isCoreModule('node:child_process') && isCoreModule('node:fs/promises') ? [
             test({

From fcbdcbae2327f0335e75c9f756ff67d96c712f97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andrzej=20W=C3=B3dkiewicz?= <akwodkiewicz@gmail.com>
Date: Tue, 6 Aug 2024 09:08:37 +0200
Subject: [PATCH 714/767] [Fix] `no-named-as-default`: Allow using an
 identifier if the export is both a named and a default export

 - add tests for #1594
---
 CHANGELOG.md                                  |   3 +
 src/rules/no-named-as-default.js              |  63 ++++++++--
 tests/files/no-named-as-default/exports.js    |   4 +
 .../misleading-re-exports.js                  |   2 +
 .../no-named-as-default/no-default-export.js  |   1 +
 tests/files/no-named-as-default/re-exports.js |   2 +
 tests/files/no-named-as-default/something.js  |   1 +
 tests/src/rules/no-named-as-default.js        | 110 +++++++++++++++---
 8 files changed, 162 insertions(+), 24 deletions(-)
 create mode 100644 tests/files/no-named-as-default/exports.js
 create mode 100644 tests/files/no-named-as-default/misleading-re-exports.js
 create mode 100644 tests/files/no-named-as-default/no-default-export.js
 create mode 100644 tests/files/no-named-as-default/re-exports.js
 create mode 100644 tests/files/no-named-as-default/something.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89c752b4ed..4e7ef808eb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - `ExportMap` / flat config: include `languageOptions` in context ([#3052], thanks [@michaelfaith])
+- [`no-named-as-default`]: Allow using an identifier if the export is both a named and a default export ([#3032], thanks [@akwodkiewicz])
 
 ## [2.30.0] - 2024-09-02
 
@@ -1139,6 +1140,7 @@ for info on changes for earlier releases.
 [#3043]: https://github.com/import-js/eslint-plugin-import/pull/3043
 [#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
 [#3033]: https://github.com/import-js/eslint-plugin-import/pull/3033
+[#3032]: https://github.com/import-js/eslint-plugin-import/pull/3032
 [#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
 [#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
 [#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
@@ -1726,6 +1728,7 @@ for info on changes for earlier releases.
 [@AdriAt360]: https://github.com/AdriAt360
 [@ai]: https://github.com/ai
 [@aks-]: https://github.com/aks-
+[@akwodkiewicz]: https://github.com/akwodkiewicz
 [@aladdin-add]: https://github.com/aladdin-add
 [@alex-page]: https://github.com/alex-page
 [@alexgorbatchev]: https://github.com/alexgorbatchev
diff --git a/src/rules/no-named-as-default.js b/src/rules/no-named-as-default.js
index c5adc7afe8..dacd294f46 100644
--- a/src/rules/no-named-as-default.js
+++ b/src/rules/no-named-as-default.js
@@ -15,28 +15,71 @@ module.exports = {
 
   create(context) {
     function checkDefault(nameKey, defaultSpecifier) {
+      /**
+       * For ImportDefaultSpecifier we're interested in the "local" name (`foo` for `import {bar as foo} ...`)
+       * For ExportDefaultSpecifier we're interested in the "exported" name (`foo` for `export {bar as foo} ...`)
+       */
+      const analyzedName = defaultSpecifier[nameKey].name;
+
       // #566: default is a valid specifier
-      if (defaultSpecifier[nameKey].name === 'default') { return; }
+      if (analyzedName === 'default') { return; }
 
       const declaration = importDeclaration(context, defaultSpecifier);
+      /** @type {import('../exportMap').default | null} */
+      const importedModule = ExportMapBuilder.get(declaration.source.value, context);
+      if (importedModule == null) { return; }
 
-      const imports = ExportMapBuilder.get(declaration.source.value, context);
-      if (imports == null) { return; }
+      if (importedModule.errors.length > 0) {
+        importedModule.reportErrors(context, declaration);
+        return;
+      }
 
-      if (imports.errors.length) {
-        imports.reportErrors(context, declaration);
+      if (!importedModule.hasDefault) {
+        // The rule is triggered for default imports/exports, so if the imported module has no default
+        // this means we're dealing with incorrect source code anyway
         return;
       }
 
-      if (imports.has('default') && imports.has(defaultSpecifier[nameKey].name)) {
+      if (!importedModule.has(analyzedName)) {
+        // The name used locally for the default import was not even used in the imported module.
+        return;
+      }
 
-        context.report(
-          defaultSpecifier,
-          `Using exported name '${defaultSpecifier[nameKey].name}' as identifier for default export.`,
-        );
+      /**
+       * FIXME: We can verify if a default and a named export are pointing to the same symbol only
+       * if they are both `reexports`. In case one of the symbols is not a re-export, but defined
+       * in the file, the ExportMap structure has no info about what actually is being exported --
+       * the value in the `namespace` Map is an empty object.
+       *
+       * To solve this, it would require not relying on the ExportMap, but on some other way of
+       * accessing the imported module and its exported values.
+       *
+       * Additionally, although `ExportMap.get` is a unified way to get info from both `reexports`
+       * and `namespace` maps, it does not return valid output we need here, and I think this is
+       * related to the "cycle safeguards" in the `get` function.
+       */
 
+      if (importedModule.reexports.has(analyzedName) && importedModule.reexports.has('default')) {
+        const thingImportedWithNamedImport = importedModule.reexports.get(analyzedName).getImport();
+        const thingImportedWithDefaultImport = importedModule.reexports.get('default').getImport();
+
+        // Case: both imports point to the same file and they both refer to the same symbol in this file.
+        if (
+          thingImportedWithNamedImport.path === thingImportedWithDefaultImport.path
+          && thingImportedWithNamedImport.local === thingImportedWithDefaultImport.local
+        ) {
+          // #1594: the imported module exports the same thing via a default export and a named export
+          return;
+        }
       }
+
+      context.report(
+        defaultSpecifier,
+        `Using exported name '${defaultSpecifier[nameKey].name}' as identifier for default ${nameKey === 'local' ? `import` : `export`}.`,
+      );
+
     }
+
     return {
       ImportDefaultSpecifier: checkDefault.bind(null, 'local'),
       ExportDefaultSpecifier: checkDefault.bind(null, 'exported'),
diff --git a/tests/files/no-named-as-default/exports.js b/tests/files/no-named-as-default/exports.js
new file mode 100644
index 0000000000..62402634f6
--- /dev/null
+++ b/tests/files/no-named-as-default/exports.js
@@ -0,0 +1,4 @@
+const variable = 1;
+
+export { variable };
+export default variable;
diff --git a/tests/files/no-named-as-default/misleading-re-exports.js b/tests/files/no-named-as-default/misleading-re-exports.js
new file mode 100644
index 0000000000..8d36a0866e
--- /dev/null
+++ b/tests/files/no-named-as-default/misleading-re-exports.js
@@ -0,0 +1,2 @@
+export { variable as something } from './exports';
+export { something as default } from './something';
diff --git a/tests/files/no-named-as-default/no-default-export.js b/tests/files/no-named-as-default/no-default-export.js
new file mode 100644
index 0000000000..db30747974
--- /dev/null
+++ b/tests/files/no-named-as-default/no-default-export.js
@@ -0,0 +1 @@
+export const foobar = 4;
diff --git a/tests/files/no-named-as-default/re-exports.js b/tests/files/no-named-as-default/re-exports.js
new file mode 100644
index 0000000000..20306c1829
--- /dev/null
+++ b/tests/files/no-named-as-default/re-exports.js
@@ -0,0 +1,2 @@
+export { something as default } from "./something";
+export { something } from "./something";
diff --git a/tests/files/no-named-as-default/something.js b/tests/files/no-named-as-default/something.js
new file mode 100644
index 0000000000..d8fd6851b3
--- /dev/null
+++ b/tests/files/no-named-as-default/something.js
@@ -0,0 +1 @@
+export const something = 42;
diff --git a/tests/src/rules/no-named-as-default.js b/tests/src/rules/no-named-as-default.js
index c6646a4f0d..7fcd6e4f72 100644
--- a/tests/src/rules/no-named-as-default.js
+++ b/tests/src/rules/no-named-as-default.js
@@ -12,14 +12,20 @@ ruleTester.run('no-named-as-default', rule, {
     test({ code: 'import bar, { foo } from "./empty-folder";' }),
 
     // es7
-    test({ code: 'export bar, { foo } from "./bar";',
-      parser: parsers.BABEL_OLD }),
-    test({ code: 'export bar from "./bar";',
-      parser: parsers.BABEL_OLD }),
+    test({
+      code: 'export bar, { foo } from "./bar";',
+      parser: parsers.BABEL_OLD,
+    }),
+    test({
+      code: 'export bar from "./bar";',
+      parser: parsers.BABEL_OLD,
+    }),
 
     // #566: don't false-positive on `default` itself
-    test({ code: 'export default from "./bar";',
-      parser: parsers.BABEL_OLD }),
+    test({
+      code: 'export default from "./bar";',
+      parser: parsers.BABEL_OLD,
+    }),
 
     // es2022: Arbitrary module namespae identifier names
     testVersion('>= 8.7', () => ({
@@ -27,6 +33,48 @@ ruleTester.run('no-named-as-default', rule, {
       parserOptions: { ecmaVersion: 2022 },
     })),
 
+    // #1594: Allow importing as default if object is exported both as default and named
+    test({ code: 'import something from "./no-named-as-default/re-exports.js";' }),
+    test({
+      code: 'import { something } from "./no-named-as-default/re-exports.js";',
+    }),
+    test({
+      code: 'import myOwnNameForVariable from "./no-named-as-default/exports.js";',
+    }),
+    test({
+      code: 'import { variable } from "./no-named-as-default/exports.js";',
+    }),
+    test({
+      code: 'import variable from "./no-named-as-default/misleading-re-exports.js";',
+    }),
+    test({
+      // incorrect import
+      code: 'import foobar from "./no-named-as-default/no-default-export.js";',
+    }),
+    // same tests, but for exports
+    test({
+      code: 'export something from "./no-named-as-default/re-exports.js";',
+      parser: parsers.BABEL_OLD,
+    }),
+    test({
+      code: 'export { something } from "./no-named-as-default/re-exports.js";',
+    }),
+    test({
+      code: 'export myOwnNameForVariable from "./no-named-as-default/exports.js";',
+      parser: parsers.BABEL_OLD,
+    }),
+    test({
+      code: 'export { variable } from "./no-named-as-default/exports.js";',
+    }),
+    test({
+      code: 'export variable from "./no-named-as-default/misleading-re-exports.js";',
+      parser: parsers.BABEL_OLD,
+    }),
+    test({
+      code: 'export foobar from "./no-named-as-default/no-default-export.js";',
+      parser: parsers.BABEL_OLD,
+    }),
+
     ...SYNTAX_CASES,
   ),
 
@@ -34,13 +82,17 @@ ruleTester.run('no-named-as-default', rule, {
     test({
       code: 'import foo from "./bar";',
       errors: [{
-        message: 'Using exported name \'foo\' as identifier for default export.',
-        type: 'ImportDefaultSpecifier' }] }),
+        message: 'Using exported name \'foo\' as identifier for default import.',
+        type: 'ImportDefaultSpecifier',
+      }],
+    }),
     test({
       code: 'import foo, { foo as bar } from "./bar";',
       errors: [{
-        message: 'Using exported name \'foo\' as identifier for default export.',
-        type: 'ImportDefaultSpecifier' }] }),
+        message: 'Using exported name \'foo\' as identifier for default import.',
+        type: 'ImportDefaultSpecifier',
+      }],
+    }),
 
     // es7
     test({
@@ -48,13 +100,17 @@ ruleTester.run('no-named-as-default', rule, {
       parser: parsers.BABEL_OLD,
       errors: [{
         message: 'Using exported name \'foo\' as identifier for default export.',
-        type: 'ExportDefaultSpecifier' }] }),
+        type: 'ExportDefaultSpecifier',
+      }],
+    }),
     test({
       code: 'export foo, { foo as bar } from "./bar";',
       parser: parsers.BABEL_OLD,
       errors: [{
         message: 'Using exported name \'foo\' as identifier for default export.',
-        type: 'ExportDefaultSpecifier' }] }),
+        type: 'ExportDefaultSpecifier',
+      }],
+    }),
 
     test({
       code: 'import foo from "./malformed.js"',
@@ -68,7 +124,7 @@ ruleTester.run('no-named-as-default', rule, {
     testVersion('>= 8.7', () => ({
       code: 'import foo from "./export-default-string-and-named"',
       errors: [{
-        message: 'Using exported name \'foo\' as identifier for default export.',
+        message: 'Using exported name \'foo\' as identifier for default import.',
         type: 'ImportDefaultSpecifier',
       }],
       parserOptions: { ecmaVersion: 2022 },
@@ -76,10 +132,36 @@ ruleTester.run('no-named-as-default', rule, {
     testVersion('>= 8.7', () => ({
       code: 'import foo, { foo as bar } from "./export-default-string-and-named"',
       errors: [{
-        message: 'Using exported name \'foo\' as identifier for default export.',
+        message: 'Using exported name \'foo\' as identifier for default import.',
         type: 'ImportDefaultSpecifier',
       }],
       parserOptions: { ecmaVersion: 2022 },
     })),
+
+    // #1594: Allow importing as default if object is exported both as default and named
+    test({
+      code: 'import something from "./no-named-as-default/misleading-re-exports.js";',
+      parser: parsers.BABEL_OLD,
+      errors: [{
+        message: 'Using exported name \'something\' as identifier for default import.',
+        type: 'ImportDefaultSpecifier',
+      }],
+    }),
+    // The only cases that are not covered by the fix
+    test({
+      code: 'import variable from "./no-named-as-default/exports.js";',
+      errors: [{
+        message: 'Using exported name \'variable\' as identifier for default import.',
+        type: 'ImportDefaultSpecifier',
+      }],
+    }),
+    test({
+      code: 'export variable from "./no-named-as-default/exports.js";',
+      parser: parsers.BABEL_OLD,
+      errors: [{
+        message: 'Using exported name \'variable\' as identifier for default export.',
+        type: 'ExportDefaultSpecifier',
+      }],
+    }),
   ),
 });

From f72f2072f4245f2c3494816d7c14352fc9e07c0a Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Tue, 10 Sep 2024 07:52:43 +1200
Subject: [PATCH 715/767] [utils] [fix] `parse`: remove unneeded extra
 backticks

---
 utils/CHANGELOG.md | 5 +++++
 utils/parse.js     | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 6b2a5e5e19..ca733eee05 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Fixed
+- `parse`: remove unneeded extra backticks ([#3057], thanks [@G-Rath])
+
 ## v2.11.0 - 2024-09-05
 
 ### New
@@ -165,6 +168,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#3057]: https://github.com/import-js/eslint-plugin-import/pull/3057
 [#3049]: https://github.com/import-js/eslint-plugin-import/pull/3049
 [#3039]: https://github.com/import-js/eslint-plugin-import/pull/3039
 [#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
@@ -204,6 +208,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@brettz9]: https://github.com/brettz9
 [@christophercurrie]: https://github.com/christophercurrie
 [@DMartens]: https://github.com/DMartens
+[@G-Rath]: https://github.com/G-Rath
 [@hulkish]: https://github.com/hulkish
 [@Hypnosphi]: https://github.com/Hypnosphi
 [@iamnapo]: https://github.com/iamnapo
diff --git a/utils/parse.js b/utils/parse.js
index 75d527b008..21a443eca4 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -161,7 +161,7 @@ exports.default = function parse(path, content, context) {
     if (!ast || typeof ast !== 'object') {
       console.warn(
         // Can only be invalid for custom parser per imports/parser
-        '`parseForESLint` from parser `' + (typeof parserOrPath === 'string' ? parserOrPath : '`context.languageOptions.parser`') + '` is invalid and will just be ignored'
+        '`parseForESLint` from parser `' + (typeof parserOrPath === 'string' ? parserOrPath : 'context.languageOptions.parser') + '` is invalid and will just be ignored'
       );
     } else {
       // @ts-expect-error TODO: FIXME

From d66933cb1df96812fc36a08c27b062e271f7581a Mon Sep 17 00:00:00 2001
From: Joshua O'Brien <joshua.obrien@tutanota.com>
Date: Fri, 20 Sep 2024 18:37:04 +1000
Subject: [PATCH 716/767] [Docs] `no-relative-packages`: fix typo

---
 CHANGELOG.md                       | 5 +++++
 docs/rules/no-relative-packages.md | 3 +--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4e7ef808eb..32899988a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - `ExportMap` / flat config: include `languageOptions` in context ([#3052], thanks [@michaelfaith])
 - [`no-named-as-default`]: Allow using an identifier if the export is both a named and a default export ([#3032], thanks [@akwodkiewicz])
 
+### Changed
+- [Docs] [`no-relative-packages`]: fix typo ([#3066], thanks [@joshuaobrien])
+
 ## [2.30.0] - 2024-09-02
 
 ### Added
@@ -1136,6 +1139,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3066]: https://github.com/import-js/eslint-plugin-import/pull/3066
 [#3052]: https://github.com/import-js/eslint-plugin-import/pull/3052
 [#3043]: https://github.com/import-js/eslint-plugin-import/pull/3043
 [#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
@@ -1840,6 +1844,7 @@ for info on changes for earlier releases.
 [@johnthagen]: https://github.com/johnthagen
 [@jonboiser]: https://github.com/jonboiser
 [@josh]: https://github.com/josh
+[@joshuaobrien]: https://github.com/joshuaobrien
 [@JounQin]: https://github.com/JounQin
 [@jquense]: https://github.com/jquense
 [@jseminck]: https://github.com/jseminck
diff --git a/docs/rules/no-relative-packages.md b/docs/rules/no-relative-packages.md
index 4014ed9859..ed724a9ebe 100644
--- a/docs/rules/no-relative-packages.md
+++ b/docs/rules/no-relative-packages.md
@@ -6,8 +6,7 @@
 
 Use this rule to prevent importing packages through relative paths.
 
-It's useful in Yarn/Lerna workspaces, were it's possible to import a sibling
-package using `../package` relative path, while direct `package` is the correct one.
+It's useful in Yarn/Lerna workspaces, where it's possible to import a sibling package using `../package` relative path, while direct `package` is the correct one.
 
 ## Examples
 

From 6075b9cb579022f45c2d132e1fbaa22976ca87c4 Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Sun, 15 Sep 2024 10:10:47 -0500
Subject: [PATCH 717/767] [utils] [fix] `parse`: espree parser isn't working
 with flat config

This change addresses an issue with using the espree parser with flat config.  `keysFromParser` is responsible for finding the `visitorKeys` from a combination of the parser instance, parserPath, and the results of a call to `parseForESLint`.  When using flat config, the `parserPath` will not be on the context object., and there are no results from `parseForESLint`.  The espree parser _does_ provide visitor keys as a  prop on the parser itself.  However, this logic was only returning it when it found that "espree" was somewhere in the `parserPath` (which doesn't exist on flat config).

I changed it so that it first does the check for the old-school babel parser using parser path, and then just checks the parser instance for the presence of `VisitorKeys`, rather than using parserPath at all. The reason for the re-order is that if the old babel-eslint parser, for some reason has `VisitorKeys`, having the new condition first, would change the behavior.
---
 .nycrc                                       |  3 ++-
 examples/flat/eslint.config.mjs              |  1 +
 examples/flat/src/depth-zero.js              |  3 +++
 examples/flat/src/es6/depth-one-dynamic.js   |  3 +++
 examples/legacy/.eslintrc.cjs                |  1 +
 examples/legacy/src/depth-zero.js            |  3 +++
 examples/legacy/src/es6/depth-one-dynamic.js |  3 +++
 utils/CHANGELOG.md                           |  2 ++
 utils/parse.js                               | 12 +++++++++---
 9 files changed, 27 insertions(+), 4 deletions(-)
 create mode 100644 examples/flat/src/depth-zero.js
 create mode 100644 examples/flat/src/es6/depth-one-dynamic.js
 create mode 100644 examples/legacy/src/depth-zero.js
 create mode 100644 examples/legacy/src/es6/depth-one-dynamic.js

diff --git a/.nycrc b/.nycrc
index 5d75e2157c..c5396cb18c 100644
--- a/.nycrc
+++ b/.nycrc
@@ -14,6 +14,7 @@
 		"resolvers/*/test",
 		"scripts",
 		"memo-parser",
-		"lib"
+		"lib",
+		"examples"
 	]
 }
diff --git a/examples/flat/eslint.config.mjs b/examples/flat/eslint.config.mjs
index 370514a65b..1432652658 100644
--- a/examples/flat/eslint.config.mjs
+++ b/examples/flat/eslint.config.mjs
@@ -20,6 +20,7 @@ export default [
       'import/no-dynamic-require': 'warn',
       'import/no-nodejs-modules': 'warn',
       'import/no-unused-modules': ['warn', { unusedExports: true }],
+      'import/no-cycle': 'warn',
     },
   },
 ];
diff --git a/examples/flat/src/depth-zero.js b/examples/flat/src/depth-zero.js
new file mode 100644
index 0000000000..8cfde99795
--- /dev/null
+++ b/examples/flat/src/depth-zero.js
@@ -0,0 +1,3 @@
+import { foo } from "./es6/depth-one-dynamic";
+
+foo();
diff --git a/examples/flat/src/es6/depth-one-dynamic.js b/examples/flat/src/es6/depth-one-dynamic.js
new file mode 100644
index 0000000000..ca129fd622
--- /dev/null
+++ b/examples/flat/src/es6/depth-one-dynamic.js
@@ -0,0 +1,3 @@
+export function foo() {}
+
+export const bar = () => import("../depth-zero").then(({foo}) => foo);
diff --git a/examples/legacy/.eslintrc.cjs b/examples/legacy/.eslintrc.cjs
index e3cec097f0..90e065c9dc 100644
--- a/examples/legacy/.eslintrc.cjs
+++ b/examples/legacy/.eslintrc.cjs
@@ -20,5 +20,6 @@ module.exports = {
     'import/no-dynamic-require': 'warn',
     'import/no-nodejs-modules': 'warn',
     'import/no-unused-modules': ['warn', { unusedExports: true }],
+    'import/no-cycle': 'warn',
   },
 };
diff --git a/examples/legacy/src/depth-zero.js b/examples/legacy/src/depth-zero.js
new file mode 100644
index 0000000000..8cfde99795
--- /dev/null
+++ b/examples/legacy/src/depth-zero.js
@@ -0,0 +1,3 @@
+import { foo } from "./es6/depth-one-dynamic";
+
+foo();
diff --git a/examples/legacy/src/es6/depth-one-dynamic.js b/examples/legacy/src/es6/depth-one-dynamic.js
new file mode 100644
index 0000000000..cda7091cdc
--- /dev/null
+++ b/examples/legacy/src/es6/depth-one-dynamic.js
@@ -0,0 +1,3 @@
+export function foo() {}
+
+export const bar = () => import("../depth-zero").then(({ foo }) => foo);
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index ca733eee05..94fc20f7d9 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - `parse`: remove unneeded extra backticks ([#3057], thanks [@G-Rath])
+- `parse`: espree parser isn't working with flat config ([#3061], thanks [@michaelfaith])
 
 ## v2.11.0 - 2024-09-05
 
@@ -168,6 +169,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#3061]: https://github.com/import-js/eslint-plugin-import/pull/3061
 [#3057]: https://github.com/import-js/eslint-plugin-import/pull/3057
 [#3049]: https://github.com/import-js/eslint-plugin-import/pull/3049
 [#3039]: https://github.com/import-js/eslint-plugin-import/pull/3039
diff --git a/utils/parse.js b/utils/parse.js
index 21a443eca4..a419371662 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -29,12 +29,18 @@ function keysFromParser(parserPath, parserInstance, parsedResult) {
   if (parsedResult && parsedResult.visitorKeys) {
     return parsedResult.visitorKeys;
   }
-  if (typeof parserPath === 'string' && (/.*espree.*/).test(parserPath)) {
-    return parserInstance.VisitorKeys;
-  }
+  // The old babel parser doesn't have a `parseForESLint` eslint function, so we don't end
+  // up with a `parsedResult` here.  It also doesn't expose the visitor keys on the parser itself,
+  // so we have to try and infer the visitor-keys module from the parserPath.
+  // This is NOT supported in flat config!
   if (typeof parserPath === 'string' && (/.*babel-eslint.*/).test(parserPath)) {
     return getBabelEslintVisitorKeys(parserPath);
   }
+  // The espree parser doesn't have the `parseForESLint` function, so we don't ended up with a
+  // `parsedResult` here, but it does expose the visitor keys on the parser instance that we can use.
+  if (parserInstance && parserInstance.VisitorKeys) {
+    return parserInstance.VisitorKeys;
+  }
   return null;
 }
 

From 0642419aeee4de20f006b1aee1f04510eeb1e6fb Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Wed, 18 Sep 2024 17:01:51 -0500
Subject: [PATCH 718/767] [utils] [fix] `parse`: add `ecmaVersion` and
 `sourceType` to `parserOptions`

This change adds `ecmaVersion` and `sourceType` to the options we're passing to the parsers, if they're present on `languageOptions` (which would only be the case for flat config).
---
 tests/src/core/parse.js | 14 ++++++++++++++
 utils/CHANGELOG.md      |  1 +
 utils/parse.js          | 16 ++++++++++++++--
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js
index 275b93982b..b213268907 100644
--- a/tests/src/core/parse.js
+++ b/tests/src/core/parse.js
@@ -138,4 +138,18 @@ describe('parse(content, { settings, ecmaFeatures })', function () {
     parseStubParser.parse = parseSpy;
     expect(parse.bind(null, path, content, { settings: {}, parserPath: 'espree', languageOptions: { parserOptions: { sourceType: 'module', ecmaVersion: 2015, ecmaFeatures: { jsx: true } } }, parserOptions: { sourceType: 'script' } })).not.to.throw(Error);
   });
+
+  it('passes ecmaVersion and sourceType from languageOptions to parser', () => {
+    const parseSpy = sinon.spy();
+    const languageOptions = { ecmaVersion: 'latest', sourceType: 'module', parserOptions: { ecmaFeatures: { jsx: true } } };
+    parseStubParser.parse = parseSpy;
+    parse(path, content, { settings: {}, parserPath: parseStubParserPath, languageOptions });
+    expect(parseSpy.args[0][1], 'custom parser to clone the parserOptions object').to.not.equal(languageOptions);
+    expect(parseSpy.args[0][1], 'custom parser to get ecmaFeatures in parserOptions which is a clone of ecmaFeatures passed in')
+      .to.have.property('ecmaFeatures')
+      .that.is.eql(languageOptions.parserOptions.ecmaFeatures)
+      .and.is.not.equal(languageOptions.parserOptions.ecmaFeatures);
+    expect(parseSpy.args[0][1], 'custom parser to get ecmaVersion in parserOptions from languageOptions').to.have.property('ecmaVersion', languageOptions.ecmaVersion);
+    expect(parseSpy.args[0][1], 'custom parser to get sourceType in parserOptions from languageOptions').to.have.property('sourceType', languageOptions.sourceType);
+  });
 });
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 94fc20f7d9..704a282da5 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - `parse`: remove unneeded extra backticks ([#3057], thanks [@G-Rath])
 - `parse`: espree parser isn't working with flat config ([#3061], thanks [@michaelfaith])
+- `parse`: add `ecmaVersion` and `sourceType` to `parserOptions` ([#3061], thanks [@michaelfaith])
 
 ## v2.11.0 - 2024-09-05
 
diff --git a/utils/parse.js b/utils/parse.js
index a419371662..03022ac401 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -36,7 +36,7 @@ function keysFromParser(parserPath, parserInstance, parsedResult) {
   if (typeof parserPath === 'string' && (/.*babel-eslint.*/).test(parserPath)) {
     return getBabelEslintVisitorKeys(parserPath);
   }
-  // The espree parser doesn't have the `parseForESLint` function, so we don't ended up with a
+  // The espree parser doesn't have the `parseForESLint` function, so we don't end up with a
   // `parsedResult` here, but it does expose the visitor keys on the parser instance that we can use.
   if (parserInstance && parserInstance.VisitorKeys) {
     return parserInstance.VisitorKeys;
@@ -113,7 +113,8 @@ exports.default = function parse(path, content, context) {
   if (context == null) { throw new Error('need context to parse properly'); }
 
   // ESLint in "flat" mode only sets context.languageOptions.parserOptions
-  let parserOptions = context.languageOptions && context.languageOptions.parserOptions || context.parserOptions;
+  const languageOptions = context.languageOptions;
+  let parserOptions = languageOptions && languageOptions.parserOptions || context.parserOptions;
   const parserOrPath = getParser(path, context);
 
   if (!parserOrPath) { throw new Error('parserPath or languageOptions.parser is required!'); }
@@ -144,6 +145,17 @@ exports.default = function parse(path, content, context) {
   delete parserOptions.project;
   delete parserOptions.projects;
 
+  // If this is a flat config, we need to add ecmaVersion and sourceType (if present) from languageOptions
+  if (languageOptions && languageOptions.ecmaVersion) {
+    parserOptions.ecmaVersion = languageOptions.ecmaVersion;
+  }
+  if (languageOptions && languageOptions.sourceType) {
+    // @ts-expect-error languageOptions is from the flatConfig Linter type in 8.57 while parserOptions is not.
+    // Non-flat config parserOptions.sourceType doesn't have "commonjs" in the type.  Once upgraded to v9 types,
+    // they'll be the same and this expect-error should be removed.
+    parserOptions.sourceType = languageOptions.sourceType;
+  }
+
   // require the parser relative to the main module (i.e., ESLint)
   const parser = typeof parserOrPath === 'string' ? moduleRequire(parserOrPath) : parserOrPath;
 

From 91f944d8e4b1591aa45f7d1b734dc2a2fe9acc57 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 23 Sep 2024 15:34:39 -0700
Subject: [PATCH 719/767] [utils] v2.11.1

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 704a282da5..6e71a26f7c 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.11.1 - 2024-09-23
+
 ### Fixed
 - `parse`: remove unneeded extra backticks ([#3057], thanks [@G-Rath])
 - `parse`: espree parser isn't working with flat config ([#3061], thanks [@michaelfaith])
diff --git a/utils/package.json b/utils/package.json
index df63ac1683..709142fafb 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.11.0",
+  "version": "2.11.1",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From a9815dac72e667f1cb9d898022183c428111b2fa Mon Sep 17 00:00:00 2001
From: liuxingbaoyu <30521560+liuxingbaoyu@users.noreply.github.com>
Date: Thu, 19 Sep 2024 21:01:07 +0800
Subject: [PATCH 720/767] [Fix] `export`: False positive for exported
 overloaded functions in TS

---
 CHANGELOG.md              |  3 +++
 src/rules/export.js       | 48 +++++++++++++--------------------------
 tests/src/rules/export.js | 26 +++++++++++++++++++--
 3 files changed, 43 insertions(+), 34 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32899988a3..1dbd46fc7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - `ExportMap` / flat config: include `languageOptions` in context ([#3052], thanks [@michaelfaith])
 - [`no-named-as-default`]: Allow using an identifier if the export is both a named and a default export ([#3032], thanks [@akwodkiewicz])
+- [`export`]: False positive for exported overloaded functions in TS ([#3065], thanks [@liuxingbaoyu])
 
 ### Changed
 - [Docs] [`no-relative-packages`]: fix typo ([#3066], thanks [@joshuaobrien])
@@ -1140,6 +1141,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#3066]: https://github.com/import-js/eslint-plugin-import/pull/3066
+[#3065]: https://github.com/import-js/eslint-plugin-import/pull/3065
 [#3052]: https://github.com/import-js/eslint-plugin-import/pull/3052
 [#3043]: https://github.com/import-js/eslint-plugin-import/pull/3043
 [#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
@@ -1875,6 +1877,7 @@ for info on changes for earlier releases.
 [@lilling]: https://github.com/lilling
 [@ljharb]: https://github.com/ljharb
 [@ljqx]: https://github.com/ljqx
+[@liuxingbaoyu]: https://github.com/liuxingbaoyu
 [@lo1tuma]: https://github.com/lo1tuma
 [@loganfsmyth]: https://github.com/loganfsmyth
 [@luczsoma]: https://github.com/luczsoma
diff --git a/src/rules/export.js b/src/rules/export.js
index 197a0eb51c..fbbc39d75f 100644
--- a/src/rules/export.js
+++ b/src/rules/export.js
@@ -2,7 +2,6 @@ import ExportMapBuilder from '../exportMap/builder';
 import recursivePatternCapture from '../exportMap/patternCapture';
 import docsUrl from '../docsUrl';
 import includes from 'array-includes';
-import flatMap from 'array.prototype.flatmap';
 
 /*
 Notes on TypeScript namespaces aka TSModuleDeclaration:
@@ -27,42 +26,25 @@ const rootProgram = 'root';
 const tsTypePrefix = 'type:';
 
 /**
- * Detect function overloads like:
+ * remove function overloads like:
  * ```ts
  * export function foo(a: number);
  * export function foo(a: string);
- * export function foo(a: number|string) { return a; }
  * ```
  * @param {Set<Object>} nodes
- * @returns {boolean}
  */
-function isTypescriptFunctionOverloads(nodes) {
-  const nodesArr = Array.from(nodes);
-
-  const idents = flatMap(
-    nodesArr,
-    (node) => node.declaration && (
-      node.declaration.type === 'TSDeclareFunction' // eslint 6+
-      || node.declaration.type === 'TSEmptyBodyFunctionDeclaration' // eslint 4-5
-    )
-      ? node.declaration.id.name
-      : [],
-  );
-  if (new Set(idents).size !== idents.length) {
-    return true;
-  }
-
-  const types = new Set(nodesArr.map((node) => node.parent.type));
-  if (!types.has('TSDeclareFunction')) {
-    return false;
-  }
-  if (types.size === 1) {
-    return true;
-  }
-  if (types.size === 2 && types.has('FunctionDeclaration')) {
-    return true;
-  }
-  return false;
+function removeTypescriptFunctionOverloads(nodes) {
+  nodes.forEach((node) => {
+    const declType = node.type === 'ExportDefaultDeclaration' ? node.declaration.type : node.parent.type;
+    if (
+      // eslint 6+
+      declType === 'TSDeclareFunction'
+      // eslint 4-5
+      || declType === 'TSEmptyBodyFunctionDeclaration'
+    ) {
+      nodes.delete(node);
+    }
+  });
 }
 
 /**
@@ -227,9 +209,11 @@ module.exports = {
       'Program:exit'() {
         for (const [, named] of namespace) {
           for (const [name, nodes] of named) {
+            removeTypescriptFunctionOverloads(nodes);
+
             if (nodes.size <= 1) { continue; }
 
-            if (isTypescriptFunctionOverloads(nodes) || isTypescriptNamespaceMerging(nodes)) { continue; }
+            if (isTypescriptNamespaceMerging(nodes)) { continue; }
 
             for (const node of nodes) {
               if (shouldSkipTypescriptNamespace(node, nodes)) { continue; }
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index a7f2bec122..f16a25ecf5 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -56,6 +56,15 @@ ruleTester.run('export', rule, {
       `,
       parser,
     })),
+    getTSParsers().map((parser) => ({
+      code: `
+        export default function foo(param: string): boolean;
+        export default function foo(param: string, param1?: number): boolean {
+          return param && param1;
+        }
+      `,
+      parser,
+    })),
   ),
 
   invalid: [].concat(
@@ -154,6 +163,19 @@ ruleTester.run('export', rule, {
         ecmaVersion: 2022,
       },
     })),
+
+    getTSParsers().map((parser) => ({
+      code: `
+        export default function a(): void;
+        export default function a() {}
+        export { x as default };
+      `,
+      errors: [
+        'Multiple default exports.',
+        'Multiple default exports.',
+      ],
+      parser,
+    })),
   ),
 });
 
@@ -510,7 +532,7 @@ context('TypeScript', function () {
           }),
           test({
             code: `
-              export function Foo();
+              export function Foo() { };
               export class Foo { }
               export namespace Foo { }
             `,
@@ -529,7 +551,7 @@ context('TypeScript', function () {
           test({
             code: `
               export const Foo = 'bar';
-              export function Foo();
+              export function Foo() { };
               export namespace Foo { }
             `,
             errors: [

From 5c9757c5ac1a0e32392333f60f9e1f11dc53aebf Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 23 Sep 2024 22:30:42 -0700
Subject: [PATCH 721/767] [Refactor] add some more type info; switch for-ofs to
 forEaches

---
 src/rules/consistent-type-specifier-style.js | 19 ++++++-
 src/rules/no-cycle.js                        |  4 +-
 src/rules/no-duplicates.js                   | 34 +++++++----
 src/rules/no-mutable-exports.js              | 59 ++++++++++----------
 4 files changed, 72 insertions(+), 44 deletions(-)

diff --git a/src/rules/consistent-type-specifier-style.js b/src/rules/consistent-type-specifier-style.js
index ee5ff9fbc6..84c33ecd81 100644
--- a/src/rules/consistent-type-specifier-style.js
+++ b/src/rules/consistent-type-specifier-style.js
@@ -6,6 +6,12 @@ function isComma(token) {
   return token.type === 'Punctuator' && token.value === ',';
 }
 
+/**
+ * @param {import('eslint').Rule.Fix[]} fixes
+ * @param {import('eslint').Rule.RuleFixer} fixer
+ * @param {import('eslint').SourceCode.SourceCode} sourceCode
+ * @param {(ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier)[]} specifiers
+ * */
 function removeSpecifiers(fixes, fixer, sourceCode, specifiers) {
   for (const specifier of specifiers) {
     // remove the trailing comma
@@ -17,6 +23,7 @@ function removeSpecifiers(fixes, fixer, sourceCode, specifiers) {
   }
 }
 
+/** @type {(node: import('estree').Node, sourceCode: import('eslint').SourceCode.SourceCode, specifiers: (ImportSpecifier | ImportNamespaceSpecifier)[], kind: 'type' | 'typeof') => string} */
 function getImportText(
   node,
   sourceCode,
@@ -38,6 +45,7 @@ function getImportText(
   return `import ${kind} {${names.join(', ')}} from ${sourceString};`;
 }
 
+/** @type {import('eslint').Rule.RuleModule} */
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -102,6 +110,7 @@ module.exports = {
 
     // prefer-top-level
     return {
+      /** @param {import('estree').ImportDeclaration} node */
       ImportDeclaration(node) {
         if (
           // already top-level is valid
@@ -120,9 +129,13 @@ module.exports = {
           return;
         }
 
+        /** @type {typeof node.specifiers} */
         const typeSpecifiers = [];
+        /** @type {typeof node.specifiers} */
         const typeofSpecifiers = [];
+        /** @type {typeof node.specifiers} */
         const valueSpecifiers = [];
+        /** @type {typeof node.specifiers[number]} */
         let defaultSpecifier = null;
         for (const specifier of node.specifiers) {
           if (specifier.type === 'ImportDefaultSpecifier') {
@@ -144,6 +157,7 @@ module.exports = {
         const newImports = `${typeImport}\n${typeofImport}`.trim();
 
         if (typeSpecifiers.length + typeofSpecifiers.length === node.specifiers.length) {
+          /** @type {('type' | 'typeof')[]} */
           // all specifiers have inline specifiers - so we replace the entire import
           const kind = [].concat(
             typeSpecifiers.length > 0 ? 'type' : [],
@@ -162,7 +176,7 @@ module.exports = {
           });
         } else {
           // remove specific specifiers and insert new imports for them
-          for (const specifier of typeSpecifiers.concat(typeofSpecifiers)) {
+          typeSpecifiers.concat(typeofSpecifiers).forEach((specifier) => {
             context.report({
               node: specifier,
               message: 'Prefer using a top-level {{kind}}-only import instead of inline {{kind}} specifiers.',
@@ -170,6 +184,7 @@ module.exports = {
                 kind: specifier.importKind,
               },
               fix(fixer) {
+                /** @type {import('eslint').Rule.Fix[]} */
                 const fixes = [];
 
                 // if there are no value specifiers, then the other report fixer will be called, not this one
@@ -215,7 +230,7 @@ module.exports = {
                 );
               },
             });
-          }
+          });
         }
       },
     };
diff --git a/src/rules/no-cycle.js b/src/rules/no-cycle.js
index d7c748d807..713503d9f8 100644
--- a/src/rules/no-cycle.js
+++ b/src/rules/no-cycle.js
@@ -152,9 +152,9 @@ module.exports = {
           */
           if (path === myPath && toTraverse.length > 0) { return true; }
           if (route.length + 1 < maxDepth) {
-            for (const { source } of toTraverse) {
+            toTraverse.forEach(({ source }) => {
               untraversed.push({ mget: getter, route: route.concat(source) });
-            }
+            });
           }
         }
       }
diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js
index 32557802fa..b8c8d848ca 100644
--- a/src/rules/no-duplicates.js
+++ b/src/rules/no-duplicates.js
@@ -74,6 +74,7 @@ function hasProblematicComments(node, sourceCode) {
   );
 }
 
+/** @type {(first: import('estree').ImportDeclaration, rest: import('estree').ImportDeclaration[], sourceCode: import('eslint').SourceCode.SourceCode, context: import('eslint').Rule.RuleContext) => import('eslint').Rule.ReportFixer | undefined} */
 function getFix(first, rest, sourceCode, context) {
   // Sorry ESLint <= 3 users, no autofix for you. Autofixing duplicate imports
   // requires multiple `fixer.whatever()` calls in the `fix`: We both need to
@@ -123,7 +124,7 @@ function getFix(first, rest, sourceCode, context) {
         isEmpty: !hasSpecifiers(node),
       };
     })
-    .filter(Boolean);
+    .filter((x) => !!x);
 
   const unnecessaryImports = restWithoutComments.filter((node) => !hasSpecifiers(node)
     && !hasNamespace(node)
@@ -139,6 +140,7 @@ function getFix(first, rest, sourceCode, context) {
     return undefined;
   }
 
+  /** @type {import('eslint').Rule.ReportFixer} */
   return (fixer) => {
     const tokens = sourceCode.getTokens(first);
     const openBrace = tokens.find((token) => isPunctuator(token, '{'));
@@ -185,6 +187,7 @@ function getFix(first, rest, sourceCode, context) {
       ['', !firstHasTrailingComma && !firstIsEmpty, firstExistingIdentifiers],
     );
 
+    /** @type {import('eslint').Rule.Fix[]} */
     const fixes = [];
 
     if (shouldAddSpecifiers && preferInline && first.importKind === 'type') {
@@ -228,7 +231,7 @@ function getFix(first, rest, sourceCode, context) {
     }
 
     // Remove imports whose specifiers have been moved into the first import.
-    for (const specifier of specifiers) {
+    specifiers.forEach((specifier) => {
       const importNode = specifier.importNode;
       fixes.push(fixer.remove(importNode));
 
@@ -237,12 +240,12 @@ function getFix(first, rest, sourceCode, context) {
       if (charAfterImport === '\n') {
         fixes.push(fixer.removeRange(charAfterImportRange));
       }
-    }
+    });
 
     // Remove imports whose default import has been moved to the first import,
     // and side-effect-only imports that are unnecessary due to the first
     // import.
-    for (const node of unnecessaryImports) {
+    unnecessaryImports.forEach((node) => {
       fixes.push(fixer.remove(node));
 
       const charAfterImportRange = [node.range[1], node.range[1] + 1];
@@ -250,12 +253,13 @@ function getFix(first, rest, sourceCode, context) {
       if (charAfterImport === '\n') {
         fixes.push(fixer.removeRange(charAfterImportRange));
       }
-    }
+    });
 
     return fixes;
   };
 }
 
+/** @type {(imported: Map<string, import('estree').ImportDeclaration[]>, context: import('eslint').Rule.RuleContext) => void} */
 function checkImports(imported, context) {
   for (const [module, nodes] of imported.entries()) {
     if (nodes.length > 1) {
@@ -270,16 +274,17 @@ function checkImports(imported, context) {
         fix, // Attach the autofix (if any) to the first import.
       });
 
-      for (const node of rest) {
+      rest.forEach((node) => {
         context.report({
           node: node.source,
           message,
         });
-      }
+      });
     }
   }
 }
 
+/** @type {import('eslint').Rule.RuleModule} */
 module.exports = {
   meta: {
     type: 'problem',
@@ -305,10 +310,13 @@ module.exports = {
     ],
   },
 
+  /** @param {import('eslint').Rule.RuleContext} context */
   create(context) {
+    /** @type {boolean} */
     // Prepare the resolver from options.
-    const considerQueryStringOption = context.options[0]
-      && context.options[0].considerQueryString;
+    const considerQueryStringOption = context.options[0] && context.options[0].considerQueryString;
+    /** @type {boolean} */
+    const preferInline = context.options[0] && context.options[0]['prefer-inline'];
     const defaultResolver = (sourcePath) => resolve(sourcePath, context) || sourcePath;
     const resolver = considerQueryStringOption ? (sourcePath) => {
       const parts = sourcePath.match(/^([^?]*)\?(.*)$/);
@@ -318,11 +326,14 @@ module.exports = {
       return `${defaultResolver(parts[1])}?${parts[2]}`;
     } : defaultResolver;
 
+    /** @type {Map<unknown, { imported: Map<string, import('estree').ImportDeclaration[]>, nsImported: Map<string, import('estree').ImportDeclaration[]>, defaultTypesImported: Map<string, import('estree').ImportDeclaration[]>, namedTypesImported: Map<string, import('estree').ImportDeclaration[]>}>} */
     const moduleMaps = new Map();
 
+    /** @param {import('estree').ImportDeclaration} n */
+    /** @returns {typeof moduleMaps[keyof typeof moduleMaps]} */
     function getImportMap(n) {
       if (!moduleMaps.has(n.parent)) {
-        moduleMaps.set(n.parent, {
+        moduleMaps.set(n.parent, /** @type {typeof moduleMaps} */ {
           imported: new Map(),
           nsImported: new Map(),
           defaultTypesImported: new Map(),
@@ -330,7 +341,6 @@ module.exports = {
         });
       }
       const map = moduleMaps.get(n.parent);
-      const preferInline = context.options[0] && context.options[0]['prefer-inline'];
       if (!preferInline && n.importKind === 'type') {
         return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? map.defaultTypesImported : map.namedTypesImported;
       }
@@ -342,7 +352,9 @@ module.exports = {
     }
 
     return {
+      /** @param {import('estree').ImportDeclaration} n */
       ImportDeclaration(n) {
+        /** @type {string} */
         // resolved path will cover aliased duplicates
         const resolvedPath = resolver(n.source.value);
         const importMap = getImportMap(n);
diff --git a/src/rules/no-mutable-exports.js b/src/rules/no-mutable-exports.js
index c3d18b2c99..0a0e128dc0 100644
--- a/src/rules/no-mutable-exports.js
+++ b/src/rules/no-mutable-exports.js
@@ -2,6 +2,7 @@ import { getScope } from 'eslint-module-utils/contextCompat';
 
 import docsUrl from '../docsUrl';
 
+/** @type {import('eslint').Rule.RuleModule} */
 module.exports = {
   meta: {
     type: 'suggestion',
@@ -21,41 +22,41 @@ module.exports = {
       }
     }
 
+    /** @type {(scope: import('eslint').Scope.Scope, name: string) => void} */
     function checkDeclarationsInScope({ variables }, name) {
-      for (const variable of variables) {
-        if (variable.name === name) {
-          for (const def of variable.defs) {
-            if (def.type === 'Variable' && def.parent) {
+      variables
+        .filter((variable) => variable.name === name)
+        .forEach((variable) => {
+          variable.defs
+            .filter((def) => def.type === 'Variable' && def.parent)
+            .forEach((def) => {
               checkDeclaration(def.parent);
-            }
-          }
-        }
-      }
-    }
-
-    function handleExportDefault(node) {
-      const scope = getScope(context, node);
-
-      if (node.declaration.name) {
-        checkDeclarationsInScope(scope, node.declaration.name);
-      }
+            });
+        });
     }
 
-    function handleExportNamed(node) {
-      const scope = getScope(context, node);
+    return {
+      /** @param {import('estree').ExportDefaultDeclaration} node */
+      ExportDefaultDeclaration(node) {
+        const scope = getScope(context, node);
 
-      if (node.declaration)  {
-        checkDeclaration(node.declaration);
-      } else if (!node.source) {
-        for (const specifier of node.specifiers) {
-          checkDeclarationsInScope(scope, specifier.local.name);
+        if ('name' in node.declaration && node.declaration.name) {
+          checkDeclarationsInScope(scope, node.declaration.name);
         }
-      }
-    }
-
-    return {
-      ExportDefaultDeclaration: handleExportDefault,
-      ExportNamedDeclaration: handleExportNamed,
+      },
+
+      /** @param {import('estree').ExportNamedDeclaration} node */
+      ExportNamedDeclaration(node) {
+        const scope = getScope(context, node);
+
+        if ('declaration' in node && node.declaration)  {
+          checkDeclaration(node.declaration);
+        } else if (!('source' in node) || !node.source) {
+          node.specifiers.forEach((specifier) => {
+            checkDeclarationsInScope(scope, specifier.local.name);
+          });
+        }
+      },
     };
   },
 };

From f1db531f3f468ef1f5581b7b82111c17e389cf4e Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Mon, 23 Sep 2024 18:11:12 +0300
Subject: [PATCH 722/767] [Performance] `no-cycle`: dont scc for each linted
 file

---
 CHANGELOG.md |  2 ++
 src/scc.js   | 10 ++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1dbd46fc7a..e40edde5eb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Changed
 - [Docs] [`no-relative-packages`]: fix typo ([#3066], thanks [@joshuaobrien])
+- [Performance] [`no-cycle`]: dont scc for each linted file ([#3068], thanks [@soryy708])
 
 ## [2.30.0] - 2024-09-02
 
@@ -1140,6 +1141,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3068]: https://github.com/import-js/eslint-plugin-import/pull/3068
 [#3066]: https://github.com/import-js/eslint-plugin-import/pull/3066
 [#3065]: https://github.com/import-js/eslint-plugin-import/pull/3065
 [#3052]: https://github.com/import-js/eslint-plugin-import/pull/3052
diff --git a/src/scc.js b/src/scc.js
index 44c818bbe1..c2b2c637dc 100644
--- a/src/scc.js
+++ b/src/scc.js
@@ -18,12 +18,18 @@ export default class StronglyConnectedComponentsBuilder {
   }
 
   static for(context) {
-    const cacheKey = context.cacheKey || hashObject(context).digest('hex');
+    const settingsHash = hashObject({
+      settings: context.settings,
+      parserOptions: context.parserOptions,
+      parserPath: context.parserPath,
+    }).digest('hex');
+    const cacheKey = context.path + settingsHash;
     if (cache.has(cacheKey)) {
       return cache.get(cacheKey);
     }
     const scc = StronglyConnectedComponentsBuilder.calculate(context);
-    cache.set(cacheKey, scc);
+    const visitedFiles = Object.keys(scc);
+    visitedFiles.forEach((filePath) => cache.set(filePath + settingsHash, scc));
     return scc;
   }
 

From 3ecc727d6dd7474deb7f91ef6d174065e2bb5580 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 24 Sep 2024 21:51:15 -0700
Subject: [PATCH 723/767] [Deps] update `eslint-module-utils`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index eda679b819..1126b19836 100644
--- a/package.json
+++ b/package.json
@@ -117,7 +117,7 @@
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
-    "eslint-module-utils": "^2.11.0",
+    "eslint-module-utils": "^2.11.1",
     "hasown": "^2.0.2",
     "is-core-module": "^2.15.1",
     "is-glob": "^4.0.3",

From cae364c2732cf6f49e5d85961df8cd9e8fc0fe2c Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 12 Apr 2024 14:49:34 +1200
Subject: [PATCH 724/767] [Tests] don't include output when nothing has been
 changed

---
 tests/src/rule-tester.js                    |   3 +
 tests/src/rules/dynamic-import-chunkname.js | 554 +++++---------------
 tests/src/rules/newline-after-import.js     |  47 +-
 tests/src/rules/no-commonjs.js              |  47 +-
 tests/src/rules/no-duplicates.js            | 145 ++---
 tests/src/rules/no-namespace.js             |  16 +-
 tests/src/rules/order.js                    | 116 +---
 tests/src/rules/unambiguous.js              |   6 +-
 8 files changed, 251 insertions(+), 683 deletions(-)
 create mode 100644 tests/src/rule-tester.js

diff --git a/tests/src/rule-tester.js b/tests/src/rule-tester.js
new file mode 100644
index 0000000000..89c5846120
--- /dev/null
+++ b/tests/src/rule-tester.js
@@ -0,0 +1,3 @@
+export function withoutAutofixOutput(test) {
+  return { ...test, output: test.code };
+}
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index 81e018af76..1362196728 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -1,5 +1,6 @@
 import { SYNTAX_CASES, getTSParsers, parsers } from '../utils';
 import { RuleTester } from 'eslint';
+import { withoutAutofixOutput } from '../rule-tester';
 import semver from 'semver';
 
 const rule = require('rules/dynamic-import-chunkname');
@@ -423,225 +424,172 @@ ruleTester.run('dynamic-import-chunkname', rule, {
   ],
 
   invalid: [
-    {
+    withoutAutofixOutput({
       code: `import(
         // webpackChunkName: "someModule"
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        // webpackChunkName: "someModule"
-        'someModule'
-      )`,
       errors: [{
         message: nonBlockCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: 'import(\'test\')',
       options,
       parser,
-      output: 'import(\'test\')',
       errors: [{
         message: noLeadingCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: someModule */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName: someModule */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: "someModule' */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName: "someModule' */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: 'someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName: 'someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName:"someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName:"someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: true */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName: true */
-        'someModule'
-      )`,
       errors: [{
         message: chunkNameFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: "my-module-[id]" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName: "my-module-[id]" */
-        'someModule'
-      )`,
       errors: [{
         message: chunkNameFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: ["request"] */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName: ["request"] */
-        'someModule'
-      )`,
       errors: [{
         message: chunkNameFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /*webpackChunkName: "someModule"*/
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /*webpackChunkName: "someModule"*/
-        'someModule'
-      )`,
       errors: [{
         message: noPaddingCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName  :  "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName  :  "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: "someModule" ; */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName: "someModule" ; */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* totally not webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* totally not webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackPrefetch: true */
         /* webpackChunk: "someModule" */
@@ -649,339 +597,253 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackPrefetch: true */
-        /* webpackChunk: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackPrefetch: true, webpackChunk: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackPrefetch: true, webpackChunk: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: "someModule123" */
         'someModule'
       )`,
       options: pickyCommentOptions,
       parser,
-      output: `import(
-        /* webpackChunkName: "someModule123" */
-        'someModule'
-      )`,
       errors: [{
         message: pickyChunkNameFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackPrefetch: "module", webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackPrefetch: "module", webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackPreload: "module", webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackPreload: "module", webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackIgnore: "no", webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackIgnore: "no", webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackInclude: "someModule", webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackInclude: "someModule", webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackInclude: true, webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackInclude: true, webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackExclude: "someModule", webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackExclude: "someModule", webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackExclude: true, webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackExclude: true, webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackMode: "fast", webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackMode: "fast", webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackMode: true, webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackMode: true, webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackExports: true, webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackExports: true, webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackExports: /default/, webpackChunkName: "someModule" */
         'someModule'
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackExports: /default/, webpackChunkName: "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `dynamicImport(
         /* webpackChunkName "someModule" */
         'someModule'
       )`,
       options: multipleImportFunctionOptions,
-      output: `dynamicImport(
-        /* webpackChunkName "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `definitelyNotStaticImport(
         /* webpackChunkName "someModule" */
         'someModule'
       )`,
       options: multipleImportFunctionOptions,
-      output: `definitelyNotStaticImport(
-        /* webpackChunkName "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `dynamicImport(
         // webpackChunkName: "someModule"
         'someModule'
       )`,
       options,
-      output: `dynamicImport(
-        // webpackChunkName: "someModule"
-        'someModule'
-      )`,
       errors: [{
         message: nonBlockCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: 'dynamicImport(\'test\')',
       options,
-      output: 'dynamicImport(\'test\')',
       errors: [{
         message: noLeadingCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `dynamicImport(
         /* webpackChunkName: someModule */
         'someModule'
       )`,
       options,
-      output: `dynamicImport(
-        /* webpackChunkName: someModule */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `dynamicImport(
         /* webpackChunkName "someModule" */
         'someModule'
       )`,
       options,
-      output: `dynamicImport(
-        /* webpackChunkName "someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: invalidSyntaxCommentError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `dynamicImport(
         /* webpackChunkName:"someModule" */
         'someModule'
       )`,
       options,
-      output: `dynamicImport(
-        /* webpackChunkName:"someModule" */
-        'someModule'
-      )`,
       errors: [{
         message: commentFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `dynamicImport(
         /* webpackChunkName: "someModule123" */
         'someModule'
       )`,
       options: pickyCommentOptions,
-      output: `dynamicImport(
-        /* webpackChunkName: "someModule123" */
-        'someModule'
-      )`,
       errors: [{
         message: pickyChunkNameFormatError,
         type: 'CallExpression',
       }],
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import(
         /* webpackChunkName: "someModule" */
         /* webpackMode: "eager" */
@@ -989,11 +851,6 @@ ruleTester.run('dynamic-import-chunkname', rule, {
       )`,
       options,
       parser,
-      output: `import(
-        /* webpackChunkName: "someModule" */
-        /* webpackMode: "eager" */
-        'someModule'
-      )`,
       errors: [{
         message: eagerModeError,
         type: 'CallExpression',
@@ -1016,7 +873,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
           },
         ],
       }],
-    },
+    }),
   ],
 });
 
@@ -1343,177 +1200,136 @@ context('TypeScript', () => {
         },
       ],
       invalid: [
-        {
+        withoutAutofixOutput({
           code: `import(
             // webpackChunkName: "someModule"
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            // webpackChunkName: "someModule"
-            'someModule'
-          )`,
           errors: [{
             message: nonBlockCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: 'import(\'test\')',
           options,
           parser: typescriptParser,
-          output: 'import(\'test\')',
           errors: [{
             message: noLeadingCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName: someModule */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName: someModule */
-            'someModule'
-          )`,
           errors: [{
             message: invalidSyntaxCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName "someModule' */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName "someModule' */
-            'someModule'
-          )`,
           errors: [{
             message: invalidSyntaxCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName 'someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName 'someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: invalidSyntaxCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: invalidSyntaxCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName:"someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName:"someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /*webpackChunkName: "someModule"*/
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /*webpackChunkName: "someModule"*/
-            'someModule'
-          )`,
           errors: [{
             message: noPaddingCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName  :  "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName  :  "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName: "someModule" ; */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName: "someModule" ; */
-            'someModule'
-          )`,
           errors: [{
             message: invalidSyntaxCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* totally not webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* totally not webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: invalidSyntaxCommentError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackPrefetch: true */
             /* webpackChunk: "someModule" */
@@ -1521,283 +1337,210 @@ context('TypeScript', () => {
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackPrefetch: true */
-            /* webpackChunk: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackPrefetch: true, webpackChunk: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackPrefetch: true, webpackChunk: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName: true */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName: true */
-            'someModule'
-          )`,
           errors: [{
             message: chunkNameFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName: "my-module-[id]" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName: "my-module-[id]" */
-            'someModule'
-          )`,
           errors: [{
             message: chunkNameFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName: ["request"] */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName: ["request"] */
-            'someModule'
-          )`,
           errors: [{
             message: chunkNameFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName: "someModule123" */
             'someModule'
           )`,
           options: pickyCommentOptions,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName: "someModule123" */
-            'someModule'
-          )`,
           errors: [{
             message: pickyChunkNameFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackPrefetch: "module", webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackPrefetch: "module", webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackPreload: "module", webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackPreload: "module", webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackIgnore: "no", webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackIgnore: "no", webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackInclude: "someModule", webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackInclude: "someModule", webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackInclude: true, webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackInclude: true, webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackExclude: "someModule", webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackExclude: "someModule", webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackExclude: true, webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackExclude: true, webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackMode: "fast", webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackMode: "fast", webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackMode: true, webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackMode: true, webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackExports: true, webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackExports: true, webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackExports: /default/, webpackChunkName: "someModule" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackExports: /default/, webpackChunkName: "someModule" */
-            'someModule'
-          )`,
           errors: [{
             message: commentFormatError,
             type: nodeType,
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `import(
             /* webpackChunkName: "someModule", webpackMode: "eager" */
             'someModule'
           )`,
           options,
           parser: typescriptParser,
-          output: `import(
-            /* webpackChunkName: "someModule", webpackMode: "eager" */
-            'someModule'
-          )`,
           errors: [{
             message: eagerModeError,
             type: nodeType,
@@ -1818,8 +1561,8 @@ context('TypeScript', () => {
               },
             ],
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `
             import(
               /* webpackMode: "eager", webpackChunkName: "someModule" */
@@ -1828,12 +1571,6 @@ context('TypeScript', () => {
           `,
           options,
           parser: typescriptParser,
-          output: `
-            import(
-              /* webpackMode: "eager", webpackChunkName: "someModule" */
-              'someModule'
-            )
-          `,
           errors: [{
             message: eagerModeError,
             type: nodeType,
@@ -1858,8 +1595,8 @@ context('TypeScript', () => {
               },
             ],
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `
             import(
               /* webpackMode: "eager", webpackPrefetch: true, webpackChunkName: "someModule" */
@@ -1868,12 +1605,6 @@ context('TypeScript', () => {
           `,
           options,
           parser: typescriptParser,
-          output: `
-            import(
-              /* webpackMode: "eager", webpackPrefetch: true, webpackChunkName: "someModule" */
-              'someModule'
-            )
-          `,
           errors: [{
             message: eagerModeError,
             type: nodeType,
@@ -1898,8 +1629,8 @@ context('TypeScript', () => {
               },
             ],
           }],
-        },
-        {
+        }),
+        withoutAutofixOutput({
           code: `
             import(
               /* webpackChunkName: "someModule" */
@@ -1909,13 +1640,6 @@ context('TypeScript', () => {
           `,
           options,
           parser: typescriptParser,
-          output: `
-            import(
-              /* webpackChunkName: "someModule" */
-              /* webpackMode: "eager" */
-              'someModule'
-            )
-          `,
           errors: [{
             message: eagerModeError,
             type: nodeType,
@@ -1942,7 +1666,7 @@ context('TypeScript', () => {
               },
             ],
           }],
-        },
+        }),
       ],
     });
   });
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index b78e891a35..5c827c0d26 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -1,4 +1,5 @@
 import { RuleTester } from 'eslint';
+import { withoutAutofixOutput } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 import semver from 'semver';
 import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
@@ -710,9 +711,8 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
-    {
+    withoutAutofixOutput({
       code: `import foo from 'foo';\n\n\n\nexport default function() {};`,
-      output: `import foo from 'foo';\n\n\n\nexport default function() {};`,
       options: [{ count: 2, exactCount: true }],
       errors: [{
         line: 1,
@@ -720,10 +720,9 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import foo from 'foo';\n\n\n\n\nexport default function() {};`,
-      output: `import foo from 'foo';\n\n\n\n\nexport default function() {};`,
       options: [{ count: 2, exactCount: true }],
       errors: [{
         line: 1,
@@ -731,7 +730,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
+    }),
     {
       code: `import foo from 'foo';\n// some random comment\nexport default function() {};`,
       output: `import foo from 'foo';\n\n// some random comment\nexport default function() {};`,
@@ -743,9 +742,8 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
-    {
+    withoutAutofixOutput({
       code: `import foo from 'foo';\n// some random comment\n\n\nexport default function() {};`,
-      output: `import foo from 'foo';\n// some random comment\n\n\nexport default function() {};`,
       options: [{ count: 2, exactCount: true }],
       errors: [{
         line: 1,
@@ -753,10 +751,9 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `import foo from 'foo';\n// some random comment\n\n\n\nexport default function() {};`,
-      output: `import foo from 'foo';\n// some random comment\n\n\n\nexport default function() {};`,
       options: [{ count: 2, exactCount: true }],
       errors: [{
         line: 1,
@@ -764,7 +761,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
+    }),
     {
       code: `import foo from 'foo';\n// some random comment\nexport default function() {};`,
       output: `import foo from 'foo';\n\n\n// some random comment\nexport default function() {};`,
@@ -787,9 +784,8 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
-    {
+    withoutAutofixOutput({
       code: `import foo from 'foo';\n\n\n\n// some random comment\nexport default function() {};`,
-      output: `import foo from 'foo';\n\n\n\n// some random comment\nexport default function() {};`,
       options: [{ count: 2, exactCount: true, considerComments: true }],
       errors: [{
         line: 1,
@@ -797,19 +793,12 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: IMPORT_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `
         import foo from 'foo';
 
 
-        // Some random single line comment
-        var bar = 42;
-      `,
-      output: `
-        import foo from 'foo';
-
-
         // Some random single line comment
         var bar = 42;
       `,
@@ -820,7 +809,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
       options: [{ considerComments: true, count: 1, exactCount: true }],
-    },
+    }),
     {
       code: `import foo from 'foo';export default function() {};`,
       output: `import foo from 'foo';\n\nexport default function() {};`,
@@ -832,9 +821,8 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
       }],
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
     },
-    {
+    withoutAutofixOutput({
       code: `const foo = require('foo');\n\n\n\nconst bar = function() {};`,
-      output: `const foo = require('foo');\n\n\n\nconst bar = function() {};`,
       options: [{ count: 2, exactCount: true }],
       errors: [{
         line: 1,
@@ -842,10 +830,9 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: REQUIRE_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015 },
-    },
-    {
+    }),
+    withoutAutofixOutput({
       code: `const foo = require('foo');\n\n\n\n// some random comment\nconst bar = function() {};`,
-      output: `const foo = require('foo');\n\n\n\n// some random comment\nconst bar = function() {};`,
       options: [{ count: 2, exactCount: true }],
       errors: [{
         line: 1,
@@ -853,7 +840,7 @@ ruleTester.run('newline-after-import', require('rules/newline-after-import'), {
         message: REQUIRE_ERROR_MESSAGE_MULTIPLE(2),
       }],
       parserOptions: { ecmaVersion: 2015 },
-    },
+    }),
     {
       code: `import foo from 'foo';// some random comment\nexport default function() {};`,
       output: `import foo from 'foo';\n\n// some random comment\nexport default function() {};`,
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index b7c0aa803f..9950608a78 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -1,4 +1,5 @@
 import { RuleTester } from 'eslint';
+import { withoutAutofixOutput } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
@@ -69,47 +70,41 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), {
 
     // imports
     ...semver.satisfies(eslintPkg.version, '< 4.0.0') ? [] : [
-      { code: 'var x = require("x")', output: 'var x = require("x")', errors: [{ message: IMPORT_MESSAGE }] },
-      { code: 'x = require("x")', output: 'x = require("x")', errors: [{ message: IMPORT_MESSAGE }] },
-      { code: 'require("x")', output: 'require("x")', errors: [{ message: IMPORT_MESSAGE }] },
-      { code: 'require(`x`)',
+      withoutAutofixOutput({ code: 'var x = require("x")', errors: [{ message: IMPORT_MESSAGE }] }),
+      withoutAutofixOutput({ code: 'x = require("x")', errors: [{ message: IMPORT_MESSAGE }] }),
+      withoutAutofixOutput({ code: 'require("x")', errors: [{ message: IMPORT_MESSAGE }] }),
+      withoutAutofixOutput({ code: 'require(`x`)',
         parserOptions: { ecmaVersion: 2015 },
-        output: 'require(`x`)',
         errors: [{ message: IMPORT_MESSAGE }],
-      },
+      }),
 
-      { code: 'if (typeof window !== "undefined") require("x")',
+      withoutAutofixOutput({ code: 'if (typeof window !== "undefined") require("x")',
         options: [{ allowConditionalRequire: false }],
-        output: 'if (typeof window !== "undefined") require("x")',
         errors: [{ message: IMPORT_MESSAGE }],
-      },
-      { code: 'if (typeof window !== "undefined") { require("x") }',
+      }),
+      withoutAutofixOutput({ code: 'if (typeof window !== "undefined") { require("x") }',
         options: [{ allowConditionalRequire: false }],
-        output: 'if (typeof window !== "undefined") { require("x") }',
         errors: [{ message: IMPORT_MESSAGE }],
-      },
-      { code: 'try { require("x") } catch (error) {}',
+      }),
+      withoutAutofixOutput({ code: 'try { require("x") } catch (error) {}',
         options: [{ allowConditionalRequire: false }],
-        output: 'try { require("x") } catch (error) {}',
         errors: [{ message: IMPORT_MESSAGE }],
-      },
+      }),
     ],
 
     // exports
-    { code: 'exports.face = "palm"', output: 'exports.face = "palm"', errors: [{ message: EXPORT_MESSAGE }] },
-    { code: 'module.exports.face = "palm"', output: 'module.exports.face = "palm"', errors: [{ message: EXPORT_MESSAGE }] },
-    { code: 'module.exports = face', output: 'module.exports = face', errors: [{ message: EXPORT_MESSAGE }] },
-    { code: 'exports = module.exports = {}', output: 'exports = module.exports = {}', errors: [{ message: EXPORT_MESSAGE }] },
-    { code: 'var x = module.exports = {}', output: 'var x = module.exports = {}', errors: [{ message: EXPORT_MESSAGE }] },
-    { code: 'module.exports = {}',
+    withoutAutofixOutput({ code: 'exports.face = "palm"', errors: [{ message: EXPORT_MESSAGE }] }),
+    withoutAutofixOutput({ code: 'module.exports.face = "palm"', errors: [{ message: EXPORT_MESSAGE }] }),
+    withoutAutofixOutput({ code: 'module.exports = face', errors: [{ message: EXPORT_MESSAGE }] }),
+    withoutAutofixOutput({ code: 'exports = module.exports = {}', errors: [{ message: EXPORT_MESSAGE }] }),
+    withoutAutofixOutput({ code: 'var x = module.exports = {}', errors: [{ message: EXPORT_MESSAGE }] }),
+    withoutAutofixOutput({ code: 'module.exports = {}',
       options: ['allow-primitive-modules'],
-      output: 'module.exports = {}',
       errors: [{ message: EXPORT_MESSAGE }],
-    },
-    { code: 'var x = module.exports',
+    }),
+    withoutAutofixOutput({ code: 'var x = module.exports',
       options: ['allow-primitive-modules'],
-      output: 'var x = module.exports',
       errors: [{ message: EXPORT_MESSAGE }],
-    },
+    }),
   ],
 });
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index c46f9df85d..a48e4d3f74 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -3,6 +3,7 @@ import { test as testUtil, getNonDefaultParsers, parsers, tsVersionSatisfies, ty
 import jsxConfig from '../../../config/react';
 
 import { RuleTester } from 'eslint';
+import { withoutAutofixOutput } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import flatMap from 'array.prototype.flatmap';
@@ -96,15 +97,14 @@ ruleTester.run('no-duplicates', rule, {
     }),
 
     // #86: duplicate unresolved modules should be flagged
-    test({
+    // Autofix bail because of different default import names.
+    test(withoutAutofixOutput({
       code: "import foo from 'non-existent'; import bar from 'non-existent';",
-      // Autofix bail because of different default import names.
-      output: "import foo from 'non-existent'; import bar from 'non-existent';",
       errors: [
         "'non-existent' imported multiple times.",
         "'non-existent' imported multiple times.",
       ],
-    }),
+    })),
 
     test({
       code: "import type { x } from './foo'; import type { y } from './foo'",
@@ -227,12 +227,11 @@ ruleTester.run('no-duplicates', rule, {
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
 
-    test({
+    // Autofix bail because cannot merge namespace imports.
+    test(withoutAutofixOutput({
       code: "import * as ns1 from './foo'; import * as ns2 from './foo'",
-      // Autofix bail because cannot merge namespace imports.
-      output: "import * as ns1 from './foo'; import * as ns2 from './foo'",
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
+    })),
 
     test({
       code: "import * as ns from './foo'; import {x} from './foo'; import {y} from './foo'",
@@ -248,89 +247,57 @@ ruleTester.run('no-duplicates', rule, {
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
 
-    test({
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         // some-tool-disable-next-line
         import {x} from './foo'
         import {//y\ny} from './foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        // some-tool-disable-next-line
-        import {x} from './foo'
-        import {//y\ny} from './foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo'
         // some-tool-disable-next-line
         import {y} from './foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo'
-        // some-tool-disable-next-line
-        import {y} from './foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo' // some-tool-disable-line
         import {y} from './foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo' // some-tool-disable-line
-        import {y} from './foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo'
         import {y} from './foo' // some-tool-disable-line
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo'
-        import {y} from './foo' // some-tool-disable-line
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo'
         /* comment */ import {y} from './foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo'
-        /* comment */ import {y} from './foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo'
         import {y} from './foo' /* comment
         multiline */
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo'
-        import {y} from './foo' /* comment
-        multiline */
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
+    })),
 
     test({
       code: `
@@ -361,75 +328,48 @@ import {x,y} from './foo'
       `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
     }),
-
-    test({
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo'
         import/* comment */{y} from './foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo'
-        import/* comment */{y} from './foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo'
         import/* comment */'./foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo'
-        import/* comment */'./foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo'
         import{y}/* comment */from './foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo'
-        import{y}/* comment */from './foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from './foo'
         import{y}from/* comment */'./foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from './foo'
-        import{y}from/* comment */'./foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
-
-    test({
+    })),
+    // Autofix bail because of comment.
+    test(withoutAutofixOutput({
       code: `
         import {x} from
         // some-tool-disable-next-line
         './foo'
         import {y} from './foo'
       `,
-      // Autofix bail because of comment.
-      output: `
-        import {x} from
-        // some-tool-disable-next-line
-        './foo'
-        import {y} from './foo'
-      `,
       errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
-    }),
+    })),
 
     // #2027 long import list generate empty lines
     test({
@@ -616,9 +556,8 @@ context('TypeScript', function () {
       ]);
 
       const invalid = [
-        test({
+        test(withoutAutofixOutput({
           code: "import type x from './foo'; import type y from './foo'",
-          output: "import type x from './foo'; import type y from './foo'",
           ...parserConfig,
           errors: [
             {
@@ -632,7 +571,7 @@ context('TypeScript', function () {
               message: "'./foo' imported multiple times.",
             },
           ],
-        }),
+        })),
         test({
           code: "import type x from './foo'; import type x from './foo'",
           output: "import type x from './foo'; ",
diff --git a/tests/src/rules/no-namespace.js b/tests/src/rules/no-namespace.js
index 03a23e3dd7..e297d953a3 100644
--- a/tests/src/rules/no-namespace.js
+++ b/tests/src/rules/no-namespace.js
@@ -1,4 +1,5 @@
 import { RuleTester } from 'eslint';
+import { withoutAutofixOutput } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import { test } from '../utils';
@@ -82,33 +83,30 @@ ruleTester.run('no-namespace', require('rules/no-namespace'), {
   ],
 
   invalid: [
-    test({
+    test(withoutAutofixOutput({
       code: 'import * as foo from \'foo\';',
-      output: 'import * as foo from \'foo\';',
       errors: [{
         line: 1,
         column: 8,
         message: ERROR_MESSAGE,
       }],
-    }),
-    test({
+    })),
+    test(withoutAutofixOutput({
       code: 'import defaultExport, * as foo from \'foo\';',
-      output: 'import defaultExport, * as foo from \'foo\';',
       errors: [{
         line: 1,
         column: 23,
         message: ERROR_MESSAGE,
       }],
-    }),
-    test({
+    })),
+    test(withoutAutofixOutput({
       code: 'import * as foo from \'./foo\';',
-      output: 'import * as foo from \'./foo\';',
       errors: [{
         line: 1,
         column: 8,
         message: ERROR_MESSAGE,
       }],
-    }),
+    })),
     ...FIX_TESTS,
   ],
 });
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 978c8e34d0..ff6b657304 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,6 +1,7 @@
 import { test, getTSParsers, getNonDefaultParsers, testFilePath, parsers } from '../utils';
 
 import { RuleTester } from 'eslint';
+import { withoutAutofixOutput } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import flatMap from 'array.prototype.flatmap';
@@ -21,10 +22,6 @@ const flowRuleTester = new RuleTester({
 });
 const rule = require('rules/order');
 
-function withoutAutofixOutput(test) {
-  return { ...test, output: test.code };
-}
-
 ruleTester.run('order', rule, {
   valid: [
     // Default order using require
@@ -1906,19 +1903,13 @@ ruleTester.run('order', rule, {
       ],
     }),
     // Cannot fix newlines-between with multiline comment after
-    test({
+    test(withoutAutofixOutput({
       code: `
         var fs = require('fs'); /* multiline
         comment */
 
         var index = require('./');
       `,
-      output: `
-        var fs = require('fs'); /* multiline
-        comment */
-
-        var index = require('./');
-      `,
       options: [
         {
           groups: [['builtin'], ['index']],
@@ -1931,7 +1922,7 @@ ruleTester.run('order', rule, {
           message: 'There should be no empty line between import groups',
         },
       ],
-    }),
+    })),
     // Option newlines-between: 'always' - should report lack of newline between groups
     test({
       code: `
@@ -2017,7 +2008,7 @@ ruleTester.run('order', rule, {
     }),
     // Option newlines-between: 'never' with unassigned imports and warnOnUnassignedImports disabled
     // newline is preserved to match existing behavior
-    test({
+    test(withoutAutofixOutput({
       code: `
         import path from 'path';
         import 'loud-rejection';
@@ -2025,13 +2016,6 @@ ruleTester.run('order', rule, {
         import 'something-else';
         import _ from 'lodash';
       `,
-      output: `
-        import path from 'path';
-        import 'loud-rejection';
-
-        import 'something-else';
-        import _ from 'lodash';
-      `,
       options: [{ 'newlines-between': 'never', warnOnUnassignedImports: false }],
       errors: [
         {
@@ -2039,7 +2023,7 @@ ruleTester.run('order', rule, {
           message: 'There should be no empty line between import groups',
         },
       ],
-    }),
+    })),
     // Option newlines-between: 'never' with unassigned imports and warnOnUnassignedImports enabled
     test({
       code: `
@@ -2064,7 +2048,7 @@ ruleTester.run('order', rule, {
       ],
     }),
     // Option newlines-between: 'never' cannot fix if there are other statements between imports
-    test({
+    test(withoutAutofixOutput({
       code: `
         import path from 'path';
         export const abc = 123;
@@ -2072,13 +2056,6 @@ ruleTester.run('order', rule, {
         import 'something-else';
         import _ from 'lodash';
       `,
-      output: `
-        import path from 'path';
-        export const abc = 123;
-
-        import 'something-else';
-        import _ from 'lodash';
-      `,
       options: [{ 'newlines-between': 'never' }],
       errors: [
         {
@@ -2086,7 +2063,7 @@ ruleTester.run('order', rule, {
           message: 'There should be no empty line between import groups',
         },
       ],
-    }),
+    })),
     // Option newlines-between: 'always' should report missing empty lines when using not assigned imports
     test({
       code: `
@@ -2170,7 +2147,7 @@ ruleTester.run('order', rule, {
       ],
     }),
     // reorder fix cannot cross function call on moving below #1
-    test({
+    test(withoutAutofixOutput({
       code: `
         const local = require('./local');
 
@@ -2181,22 +2158,12 @@ ruleTester.run('order', rule, {
 
         fn_call();
       `,
-      output: `
-        const local = require('./local');
-
-        fn_call();
-
-        const global1 = require('global1');
-        const global2 = require('global2');
-
-        fn_call();
-      `,
       errors: [{
         message: '`./local` import should occur after import of `global2`',
       }],
-    }),
+    })),
     // reorder fix cannot cross function call on moving below #2
-    test({
+    test(withoutAutofixOutput({
       code: `
         const local = require('./local');
         fn_call();
@@ -2205,20 +2172,12 @@ ruleTester.run('order', rule, {
 
         fn_call();
       `,
-      output: `
-        const local = require('./local');
-        fn_call();
-        const global1 = require('global1');
-        const global2 = require('global2');
-
-        fn_call();
-      `,
       errors: [{
         message: '`./local` import should occur after import of `global2`',
       }],
-    }),
+    })),
     // reorder fix cannot cross function call on moving below #3
-    test({
+    test(withoutAutofixOutput({
       code: `
         const local1 = require('./local1');
         const local2 = require('./local2');
@@ -2232,26 +2191,13 @@ ruleTester.run('order', rule, {
         const global5 = require('global5');
         fn_call();
       `,
-      output: `
-        const local1 = require('./local1');
-        const local2 = require('./local2');
-        const local3 = require('./local3');
-        const local4 = require('./local4');
-        fn_call();
-        const global1 = require('global1');
-        const global2 = require('global2');
-        const global3 = require('global3');
-        const global4 = require('global4');
-        const global5 = require('global5');
-        fn_call();
-      `,
       errors: [
         '`./local1` import should occur after import of `global5`',
         '`./local2` import should occur after import of `global5`',
         '`./local3` import should occur after import of `global5`',
         '`./local4` import should occur after import of `global5`',
       ],
-    }),
+    })),
     // reorder fix cannot cross function call on moving below
     test(withoutAutofixOutput({
       code: `
@@ -2561,7 +2507,7 @@ ruleTester.run('order', rule, {
       }],
     })),
     // reorder fix cannot cross function call on moving below (from #1252)
-    test({
+    test(withoutAutofixOutput({
       code: `
         const env = require('./config');
 
@@ -2572,20 +2518,10 @@ ruleTester.run('order', rule, {
 
         http.createServer(express());
       `,
-      output: `
-        const env = require('./config');
-
-        Object.keys(env);
-
-        const http = require('http');
-        const express = require('express');
-
-        http.createServer(express());
-      `,
       errors: [{
         message: '`./config` import should occur after import of `express`',
       }],
-    }),
+    })),
     // reorder cannot cross non plain requires
     test(withoutAutofixOutput({
       code: `
@@ -3497,19 +3433,13 @@ context('TypeScript', function () {
             ],
           }),
           // warns for out of order unassigned imports (warnOnUnassignedImports enabled)
-          test({
+          test(withoutAutofixOutput({
             code: `
               import './local1';
               import global from 'global1';
               import local from './local2';
               import 'global2';
             `,
-            output: `
-              import './local1';
-              import global from 'global1';
-              import local from './local2';
-              import 'global2';
-            `,
             errors: [
               {
                 message: '`global1` import should occur before import of `./local1`',
@@ -3519,9 +3449,9 @@ context('TypeScript', function () {
               },
             ],
             options: [{ warnOnUnassignedImports: true }],
-          }),
+          })),
           // fix cannot move below unassigned import (warnOnUnassignedImports enabled)
-          test({
+          test(withoutAutofixOutput({
             code: `
               import local from './local';
 
@@ -3530,19 +3460,11 @@ context('TypeScript', function () {
               import global2 from 'global2';
               import global3 from 'global3';
             `,
-            output: `
-              import local from './local';
-
-              import 'global1';
-
-              import global2 from 'global2';
-              import global3 from 'global3';
-            `,
             errors: [{
               message: '`./local` import should occur after import of `global3`',
             }],
             options: [{ warnOnUnassignedImports: true }],
-          }),
+          })),
           // Imports inside module declaration
           test({
             code: `
diff --git a/tests/src/rules/unambiguous.js b/tests/src/rules/unambiguous.js
index 8cef69625f..c103353e49 100644
--- a/tests/src/rules/unambiguous.js
+++ b/tests/src/rules/unambiguous.js
@@ -1,4 +1,5 @@
 import { RuleTester } from 'eslint';
+import { withoutAutofixOutput } from '../rule-tester';
 import { parsers } from '../utils';
 
 const ruleTester = new RuleTester();
@@ -48,11 +49,10 @@ ruleTester.run('unambiguous', rule, {
     },
   ],
   invalid: [
-    {
+    withoutAutofixOutput({
       code: 'function x() {}',
       parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
-      output: 'function x() {}',
       errors: ['This module could be parsed as a valid script.'],
-    },
+    }),
   ],
 });

From 743ebca91a5bc151ce3d5862b52474ceaaf6c8de Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 20 Sep 2024 07:23:53 +1200
Subject: [PATCH 725/767] [Tests] `no-cycle`: don't override the filename

---
 tests/src/rules/no-cycle.js | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index d005727e31..e9b41c8fba 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -8,11 +8,13 @@ const rule = require('rules/no-cycle');
 
 const error = (message) => ({ message });
 
-const test = (def) => _test(Object.assign(def, {
+const test = (def) => _test({
   filename: testFilePath('./cycles/depth-zero.js'),
-}));
-const testVersion = (specifier, t) => _testVersion(specifier, () => Object.assign(t(), {
+  ...def,
+});
+const testVersion = (specifier, t) => _testVersion(specifier, () => ({
   filename: testFilePath('./cycles/depth-zero.js'),
+  ...t(),
 }));
 
 const testDialects = ['es6'];

From 6218a8acb5afde0db1f2273bab1db642a3668269 Mon Sep 17 00:00:00 2001
From: Ivan Rubinson <soryy708@gmail.com>
Date: Wed, 25 Sep 2024 18:14:32 +0300
Subject: [PATCH 726/767] [Docs] `no-cycle`: add `disableScc` to docs

---
 CHANGELOG.md           | 2 ++
 docs/rules/no-cycle.md | 8 ++++++++
 2 files changed, 10 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e40edde5eb..33b4eb4f4e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [Docs] [`no-relative-packages`]: fix typo ([#3066], thanks [@joshuaobrien])
 - [Performance] [`no-cycle`]: dont scc for each linted file ([#3068], thanks [@soryy708])
+- [Docs] [`no-cycle`]: add `disableScc` to docs ([#3070], thanks [@soryy708])
 
 ## [2.30.0] - 2024-09-02
 
@@ -1141,6 +1142,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3070]: https://github.com/import-js/eslint-plugin-import/pull/3070
 [#3068]: https://github.com/import-js/eslint-plugin-import/pull/3068
 [#3066]: https://github.com/import-js/eslint-plugin-import/pull/3066
 [#3065]: https://github.com/import-js/eslint-plugin-import/pull/3065
diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md
index 76e96f95f2..898b75330e 100644
--- a/docs/rules/no-cycle.md
+++ b/docs/rules/no-cycle.md
@@ -94,6 +94,14 @@ export function getBar() { return import('./bar'); }
 
 > Cyclic dependency are **always** a dangerous anti-pattern as discussed extensively in [#2265](https://github.com/import-js/eslint-plugin-import/issues/2265). Please be extra careful about using this option.
 
+#### `disableScc`
+
+This option disables a pre-processing step that calculates [Strongly Connected Components](https://en.wikipedia.org/wiki/Strongly_connected_component), which are used for avoiding unnecessary work checking files in different SCCs for cycles.
+
+However, under some configurations, this pre-processing may be more expensive than the time it saves.
+
+When this option is `true`, we don't calculate any SCC graph, and check all files for cycles (leading to higher time-complexity). Default is `false`.
+
 ## When Not To Use It
 
 This rule is comparatively computationally expensive. If you are pressed for lint

From 61f02a2cac4b9c12bba8da670e5ccdd772a363e2 Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Sun, 15 Sep 2024 11:12:26 -0500
Subject: [PATCH 727/767] [Fix] `exportMap`: export map cache is tainted by
 unreliable parse results

This change addresses and issue observed with the v9 upgrade, where the ExportMap Cache is being tainted with a bad export map, if the parse doesn't yield a `visitorKeys` (which can happen if an incompatible parser is used (e.g. og babel eslint)) for one run of the no-cycle rule.  If a subsequent test is run with a compatible parser, then the bad export map will be found in the cache and used instead of attempting to proceed with the parse.

I also updated the `getExports` test to use a valid parserPath, rather than a mocked one, so that the tests are acting on a valid parserPath.  Otherwise the export map won't be cached following this change.
---
 CHANGELOG.md                 |  2 ++
 src/exportMap/builder.js     |  6 +++++-
 tests/src/core/getExports.js | 24 ++++++++++++++++++------
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33b4eb4f4e..da66f7e87f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - `ExportMap` / flat config: include `languageOptions` in context ([#3052], thanks [@michaelfaith])
 - [`no-named-as-default`]: Allow using an identifier if the export is both a named and a default export ([#3032], thanks [@akwodkiewicz])
 - [`export`]: False positive for exported overloaded functions in TS ([#3065], thanks [@liuxingbaoyu])
+- `exportMap`: export map cache is tainted by unreliable parse results ([#3062], thanks [@michaelfaith])
 
 ### Changed
 - [Docs] [`no-relative-packages`]: fix typo ([#3066], thanks [@joshuaobrien])
@@ -1146,6 +1147,7 @@ for info on changes for earlier releases.
 [#3068]: https://github.com/import-js/eslint-plugin-import/pull/3068
 [#3066]: https://github.com/import-js/eslint-plugin-import/pull/3066
 [#3065]: https://github.com/import-js/eslint-plugin-import/pull/3065
+[#3062]: https://github.com/import-js/eslint-plugin-import/pull/3062
 [#3052]: https://github.com/import-js/eslint-plugin-import/pull/3052
 [#3043]: https://github.com/import-js/eslint-plugin-import/pull/3043
 [#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
diff --git a/src/exportMap/builder.js b/src/exportMap/builder.js
index 5348dba375..f7b9006eff 100644
--- a/src/exportMap/builder.js
+++ b/src/exportMap/builder.js
@@ -92,7 +92,11 @@ export default class ExportMapBuilder {
 
     exportMap.mtime = stats.mtime;
 
-    exportCache.set(cacheKey, exportMap);
+    // If the visitor keys were not populated, then we shouldn't save anything to the cache,
+    // since the parse results may not be reliable.
+    if (exportMap.visitorKeys) {
+      exportCache.set(cacheKey, exportMap);
+    }
     return exportMap;
   }
 
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index 76003410d5..f11a261311 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -1,15 +1,18 @@
 import { expect } from  'chai';
+import fs from 'fs';
 import semver from 'semver';
 import sinon from 'sinon';
 import eslintPkg from 'eslint/package.json';
+import { test as testUnambiguous } from 'eslint-module-utils/unambiguous';
 import typescriptPkg from 'typescript/package.json';
 import * as tsConfigLoader from 'tsconfig-paths/lib/tsconfig-loader';
-import ExportMapBuilder from '../../../src/exportMap/builder';
-
-import * as fs from 'fs';
 
+import ExportMapBuilder from '../../../src/exportMap/builder';
 import { getFilename } from '../utils';
-import { test as testUnambiguous } from 'eslint-module-utils/unambiguous';
+
+const babelPath = require.resolve('babel-eslint');
+const hypotheticalLocation = babelPath.replace('index.js', 'visitor-keys.js');
+const isVisitorKeysSupported = fs.existsSync(hypotheticalLocation);
 
 describe('ExportMap', function () {
   const fakeContext = Object.assign(
@@ -21,7 +24,7 @@ describe('ExportMap', function () {
     },
     {
       settings: {},
-      parserPath: 'babel-eslint',
+      parserPath: require.resolve('babel-eslint'),
     },
   );
 
@@ -36,11 +39,20 @@ describe('ExportMap', function () {
 
   });
 
-  it('returns a cached copy on subsequent requests', function () {
+  (isVisitorKeysSupported ? it : it.skip)('returns a cached copy on subsequent requests', function () {
     expect(ExportMapBuilder.get('./named-exports', fakeContext))
       .to.exist.and.equal(ExportMapBuilder.get('./named-exports', fakeContext));
   });
 
+  it('does not return a cached copy if the parse does not yield a visitor keys', function () {
+    const mockContext = {
+      ...fakeContext,
+      parserPath: 'not-real',
+    };
+    expect(ExportMapBuilder.get('./named-exports', mockContext))
+      .to.exist.and.not.equal(ExportMapBuilder.get('./named-exports', mockContext));
+  });
+
   it('does not return a cached copy after modification', (done) => {
     const firstAccess = ExportMapBuilder.get('./mutator', fakeContext);
     expect(firstAccess).to.exist;

From 3fbe10fa85d5fc2fad338bfb062fb2f57ce996fa Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 26 Sep 2024 08:48:38 +1200
Subject: [PATCH 728/767] [Tests] use re-exported `RuleTester`

This reduces the diff in #2996.
---
 CHANGELOG.md                                       | 2 ++
 tests/src/rule-tester.js                           | 2 ++
 tests/src/rules/consistent-type-specifier-style.js | 2 +-
 tests/src/rules/default.js                         | 2 +-
 tests/src/rules/dynamic-import-chunkname.js        | 3 +--
 tests/src/rules/export.js                          | 2 +-
 tests/src/rules/exports-last.js                    | 2 +-
 tests/src/rules/extensions.js                      | 2 +-
 tests/src/rules/first.js                           | 2 +-
 tests/src/rules/group-exports.js                   | 2 +-
 tests/src/rules/max-dependencies.js                | 2 +-
 tests/src/rules/named.js                           | 2 +-
 tests/src/rules/namespace.js                       | 2 +-
 tests/src/rules/newline-after-import.js            | 3 +--
 tests/src/rules/no-absolute-path.js                | 2 +-
 tests/src/rules/no-amd.js                          | 2 +-
 tests/src/rules/no-anonymous-default-export.js     | 2 +-
 tests/src/rules/no-commonjs.js                     | 3 +--
 tests/src/rules/no-cycle.js                        | 2 +-
 tests/src/rules/no-default-export.js               | 2 +-
 tests/src/rules/no-deprecated.js                   | 2 +-
 tests/src/rules/no-duplicates.js                   | 3 +--
 tests/src/rules/no-dynamic-require.js              | 2 +-
 tests/src/rules/no-empty-named-blocks.js           | 2 +-
 tests/src/rules/no-extraneous-dependencies.js      | 2 +-
 tests/src/rules/no-import-module-exports.js        | 2 +-
 tests/src/rules/no-internal-modules.js             | 2 +-
 tests/src/rules/no-mutable-exports.js              | 2 +-
 tests/src/rules/no-named-as-default-member.js      | 2 +-
 tests/src/rules/no-named-as-default.js             | 2 +-
 tests/src/rules/no-named-default.js                | 2 +-
 tests/src/rules/no-named-export.js                 | 2 +-
 tests/src/rules/no-namespace.js                    | 3 +--
 tests/src/rules/no-nodejs-modules.js               | 2 +-
 tests/src/rules/no-relative-packages.js            | 2 +-
 tests/src/rules/no-relative-parent-imports.js      | 2 +-
 tests/src/rules/no-restricted-paths.js             | 2 +-
 tests/src/rules/no-self-import.js                  | 2 +-
 tests/src/rules/no-unassigned-import.js            | 2 +-
 tests/src/rules/no-unresolved.js                   | 2 +-
 tests/src/rules/no-unused-modules.js               | 2 +-
 tests/src/rules/no-useless-path-segments.js        | 2 +-
 tests/src/rules/no-webpack-loader-syntax.js        | 2 +-
 tests/src/rules/order.js                           | 3 +--
 tests/src/rules/prefer-default-export.js           | 2 +-
 tests/src/rules/unambiguous.js                     | 3 +--
 46 files changed, 48 insertions(+), 51 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index da66f7e87f..8dcb3a98de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] [`no-relative-packages`]: fix typo ([#3066], thanks [@joshuaobrien])
 - [Performance] [`no-cycle`]: dont scc for each linted file ([#3068], thanks [@soryy708])
 - [Docs] [`no-cycle`]: add `disableScc` to docs ([#3070], thanks [@soryy708])
+- [Tests] use re-exported `RuleTester` ([#3071], thanks [@G-Rath])
 
 ## [2.30.0] - 2024-09-02
 
@@ -1143,6 +1144,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3071]: https://github.com/import-js/eslint-plugin-import/pull/3071
 [#3070]: https://github.com/import-js/eslint-plugin-import/pull/3070
 [#3068]: https://github.com/import-js/eslint-plugin-import/pull/3068
 [#3066]: https://github.com/import-js/eslint-plugin-import/pull/3066
diff --git a/tests/src/rule-tester.js b/tests/src/rule-tester.js
index 89c5846120..f00b520d07 100644
--- a/tests/src/rule-tester.js
+++ b/tests/src/rule-tester.js
@@ -1,3 +1,5 @@
 export function withoutAutofixOutput(test) {
   return { ...test, output: test.code };
 }
+
+export { RuleTester } from 'eslint';
diff --git a/tests/src/rules/consistent-type-specifier-style.js b/tests/src/rules/consistent-type-specifier-style.js
index 7799238c32..139457ff60 100644
--- a/tests/src/rules/consistent-type-specifier-style.js
+++ b/tests/src/rules/consistent-type-specifier-style.js
@@ -1,4 +1,4 @@
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import { test, parsers, tsVersionSatisfies, eslintVersionSatisfies, typescriptEslintParserSatisfies } from '../utils';
 
 const rule = require('rules/consistent-type-specifier-style');
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index eb2028c71a..1df57a23aa 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -1,6 +1,6 @@
 import path from 'path';
 import { test, testVersion, SYNTAX_CASES, getTSParsers, parsers } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import semver from 'semver';
 import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
 
diff --git a/tests/src/rules/dynamic-import-chunkname.js b/tests/src/rules/dynamic-import-chunkname.js
index 1362196728..e8f97475da 100644
--- a/tests/src/rules/dynamic-import-chunkname.js
+++ b/tests/src/rules/dynamic-import-chunkname.js
@@ -1,6 +1,5 @@
 import { SYNTAX_CASES, getTSParsers, parsers } from '../utils';
-import { RuleTester } from 'eslint';
-import { withoutAutofixOutput } from '../rule-tester';
+import { RuleTester, withoutAutofixOutput } from '../rule-tester';
 import semver from 'semver';
 
 const rule = require('rules/dynamic-import-chunkname');
diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js
index f16a25ecf5..338501511c 100644
--- a/tests/src/rules/export.js
+++ b/tests/src/rules/export.js
@@ -1,6 +1,6 @@
 import { test, testFilePath, SYNTAX_CASES, getTSParsers, testVersion } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
diff --git a/tests/src/rules/exports-last.js b/tests/src/rules/exports-last.js
index d7122e9a00..a676ae044b 100644
--- a/tests/src/rules/exports-last.js
+++ b/tests/src/rules/exports-last.js
@@ -1,6 +1,6 @@
 import { test } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import rule from 'rules/exports-last';
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 14d84eaa62..97267832c5 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -1,4 +1,4 @@
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import rule from 'rules/extensions';
 import { getTSParsers, test, testFilePath, parsers } from '../utils';
 
diff --git a/tests/src/rules/first.js b/tests/src/rules/first.js
index f34f227b2d..52b71db861 100644
--- a/tests/src/rules/first.js
+++ b/tests/src/rules/first.js
@@ -2,7 +2,7 @@ import { test, getTSParsers, testVersion } from '../utils';
 import fs from 'fs';
 import path from 'path';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/first');
diff --git a/tests/src/rules/group-exports.js b/tests/src/rules/group-exports.js
index c3d07046f0..6f05bc866b 100644
--- a/tests/src/rules/group-exports.js
+++ b/tests/src/rules/group-exports.js
@@ -1,5 +1,5 @@
 import { test } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import rule from 'rules/group-exports';
 import { resolve } from 'path';
 import { default as babelPresetFlow } from 'babel-preset-flow';
diff --git a/tests/src/rules/max-dependencies.js b/tests/src/rules/max-dependencies.js
index 982a4b427a..959ee68de3 100644
--- a/tests/src/rules/max-dependencies.js
+++ b/tests/src/rules/max-dependencies.js
@@ -1,6 +1,6 @@
 import { test, getTSParsers, parsers } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/max-dependencies');
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index 227bffc80d..f506caeb68 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -1,5 +1,5 @@
 import { test, SYNTAX_CASES, getTSParsers, testFilePath, testVersion, parsers } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import path from 'path';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 3f768a5717..60fcb93f6d 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -1,5 +1,5 @@
 import { test, SYNTAX_CASES, getTSParsers, testVersion, testFilePath, parsers } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 
 const ruleTester = new RuleTester({ env: { es6: true } });
diff --git a/tests/src/rules/newline-after-import.js b/tests/src/rules/newline-after-import.js
index 5c827c0d26..984e898550 100644
--- a/tests/src/rules/newline-after-import.js
+++ b/tests/src/rules/newline-after-import.js
@@ -1,5 +1,4 @@
-import { RuleTester } from 'eslint';
-import { withoutAutofixOutput } from '../rule-tester';
+import { RuleTester, withoutAutofixOutput } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 import semver from 'semver';
 import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
diff --git a/tests/src/rules/no-absolute-path.js b/tests/src/rules/no-absolute-path.js
index bfa08465c0..bcf215137b 100644
--- a/tests/src/rules/no-absolute-path.js
+++ b/tests/src/rules/no-absolute-path.js
@@ -1,6 +1,6 @@
 import { test } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-absolute-path');
diff --git a/tests/src/rules/no-amd.js b/tests/src/rules/no-amd.js
index 5317aa8fde..6b66578df3 100644
--- a/tests/src/rules/no-amd.js
+++ b/tests/src/rules/no-amd.js
@@ -1,4 +1,4 @@
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
diff --git a/tests/src/rules/no-anonymous-default-export.js b/tests/src/rules/no-anonymous-default-export.js
index 53b2fc6fbb..37b3009f0c 100644
--- a/tests/src/rules/no-anonymous-default-export.js
+++ b/tests/src/rules/no-anonymous-default-export.js
@@ -1,6 +1,6 @@
 import { test, testVersion, SYNTAX_CASES } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-anonymous-default-export');
diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js
index 9950608a78..3211c085a7 100644
--- a/tests/src/rules/no-commonjs.js
+++ b/tests/src/rules/no-commonjs.js
@@ -1,5 +1,4 @@
-import { RuleTester } from 'eslint';
-import { withoutAutofixOutput } from '../rule-tester';
+import { RuleTester, withoutAutofixOutput } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 
diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js
index e9b41c8fba..ae4baab666 100644
--- a/tests/src/rules/no-cycle.js
+++ b/tests/src/rules/no-cycle.js
@@ -1,6 +1,6 @@
 import { parsers, test as _test, testFilePath, testVersion as _testVersion } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index 6c1a85a1d5..29292427cc 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -1,6 +1,6 @@
 import { parsers, test, testVersion } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-default-export');
diff --git a/tests/src/rules/no-deprecated.js b/tests/src/rules/no-deprecated.js
index 318ea7c368..ad51d23c21 100644
--- a/tests/src/rules/no-deprecated.js
+++ b/tests/src/rules/no-deprecated.js
@@ -1,6 +1,6 @@
 import { test, SYNTAX_CASES, getTSParsers } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-deprecated');
diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js
index a48e4d3f74..cf57a3d599 100644
--- a/tests/src/rules/no-duplicates.js
+++ b/tests/src/rules/no-duplicates.js
@@ -2,8 +2,7 @@ import * as path from 'path';
 import { test as testUtil, getNonDefaultParsers, parsers, tsVersionSatisfies, typescriptEslintParserSatisfies } from '../utils';
 import jsxConfig from '../../../config/react';
 
-import { RuleTester } from 'eslint';
-import { withoutAutofixOutput } from '../rule-tester';
+import { RuleTester, withoutAutofixOutput } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import flatMap from 'array.prototype.flatmap';
diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js
index e316470ec8..fc7cf2b066 100644
--- a/tests/src/rules/no-dynamic-require.js
+++ b/tests/src/rules/no-dynamic-require.js
@@ -1,6 +1,6 @@
 import { parsers, test, testVersion } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/no-empty-named-blocks.js b/tests/src/rules/no-empty-named-blocks.js
index 87965a1407..d9514a845b 100644
--- a/tests/src/rules/no-empty-named-blocks.js
+++ b/tests/src/rules/no-empty-named-blocks.js
@@ -1,6 +1,6 @@
 import { parsers, test } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-empty-named-blocks');
diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js
index dd01c141d3..4a465eb39d 100644
--- a/tests/src/rules/no-extraneous-dependencies.js
+++ b/tests/src/rules/no-extraneous-dependencies.js
@@ -3,7 +3,7 @@ import typescriptConfig from '../../../config/typescript';
 import path from 'path';
 import fs from 'fs';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/no-import-module-exports.js b/tests/src/rules/no-import-module-exports.js
index aa927857e0..5738f8c524 100644
--- a/tests/src/rules/no-import-module-exports.js
+++ b/tests/src/rules/no-import-module-exports.js
@@ -1,5 +1,5 @@
 import path from 'path';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 import { eslintVersionSatisfies, test, testVersion } from '../utils';
 
diff --git a/tests/src/rules/no-internal-modules.js b/tests/src/rules/no-internal-modules.js
index c1c3015453..9fa91ea3d6 100644
--- a/tests/src/rules/no-internal-modules.js
+++ b/tests/src/rules/no-internal-modules.js
@@ -1,4 +1,4 @@
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 import rule from 'rules/no-internal-modules';
 
diff --git a/tests/src/rules/no-mutable-exports.js b/tests/src/rules/no-mutable-exports.js
index 1171443c4a..ff9643b0d7 100644
--- a/tests/src/rules/no-mutable-exports.js
+++ b/tests/src/rules/no-mutable-exports.js
@@ -1,5 +1,5 @@
 import { parsers, test, testVersion } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import rule from 'rules/no-mutable-exports';
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/no-named-as-default-member.js b/tests/src/rules/no-named-as-default-member.js
index 1773176f4f..5c00224ed4 100644
--- a/tests/src/rules/no-named-as-default-member.js
+++ b/tests/src/rules/no-named-as-default-member.js
@@ -1,5 +1,5 @@
 import { test, testVersion, SYNTAX_CASES } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import rule from 'rules/no-named-as-default-member';
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/no-named-as-default.js b/tests/src/rules/no-named-as-default.js
index 7fcd6e4f72..349372067b 100644
--- a/tests/src/rules/no-named-as-default.js
+++ b/tests/src/rules/no-named-as-default.js
@@ -1,5 +1,5 @@
 import { test, testVersion, SYNTAX_CASES, parsers } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-named-as-default');
diff --git a/tests/src/rules/no-named-default.js b/tests/src/rules/no-named-default.js
index 191c9c6ce9..d36e26c448 100644
--- a/tests/src/rules/no-named-default.js
+++ b/tests/src/rules/no-named-default.js
@@ -1,5 +1,5 @@
 import { test, testVersion, SYNTAX_CASES, parsers } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-named-default');
diff --git a/tests/src/rules/no-named-export.js b/tests/src/rules/no-named-export.js
index 58b5da2f85..83ea8571fc 100644
--- a/tests/src/rules/no-named-export.js
+++ b/tests/src/rules/no-named-export.js
@@ -1,4 +1,4 @@
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import { parsers, test, testVersion } from '../utils';
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/no-namespace.js b/tests/src/rules/no-namespace.js
index e297d953a3..f5cd967a22 100644
--- a/tests/src/rules/no-namespace.js
+++ b/tests/src/rules/no-namespace.js
@@ -1,5 +1,4 @@
-import { RuleTester } from 'eslint';
-import { withoutAutofixOutput } from '../rule-tester';
+import { RuleTester, withoutAutofixOutput } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import { test } from '../utils';
diff --git a/tests/src/rules/no-nodejs-modules.js b/tests/src/rules/no-nodejs-modules.js
index b25eb0ce85..cf131ffee2 100644
--- a/tests/src/rules/no-nodejs-modules.js
+++ b/tests/src/rules/no-nodejs-modules.js
@@ -1,6 +1,6 @@
 import { test } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 const isCore = require('is-core-module');
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/no-relative-packages.js b/tests/src/rules/no-relative-packages.js
index 6104aeb9ca..9b424506c5 100644
--- a/tests/src/rules/no-relative-packages.js
+++ b/tests/src/rules/no-relative-packages.js
@@ -1,4 +1,4 @@
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import rule from 'rules/no-relative-packages';
 import { normalize } from 'path';
 
diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js
index 1af9b8cf8d..93c8b97aac 100644
--- a/tests/src/rules/no-relative-parent-imports.js
+++ b/tests/src/rules/no-relative-parent-imports.js
@@ -1,4 +1,4 @@
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import rule from 'rules/no-relative-parent-imports';
 import { parsers, test as _test, testFilePath } from '../utils';
 
diff --git a/tests/src/rules/no-restricted-paths.js b/tests/src/rules/no-restricted-paths.js
index a83a804a0a..c3382ad086 100644
--- a/tests/src/rules/no-restricted-paths.js
+++ b/tests/src/rules/no-restricted-paths.js
@@ -1,4 +1,4 @@
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import rule from 'rules/no-restricted-paths';
 
 import { getTSParsers, test, testFilePath } from '../utils';
diff --git a/tests/src/rules/no-self-import.js b/tests/src/rules/no-self-import.js
index ff1248b43c..dd2ea1bf2d 100644
--- a/tests/src/rules/no-self-import.js
+++ b/tests/src/rules/no-self-import.js
@@ -1,6 +1,6 @@
 import { test, testFilePath } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-self-import');
diff --git a/tests/src/rules/no-unassigned-import.js b/tests/src/rules/no-unassigned-import.js
index f96808cbcc..b73246ac0d 100644
--- a/tests/src/rules/no-unassigned-import.js
+++ b/tests/src/rules/no-unassigned-import.js
@@ -1,7 +1,7 @@
 import { test } from '../utils';
 import * as path from 'path';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-unassigned-import');
diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js
index 9bf1a42d4a..c6e300c5dc 100644
--- a/tests/src/rules/no-unresolved.js
+++ b/tests/src/rules/no-unresolved.js
@@ -4,7 +4,7 @@ import { getTSParsers, test, SYNTAX_CASES, testVersion, parsers } from '../utils
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-unresolved');
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 80bd70227e..22b54ce6f4 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -2,7 +2,7 @@ import { test, testVersion, testFilePath, getTSParsers, parsers } from '../utils
 import jsxConfig from '../../../config/react';
 import typescriptConfig from '../../../config/typescript';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import fs from 'fs';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
diff --git a/tests/src/rules/no-useless-path-segments.js b/tests/src/rules/no-useless-path-segments.js
index d6d0395dea..87f7a73e9a 100644
--- a/tests/src/rules/no-useless-path-segments.js
+++ b/tests/src/rules/no-useless-path-segments.js
@@ -1,5 +1,5 @@
 import { parsers, test } from '../utils';
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/no-useless-path-segments');
diff --git a/tests/src/rules/no-webpack-loader-syntax.js b/tests/src/rules/no-webpack-loader-syntax.js
index 05ad242f50..86114b36c6 100644
--- a/tests/src/rules/no-webpack-loader-syntax.js
+++ b/tests/src/rules/no-webpack-loader-syntax.js
@@ -1,6 +1,6 @@
 import { test, getTSParsers, parsers } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import semver from 'semver';
 
 const ruleTester = new RuleTester();
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index ff6b657304..ea62cec71d 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -1,7 +1,6 @@
 import { test, getTSParsers, getNonDefaultParsers, testFilePath, parsers } from '../utils';
 
-import { RuleTester } from 'eslint';
-import { withoutAutofixOutput } from '../rule-tester';
+import { RuleTester, withoutAutofixOutput } from '../rule-tester';
 import eslintPkg from 'eslint/package.json';
 import semver from 'semver';
 import flatMap from 'array.prototype.flatmap';
diff --git a/tests/src/rules/prefer-default-export.js b/tests/src/rules/prefer-default-export.js
index a7310445b5..8e459873f9 100644
--- a/tests/src/rules/prefer-default-export.js
+++ b/tests/src/rules/prefer-default-export.js
@@ -1,6 +1,6 @@
 import { test, testVersion, getNonDefaultParsers, parsers } from '../utils';
 
-import { RuleTester } from 'eslint';
+import { RuleTester } from '../rule-tester';
 import semver from 'semver';
 import { version as tsEslintVersion } from 'typescript-eslint-parser/package.json';
 
diff --git a/tests/src/rules/unambiguous.js b/tests/src/rules/unambiguous.js
index c103353e49..15c67470ef 100644
--- a/tests/src/rules/unambiguous.js
+++ b/tests/src/rules/unambiguous.js
@@ -1,5 +1,4 @@
-import { RuleTester } from 'eslint';
-import { withoutAutofixOutput } from '../rule-tester';
+import { RuleTester, withoutAutofixOutput } from '../rule-tester';
 import { parsers } from '../utils';
 
 const ruleTester = new RuleTester();

From 468321a2acc667f355fdc03543be9589361ab0ef Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Thu, 26 Sep 2024 05:12:56 -0500
Subject: [PATCH 729/767] [utils] [new] `hash`: add support for hashing
 functions

---
 utils/CHANGELOG.md | 4 ++++
 utils/hash.js      | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 6e71a26f7c..e2a6e9139d 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Added
+- `hash`: add support for hashing functions ([#3072], thanks [@michaelfaith])
+
 ## v2.11.1 - 2024-09-23
 
 ### Fixed
@@ -172,6 +175,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#3072]: https://github.com/import-js/eslint-plugin-import/pull/3072
 [#3061]: https://github.com/import-js/eslint-plugin-import/pull/3061
 [#3057]: https://github.com/import-js/eslint-plugin-import/pull/3057
 [#3049]: https://github.com/import-js/eslint-plugin-import/pull/3049
diff --git a/utils/hash.js b/utils/hash.js
index b3ce618b54..21ed524a9f 100644
--- a/utils/hash.js
+++ b/utils/hash.js
@@ -17,6 +17,8 @@ function hashify(value, hash) {
 
   if (Array.isArray(value)) {
     hashArray(value, hash);
+  } else if (typeof value === 'function') {
+    hash.update(String(value));
   } else if (value instanceof Object) {
     hashObject(value, hash);
   } else {

From 96cad2ad906d8f0cf9a80792a6afb1300a532180 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 26 Sep 2024 12:32:24 -0700
Subject: [PATCH 730/767] [utils] v2.12.0

---
 utils/CHANGELOG.md | 2 ++
 utils/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index e2a6e9139d..619d050633 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+## v2.12.0 - 2024-09-26
+
 ### Added
 - `hash`: add support for hashing functions ([#3072], thanks [@michaelfaith])
 
diff --git a/utils/package.json b/utils/package.json
index 709142fafb..017eb7192b 100644
--- a/utils/package.json
+++ b/utils/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-module-utils",
-  "version": "2.11.1",
+  "version": "2.12.0",
   "description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
   "engines": {
     "node": ">=4"

From ab0941e5fb1aee388816f0b91659e256e33d8710 Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Wed, 25 Sep 2024 20:32:24 -0500
Subject: [PATCH 731/767] [Fix] `exportMap`: improve cacheKey when using flat
 config

Discovered this issue in https://github.com/import-js/eslint-plugin-import/pull/2996#issuecomment-2372522774

This change improves the logic for generating the cache key used for both the exportMap cache and resolver cache when using flat config. Prior to this change, the cache key was a combination of the `parserPath`, a hash of the `parserOptions`, a hash of the plugin settings, and the path of the file. When using flat config, `parserPath` isn't provided. So, there's the possibility of incorrect cache objects being used if someone ran with this plugin using different parsers within the same lint execution, if parserOptions and settings are the same. The equivalent cacheKey construction when using flat config is to use `languageOptions` as a component of the key, rather than `parserPath` and `parserOptions`. One caveat is that the `parser` property of `languageOptions` is an object that oftentimes has the same two functions (`parse` and `parseForESLint`). This won't be reliably distinct when using the base JSON.stringify function to detect changes. So, this implementation uses a replace function along with `JSON.stringify` to stringify function properties along with other property types.

To ensure that this will work properly with v9, I also tested this against #2996 with v9 installed. Not only does it pass all tests in that branch, but it also removes the need to add this exception: https://github.com/import-js/eslint-plugin-import/pull/2996#discussion_r1774135785
---
 CHANGELOG.md                        |  2 +
 package.json                        |  2 +-
 src/exportMap/childContext.js       | 35 +++++++++++---
 tests/src/exportMap/childContext.js | 72 ++++++++++++++++++++++++++++-
 4 files changed, 103 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dcb3a98de..90cabd4eb3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-named-as-default`]: Allow using an identifier if the export is both a named and a default export ([#3032], thanks [@akwodkiewicz])
 - [`export`]: False positive for exported overloaded functions in TS ([#3065], thanks [@liuxingbaoyu])
 - `exportMap`: export map cache is tainted by unreliable parse results ([#3062], thanks [@michaelfaith])
+- `exportMap`: improve cacheKey when using flat config ([#3072], thanks [@michaelfaith])
 
 ### Changed
 - [Docs] [`no-relative-packages`]: fix typo ([#3066], thanks [@joshuaobrien])
@@ -1144,6 +1145,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3072]: https://github.com/import-js/eslint-plugin-import/pull/3072
 [#3071]: https://github.com/import-js/eslint-plugin-import/pull/3071
 [#3070]: https://github.com/import-js/eslint-plugin-import/pull/3070
 [#3068]: https://github.com/import-js/eslint-plugin-import/pull/3068
diff --git a/package.json b/package.json
index 1126b19836..c0a6b56e4a 100644
--- a/package.json
+++ b/package.json
@@ -117,7 +117,7 @@
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
-    "eslint-module-utils": "^2.11.1",
+    "eslint-module-utils": "^2.12.0",
     "hasown": "^2.0.2",
     "is-core-module": "^2.15.1",
     "is-glob": "^4.0.3",
diff --git a/src/exportMap/childContext.js b/src/exportMap/childContext.js
index 3534c59138..8994ac206a 100644
--- a/src/exportMap/childContext.js
+++ b/src/exportMap/childContext.js
@@ -1,10 +1,18 @@
 import { hashObject } from 'eslint-module-utils/hash';
 
-let parserOptionsHash = '';
-let prevParserOptions = '';
+let optionsHash = '';
+let prevOptions = '';
 let settingsHash = '';
 let prevSettings = '';
 
+// Replacer function helps us with serializing the parser nested within `languageOptions`.
+function stringifyReplacerFn(_, value) {
+  if (typeof value === 'function') {
+    return String(value);
+  }
+  return value;
+}
+
 /**
  * don't hold full context object in memory, just grab what we need.
  * also calculate a cacheKey, where parts of the cacheKey hash are memoized
@@ -17,13 +25,28 @@ export default function childContext(path, context) {
     prevSettings = JSON.stringify(settings);
   }
 
-  if (JSON.stringify(parserOptions) !== prevParserOptions) {
-    parserOptionsHash = hashObject({ parserOptions }).digest('hex');
-    prevParserOptions = JSON.stringify(parserOptions);
+  // We'll use either a combination of `parserOptions` and `parserPath` or `languageOptions`
+  // to construct the cache key, depending on whether this is using a flat config or not.
+  let optionsToken;
+  if (!parserPath && languageOptions) {
+    if (JSON.stringify(languageOptions, stringifyReplacerFn) !== prevOptions) {
+      optionsHash = hashObject({ languageOptions }).digest('hex');
+      prevOptions = JSON.stringify(languageOptions, stringifyReplacerFn);
+    }
+    // For languageOptions, we're just using the hashed options as the options token
+    optionsToken = optionsHash;
+  } else {
+    if (JSON.stringify(parserOptions) !== prevOptions) {
+      optionsHash = hashObject({ parserOptions }).digest('hex');
+      prevOptions = JSON.stringify(parserOptions);
+    }
+    // When not using flat config, we use a combination of the hashed parserOptions
+    // and parserPath as the token
+    optionsToken = String(parserPath) + optionsHash;
   }
 
   return {
-    cacheKey: String(parserPath) + parserOptionsHash + settingsHash + String(path),
+    cacheKey: optionsToken + settingsHash + String(path),
     settings,
     parserOptions,
     parserPath,
diff --git a/tests/src/exportMap/childContext.js b/tests/src/exportMap/childContext.js
index 06fa04afec..5bc53fdb06 100644
--- a/tests/src/exportMap/childContext.js
+++ b/tests/src/exportMap/childContext.js
@@ -1,4 +1,5 @@
 import { expect } from 'chai';
+import { hashObject } from 'eslint-module-utils/hash';
 
 import childContext from '../../../src/exportMap/childContext';
 
@@ -16,8 +17,13 @@ describe('childContext', () => {
   const languageOptions = {
     ecmaVersion: 2024,
     sourceType: 'module',
-    parser: {},
+    parser: {
+      parseForESLint() { return 'parser1'; },
+    },
   };
+  const languageOptionsHash = hashObject({ languageOptions }).digest('hex');
+  const parserOptionsHash = hashObject({ parserOptions }).digest('hex');
+  const settingsHash = hashObject({ settings }).digest('hex');
 
   // https://github.com/import-js/eslint-plugin-import/issues/3051
   it('should pass context properties through, if present', () => {
@@ -48,4 +54,68 @@ describe('childContext', () => {
     expect(result.path).to.equal(path);
     expect(result.cacheKey).to.be.a('string');
   });
+
+  it('should construct cache key out of languageOptions if present', () => {
+    const mockContext = {
+      settings,
+      languageOptions,
+    };
+
+    const result = childContext(path, mockContext);
+
+    expect(result.cacheKey).to.equal(languageOptionsHash + settingsHash + path);
+  });
+
+  it('should use the same cache key upon multiple calls', () => {
+    const mockContext = {
+      settings,
+      languageOptions,
+    };
+
+    let result = childContext(path, mockContext);
+
+    const expectedCacheKey = languageOptionsHash + settingsHash + path;
+    expect(result.cacheKey).to.equal(expectedCacheKey);
+
+    result = childContext(path, mockContext);
+    expect(result.cacheKey).to.equal(expectedCacheKey);
+  });
+
+  it('should update cacheKey if different languageOptions are passed in', () => {
+    const mockContext = {
+      settings,
+      languageOptions,
+    };
+
+    let result = childContext(path, mockContext);
+
+    const firstCacheKey = languageOptionsHash + settingsHash + path;
+    expect(result.cacheKey).to.equal(firstCacheKey);
+
+    // Second run with different parser function
+    mockContext.languageOptions = {
+      ...languageOptions,
+      parser: {
+        parseForESLint() { return 'parser2'; },
+      },
+    };
+
+    result = childContext(path, mockContext);
+
+    const secondCacheKey = hashObject({ languageOptions: mockContext.languageOptions }).digest('hex') + settingsHash + path;
+    expect(result.cacheKey).to.not.equal(firstCacheKey);
+    expect(result.cacheKey).to.equal(secondCacheKey);
+  });
+
+  it('should construct cache key out of parserOptions and parserPath if no languageOptions', () => {
+    const mockContext = {
+      settings,
+      parserOptions,
+      parserPath,
+    };
+
+    const result = childContext(path, mockContext);
+
+    expect(result.cacheKey).to.equal(String(parserPath) + parserOptionsHash + settingsHash + path);
+  });
 });

From 6be20dfa1170c9c5f3cf12f328c1a7cc5cd04c13 Mon Sep 17 00:00:00 2001
From: Emin Yilmaz <70356757+unbeauvoyage@users.noreply.github.com>
Date: Thu, 26 Sep 2024 17:19:32 +0900
Subject: [PATCH 732/767] [Docs] `no-restricted-paths`: fix grammar

---
 CHANGELOG.md                      | 3 +++
 docs/rules/no-restricted-paths.md | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 90cabd4eb3..699cd58e45 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Performance] [`no-cycle`]: dont scc for each linted file ([#3068], thanks [@soryy708])
 - [Docs] [`no-cycle`]: add `disableScc` to docs ([#3070], thanks [@soryy708])
 - [Tests] use re-exported `RuleTester` ([#3071], thanks [@G-Rath])
+- [Docs] `no-restricted-paths`: fix grammar ([#3073], thanks [@unbeauvoyage])
 
 ## [2.30.0] - 2024-09-02
 
@@ -1145,6 +1146,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3073]: https://github.com/import-js/eslint-plugin-import/pull/3073
 [#3072]: https://github.com/import-js/eslint-plugin-import/pull/3072
 [#3071]: https://github.com/import-js/eslint-plugin-import/pull/3071
 [#3070]: https://github.com/import-js/eslint-plugin-import/pull/3070
@@ -1997,6 +1999,7 @@ for info on changes for earlier releases.
 [@tomprats]: https://github.com/tomprats
 [@TrevorBurnham]: https://github.com/TrevorBurnham
 [@ttmarek]: https://github.com/ttmarek
+[@unbeauvoyage]: https://github.com/unbeauvoyage
 [@vikr01]: https://github.com/vikr01
 [@wenfangdu]: https://github.com/wenfangdu
 [@wKich]: https://github.com/wKich
diff --git a/docs/rules/no-restricted-paths.md b/docs/rules/no-restricted-paths.md
index 293f3ba009..a905226c22 100644
--- a/docs/rules/no-restricted-paths.md
+++ b/docs/rules/no-restricted-paths.md
@@ -5,7 +5,7 @@
 Some projects contain files which are not always meant to be executed in the same environment.
 For example consider a web application that contains specific code for the server and some specific code for the browser/client. In this case you don’t want to import server-only files in your client code.
 
-In order to prevent such scenarios this rule allows you to define restricted zones where you can forbid files from imported if they match a specific path.
+In order to prevent such scenarios this rule allows you to define restricted zones where you can forbid files from being imported if they match a specific path.
 
 ## Rule Details
 

From 55fa203518fe71a28c697407b436619961009166 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 27 Sep 2024 11:37:41 +1200
Subject: [PATCH 733/767] [Tests] `no-default-export`, `no-named-export`:  add
 test case

---
 CHANGELOG.md                         | 3 ++-
 tests/src/rules/no-default-export.js | 3 +++
 tests/src/rules/no-named-export.js   | 3 +++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 699cd58e45..8c249f1dff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,7 +21,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Performance] [`no-cycle`]: dont scc for each linted file ([#3068], thanks [@soryy708])
 - [Docs] [`no-cycle`]: add `disableScc` to docs ([#3070], thanks [@soryy708])
 - [Tests] use re-exported `RuleTester` ([#3071], thanks [@G-Rath])
-- [Docs] `no-restricted-paths`: fix grammar ([#3073], thanks [@unbeauvoyage])
+- [Docs] [`no-restricted-paths`]: fix grammar ([#3073], thanks [@unbeauvoyage])
+- [Tests] [`no-default-export`], [`no-named-export`]:  add test case (thanks [@G-Rath])
 
 ## [2.30.0] - 2024-09-02
 
diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index 29292427cc..eef8b13224 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -7,6 +7,9 @@ const rule = require('rules/no-default-export');
 
 ruleTester.run('no-default-export', rule, {
   valid: [
+    test({
+      code: 'module.exports = function foo() {}',
+    }),
     test({
       code: `
         export const foo = 'foo';
diff --git a/tests/src/rules/no-named-export.js b/tests/src/rules/no-named-export.js
index 83ea8571fc..c592189f55 100644
--- a/tests/src/rules/no-named-export.js
+++ b/tests/src/rules/no-named-export.js
@@ -6,6 +6,9 @@ const rule = require('rules/no-named-export');
 
 ruleTester.run('no-named-export', rule, {
   valid: [].concat(
+    test({
+      code: 'module.export.foo = function () {}',
+    }),
     test({
       code: 'export default function bar() {};',
     }),

From 0bc13553d44e962b416d602da779364515d3df28 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 30 Sep 2024 13:43:45 +0700
Subject: [PATCH 734/767] [Tests] `no-default-export`, `no-named-export`:  add
 test cases with non-module `sourceType`

---
 tests/src/rules/no-default-export.js | 6 ++++++
 tests/src/rules/no-named-export.js   | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/tests/src/rules/no-default-export.js b/tests/src/rules/no-default-export.js
index eef8b13224..8434ee1486 100644
--- a/tests/src/rules/no-default-export.js
+++ b/tests/src/rules/no-default-export.js
@@ -7,6 +7,12 @@ const rule = require('rules/no-default-export');
 
 ruleTester.run('no-default-export', rule, {
   valid: [
+    test({
+      code: 'module.exports = function foo() {}',
+      parserOptions: {
+        sourceType: 'script',
+      },
+    }),
     test({
       code: 'module.exports = function foo() {}',
     }),
diff --git a/tests/src/rules/no-named-export.js b/tests/src/rules/no-named-export.js
index c592189f55..41f8e8f02c 100644
--- a/tests/src/rules/no-named-export.js
+++ b/tests/src/rules/no-named-export.js
@@ -6,6 +6,12 @@ const rule = require('rules/no-named-export');
 
 ruleTester.run('no-named-export', rule, {
   valid: [].concat(
+    test({
+      code: 'module.export.foo = function () {}',
+      parserOptions: {
+        sourceType: 'script',
+      },
+    }),
     test({
       code: 'module.export.foo = function () {}',
     }),

From 1fa8a07a791b2497c8003e63e45f359eb65b1508 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 30 Sep 2024 13:59:51 +0700
Subject: [PATCH 735/767] [Refactor] create `sourceType` helper

---
 src/core/sourceType.js         | 7 +++++++
 src/rules/no-default-export.js | 3 ++-
 src/rules/no-named-export.js   | 3 ++-
 src/rules/unambiguous.js       | 3 ++-
 4 files changed, 13 insertions(+), 3 deletions(-)
 create mode 100644 src/core/sourceType.js

diff --git a/src/core/sourceType.js b/src/core/sourceType.js
new file mode 100644
index 0000000000..4243be4cf9
--- /dev/null
+++ b/src/core/sourceType.js
@@ -0,0 +1,7 @@
+/**
+ * @param {import('eslint').Rule.RuleContext} context
+ * @returns 'module' | 'script' | undefined
+ */
+export default function sourceType(context) {
+  return context.parserOptions.sourceType;
+}
diff --git a/src/rules/no-default-export.js b/src/rules/no-default-export.js
index fcb4f1b2fd..d18f0c48f6 100644
--- a/src/rules/no-default-export.js
+++ b/src/rules/no-default-export.js
@@ -1,6 +1,7 @@
 import { getSourceCode } from 'eslint-module-utils/contextCompat';
 
 import docsUrl from '../docsUrl';
+import sourceType from '../core/sourceType';
 
 module.exports = {
   meta: {
@@ -15,7 +16,7 @@ module.exports = {
 
   create(context) {
     // ignore non-modules
-    if (context.parserOptions.sourceType !== 'module') {
+    if (sourceType(context) !== 'module') {
       return {};
     }
 
diff --git a/src/rules/no-named-export.js b/src/rules/no-named-export.js
index efaf9dc4c8..fc9b2c48d6 100644
--- a/src/rules/no-named-export.js
+++ b/src/rules/no-named-export.js
@@ -1,3 +1,4 @@
+import sourceType from '../core/sourceType';
 import docsUrl from '../docsUrl';
 
 module.exports = {
@@ -13,7 +14,7 @@ module.exports = {
 
   create(context) {
     // ignore non-modules
-    if (context.parserOptions.sourceType !== 'module') {
+    if (sourceType(context) !== 'module') {
       return {};
     }
 
diff --git a/src/rules/unambiguous.js b/src/rules/unambiguous.js
index 91152ea2af..2491fad3eb 100644
--- a/src/rules/unambiguous.js
+++ b/src/rules/unambiguous.js
@@ -5,6 +5,7 @@
 
 import { isModule } from 'eslint-module-utils/unambiguous';
 import docsUrl from '../docsUrl';
+import sourceType from '../core/sourceType';
 
 module.exports = {
   meta: {
@@ -19,7 +20,7 @@ module.exports = {
 
   create(context) {
     // ignore non-modules
-    if (context.parserOptions.sourceType !== 'module') {
+    if (sourceType(context) !== 'module') {
       return {};
     }
 

From d27a639f338a77a6a0de87cb40c17d7b81a65b41 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Mon, 16 Sep 2024 08:07:30 +1200
Subject: [PATCH 736/767] [Fix] adjust "is source type module" checks for flat
 config

Also see https://github.com/jest-community/eslint-plugin-jest/pull/1639
---
 CHANGELOG.md           | 2 ++
 src/core/sourceType.js | 9 +++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c249f1dff..9865e3b2b6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`export`]: False positive for exported overloaded functions in TS ([#3065], thanks [@liuxingbaoyu])
 - `exportMap`: export map cache is tainted by unreliable parse results ([#3062], thanks [@michaelfaith])
 - `exportMap`: improve cacheKey when using flat config ([#3072], thanks [@michaelfaith])
+- adjust "is source type module" checks for flat config ([#2996], thanks [@G-Rath])
 
 ### Changed
 - [Docs] [`no-relative-packages`]: fix typo ([#3066], thanks [@joshuaobrien])
@@ -1165,6 +1166,7 @@ for info on changes for earlier releases.
 [#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
 [#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
 [#2998]: https://github.com/import-js/eslint-plugin-import/pull/2998
+[#2996]: https://github.com/import-js/eslint-plugin-import/pull/2996
 [#2993]: https://github.com/import-js/eslint-plugin-import/pull/2993
 [#2991]: https://github.com/import-js/eslint-plugin-import/pull/2991
 [#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
diff --git a/src/core/sourceType.js b/src/core/sourceType.js
index 4243be4cf9..5ff92edc97 100644
--- a/src/core/sourceType.js
+++ b/src/core/sourceType.js
@@ -1,7 +1,12 @@
 /**
  * @param {import('eslint').Rule.RuleContext} context
- * @returns 'module' | 'script' | undefined
+ * @returns 'module' | 'script' | 'commonjs' | undefined
  */
 export default function sourceType(context) {
-  return context.parserOptions.sourceType;
+  if ('sourceType' in context.parserOptions) {
+    return context.parserOptions.sourceType;
+  }
+  if ('languageOptions' in context && context.languageOptions) {
+    return context.languageOptions.sourceType;
+  }
 }

From d66cde00ee15c49951071636ccf0b3c4ed8ba831 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Sun, 7 Apr 2024 12:31:53 +1200
Subject: [PATCH 737/767] [New] support eslint v9

Co-authored-by: Gareth Jones <jones258@gmail.com>
Co-authored-by: michael faith <michaelfaith@users.noreply.github.com>
---
 .github/workflows/node-4+.yml                | 27 ++++++++++
 CHANGELOG.md                                 |  1 +
 package.json                                 |  4 +-
 tests/files/issue210.config.flat.js          |  3 ++
 tests/files/just-json-files/eslint.config.js | 28 +++++++++++
 tests/src/cli.js                             | 53 +++++++++++++-------
 tests/src/rule-tester.js                     | 46 ++++++++++++++++-
 tests/src/rules/named.js                     |  4 +-
 tests/src/rules/namespace.js                 |  2 +-
 tests/src/rules/no-unused-modules.js         | 16 +++---
 10 files changed, 152 insertions(+), 32 deletions(-)
 create mode 100644 tests/files/issue210.config.flat.js
 create mode 100644 tests/files/just-json-files/eslint.config.js

diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml
index f2dad098ca..323c2ad540 100644
--- a/.github/workflows/node-4+.yml
+++ b/.github/workflows/node-4+.yml
@@ -36,6 +36,7 @@ jobs:
           - macos-latest
         node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
         eslint:
+          - 9
           - 8
           - 7
           - 6
@@ -63,34 +64,58 @@ jobs:
             env:
               TS_PARSER: 2
         exclude:
+          - node-version: 16
+            eslint: 9
+          - node-version: 15
+            eslint: 9
           - node-version: 15
             eslint: 8
+          - node-version: 14
+            eslint: 9
+          - node-version: 13
+            eslint: 9
           - node-version: 13
             eslint: 8
+          - node-version: 12
+            eslint: 9
+          - node-version: 11
+            eslint: 9
           - node-version: 11
             eslint: 8
+          - node-version: 10
+            eslint: 9
           - node-version: 10
             eslint: 8
+          - node-version: 9
+            eslint: 9
           - node-version: 9
             eslint: 8
           - node-version: 9
             eslint: 7
+          - node-version: 8
+            eslint: 9
           - node-version: 8
             eslint: 8
           - node-version: 8
             eslint: 7
+          - node-version: 7
+            eslint: 9
           - node-version: 7
             eslint: 8
           - node-version: 7
             eslint: 7
           - node-version: 7
             eslint: 6
+          - node-version: 6
+            eslint: 9
           - node-version: 6
             eslint: 8
           - node-version: 6
             eslint: 7
           - node-version: 6
             eslint: 6
+          - node-version: 5
+            eslint: 9
           - node-version: 5
             eslint: 8
           - node-version: 5
@@ -99,6 +124,8 @@ jobs:
             eslint: 6
           - node-version: 5
             eslint: 5
+          - node-version: 4
+            eslint: 9
           - node-version: 4
             eslint: 8
           - node-version: 4
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9865e3b2b6..795fa5bc48 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ## [Unreleased]
 
 ### Added
+- support eslint v9 ([#2996], thanks [@G-Rath] [@michaelfaith])
 - [`order`]: allow validating named imports ([#3043], thanks [@manuth])
 
 ### Fixed
diff --git a/package.json b/package.json
index c0a6b56e4a..53997893aa 100644
--- a/package.json
+++ b/package.json
@@ -76,7 +76,7 @@
     "chai": "^4.3.10",
     "cross-env": "^4.0.0",
     "escope": "^3.6.0",
-    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8",
+    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9",
     "eslint-doc-generator": "^1.6.1",
     "eslint-import-resolver-node": "file:./resolvers/node",
     "eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1",
@@ -106,7 +106,7 @@
     "typescript-eslint-parser": "^15 || ^20 || ^22"
   },
   "peerDependencies": {
-    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+    "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
   },
   "dependencies": {
     "@rtsao/scc": "^1.1.0",
diff --git a/tests/files/issue210.config.flat.js b/tests/files/issue210.config.flat.js
new file mode 100644
index 0000000000..c894376f48
--- /dev/null
+++ b/tests/files/issue210.config.flat.js
@@ -0,0 +1,3 @@
+exports.languageOptions = {
+  sourceType: 'module',
+}
diff --git a/tests/files/just-json-files/eslint.config.js b/tests/files/just-json-files/eslint.config.js
new file mode 100644
index 0000000000..b1bf2070bb
--- /dev/null
+++ b/tests/files/just-json-files/eslint.config.js
@@ -0,0 +1,28 @@
+var jsonPlugin = require('eslint-plugin-json');
+
+if (!jsonPlugin.processors.json) {
+  jsonPlugin.processors.json = jsonPlugin.processors['.json'];
+}
+
+module.exports = [
+  {
+    files: ['tests/files/just-json-files/*.json'],
+    plugins:{
+      json: jsonPlugin,
+    },
+    processor: 'json/json',
+    rules: Object.assign(
+      {},
+      {
+        'import/no-unused-modules': [
+          'error',
+          {
+            'missingExports': false,
+            'unusedExports': true,
+          },
+        ],
+      },
+      jsonPlugin.configs.recommended.rules
+    )
+  },
+];
diff --git a/tests/src/cli.js b/tests/src/cli.js
index 8a73454878..60b8382d09 100644
--- a/tests/src/cli.js
+++ b/tests/src/cli.js
@@ -15,17 +15,29 @@ describe('CLI regression tests', function () {
     let cli;
     before(function () {
       if (ESLint) {
-        eslint = new ESLint({
-          useEslintrc: false,
-          overrideConfigFile: './tests/files/issue210.config.js',
-          rulePaths: ['./src/rules'],
-          overrideConfig: {
-            rules: {
-              named: 2,
+        if (semver.satisfies(eslintPkg.version, '>= 9')) {
+          eslint = new ESLint({
+            overrideConfigFile: './tests/files/issue210.config.flat.js',
+            overrideConfig: {
+              rules: {
+                'import/named': 2,
+              },
             },
-          },
-          plugins: { 'eslint-plugin-import': importPlugin },
-        });
+            plugins: { 'eslint-plugin-import': importPlugin },
+          });
+        } else {
+          eslint = new ESLint({
+            useEslintrc: false,
+            overrideConfigFile: './tests/files/issue210.config.js',
+            rulePaths: ['./src/rules'],
+            overrideConfig: {
+              rules: {
+                named: 2,
+              },
+            },
+            plugins: { 'eslint-plugin-import': importPlugin },
+          });
+        }
       } else {
         cli = new CLIEngine({
           useEslintrc: false,
@@ -56,13 +68,20 @@ describe('CLI regression tests', function () {
         this.skip();
       } else {
         if (ESLint) {
-          eslint = new ESLint({
-            useEslintrc: false,
-            overrideConfigFile: './tests/files/just-json-files/.eslintrc.json',
-            rulePaths: ['./src/rules'],
-            ignore: false,
-            plugins: { 'eslint-plugin-import': importPlugin },
-          });
+          if (semver.satisfies(eslintPkg.version, '>= 9')) {
+            eslint = new ESLint({
+              overrideConfigFile: './tests/files/just-json-files/eslint.config.js',
+              plugins: { 'eslint-plugin-import': importPlugin },
+            });
+          } else {
+            eslint = new ESLint({
+              useEslintrc: false,
+              overrideConfigFile: './tests/files/just-json-files/.eslintrc.json',
+              rulePaths: ['./src/rules'],
+              ignore: false,
+              plugins: { 'eslint-plugin-import': importPlugin },
+            });
+          }
         } else {
           cli = new CLIEngine({
             useEslintrc: false,
diff --git a/tests/src/rule-tester.js b/tests/src/rule-tester.js
index f00b520d07..390c6cd7f7 100644
--- a/tests/src/rule-tester.js
+++ b/tests/src/rule-tester.js
@@ -1,5 +1,47 @@
+import { RuleTester } from 'eslint';
+import { version as eslintVersion } from 'eslint/package.json';
+import semver from 'semver';
+
+export const usingFlatConfig = semver.major(eslintVersion) >= 9;
+
 export function withoutAutofixOutput(test) {
-  return { ...test, output: test.code };
+  return { ...test, ...usingFlatConfig || { output: test.code } };
+}
+
+class FlatCompatRuleTester extends RuleTester {
+  constructor(testerConfig = { parserOptions: { sourceType: 'script' } }) {
+    super(FlatCompatRuleTester._flatCompat(testerConfig));
+  }
+
+  run(ruleName, rule, tests) {
+    super.run(ruleName, rule, {
+      valid: tests.valid.map((t) => FlatCompatRuleTester._flatCompat(t)),
+      invalid: tests.invalid.map((t) => FlatCompatRuleTester._flatCompat(t)),
+    });
+  }
+
+  static _flatCompat(config) {
+    if (!config || !usingFlatConfig || typeof config !== 'object') {
+      return config;
+    }
+
+    const { parser, parserOptions = {}, languageOptions = {}, ...remainingConfig  } = config;
+    const { ecmaVersion, sourceType, ...remainingParserOptions } = parserOptions;
+    const parserObj = typeof parser === 'string' ? require(parser) : parser;
+
+    return {
+      ...remainingConfig,
+      languageOptions: {
+        ...languageOptions,
+        ...parserObj ? { parser: parserObj } : {},
+        ...ecmaVersion ? { ecmaVersion } : {},
+        ...sourceType ? { sourceType } : {},
+        parserOptions: {
+          ...remainingParserOptions,
+        },
+      },
+    };
+  }
 }
 
-export { RuleTester } from 'eslint';
+export { FlatCompatRuleTester as RuleTester };
diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js
index f506caeb68..51a76c1290 100644
--- a/tests/src/rules/named.js
+++ b/tests/src/rules/named.js
@@ -1,5 +1,5 @@
 import { test, SYNTAX_CASES, getTSParsers, testFilePath, testVersion, parsers } from '../utils';
-import { RuleTester } from '../rule-tester';
+import { RuleTester, usingFlatConfig } from '../rule-tester';
 import path from 'path';
 
 import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
@@ -32,7 +32,7 @@ ruleTester.run('named', rule, {
       settings: { 'import/resolve': { extensions: ['.js', '.jsx'] } } }),
 
     // validate that eslint-disable-line silences this properly
-    test({ code: 'import {a, b, d} from "./common"; // eslint-disable-line named' }),
+    test({ code: `import {a, b, d} from "./common"; // eslint-disable-line ${usingFlatConfig ? 'rule-to-test/' : ''}named` }),
 
     test({ code: 'import { foo, bar } from "./re-export-names"' }),
 
diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js
index 60fcb93f6d..2a31d57e19 100644
--- a/tests/src/rules/namespace.js
+++ b/tests/src/rules/namespace.js
@@ -2,7 +2,7 @@ import { test, SYNTAX_CASES, getTSParsers, testVersion, testFilePath, parsers }
 import { RuleTester } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 
-const ruleTester = new RuleTester({ env: { es6: true } });
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
 const rule = require('rules/namespace');
 
 function error(name, namespace) {
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index 22b54ce6f4..d86f406220 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -288,8 +288,8 @@ describe('dynamic imports', function () {
 
   // test for unused exports with `import()`
   ruleTester.run('no-unused-modules', rule, {
-    valid: [
-      test({
+    valid: [].concat(
+      testVersion('< 9', () => ({
         options: unusedExportsOptions,
         code: `
             export const a = 10
@@ -300,10 +300,10 @@ describe('dynamic imports', function () {
             `,
         parser: parsers.BABEL_OLD,
         filename: testFilePath('./no-unused-modules/exports-for-dynamic-js.js'),
-      }),
-    ],
-    invalid: [
-      test({
+      })),
+    ),
+    invalid: [].concat(
+      testVersion('< 9', () => ({
         options: unusedExportsOptions,
         code: `
         export const a = 10
@@ -319,8 +319,8 @@ describe('dynamic imports', function () {
           error(`exported declaration 'b' not used within other modules`),
           error(`exported declaration 'c' not used within other modules`),
           error(`exported declaration 'default' not used within other modules`),
-        ] }),
-    ],
+        ] })),
+    ),
   });
   typescriptRuleTester.run('no-unused-modules', rule, {
     valid: [

From 5a51b9a4ca13cb5fa5cfa349a99999826b5e2aed Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Mon, 8 Apr 2024 17:11:39 +1200
Subject: [PATCH 738/767] [Tests] `rule-tester`: try this babel class
 workaround

---
 tests/src/rule-tester.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/src/rule-tester.js b/tests/src/rule-tester.js
index 390c6cd7f7..103f2fd6fe 100644
--- a/tests/src/rule-tester.js
+++ b/tests/src/rule-tester.js
@@ -8,13 +8,13 @@ export function withoutAutofixOutput(test) {
   return { ...test, ...usingFlatConfig || { output: test.code } };
 }
 
-class FlatCompatRuleTester extends RuleTester {
+class FlatCompatRuleTester {
   constructor(testerConfig = { parserOptions: { sourceType: 'script' } }) {
-    super(FlatCompatRuleTester._flatCompat(testerConfig));
+    this._tester = new RuleTester(FlatCompatRuleTester._flatCompat(testerConfig));
   }
 
   run(ruleName, rule, tests) {
-    super.run(ruleName, rule, {
+    this._tester.run(ruleName, rule, {
       valid: tests.valid.map((t) => FlatCompatRuleTester._flatCompat(t)),
       invalid: tests.invalid.map((t) => FlatCompatRuleTester._flatCompat(t)),
     });

From d225176343d491db07a1c9e6e521ea90f169c928 Mon Sep 17 00:00:00 2001
From: Lenz Weber-Tronic <lorenz.weber-tronic@apollographql.com>
Date: Wed, 5 Jul 2023 12:20:03 +0200
Subject: [PATCH 739/767] [New] `extensions`: add the `checkTypeImports` option

---
 CHANGELOG.md                  |  3 ++
 docs/rules/extensions.md      | 18 ++++++++++
 src/rules/extensions.js       |  9 +++--
 tests/src/rules/extensions.js | 67 +++++++++++++++++++++++++++++++++++
 4 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 795fa5bc48..d1dc35e798 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
 - support eslint v9 ([#2996], thanks [@G-Rath] [@michaelfaith])
 - [`order`]: allow validating named imports ([#3043], thanks [@manuth])
+- [`extensions`]: add the `checkTypeImports` option ([#2817], thanks [@phryneas])
 
 ### Fixed
 - `ExportMap` / flat config: include `languageOptions` in context ([#3052], thanks [@michaelfaith])
@@ -1187,6 +1188,7 @@ for info on changes for earlier releases.
 [#2842]: https://github.com/import-js/eslint-plugin-import/pull/2842
 [#2835]: https://github.com/import-js/eslint-plugin-import/pull/2835
 [#2832]: https://github.com/import-js/eslint-plugin-import/pull/2832
+[#2817]: https://github.com/import-js/eslint-plugin-import/pull/2817
 [#2778]: https://github.com/import-js/eslint-plugin-import/pull/2778
 [#2756]: https://github.com/import-js/eslint-plugin-import/pull/2756
 [#2754]: https://github.com/import-js/eslint-plugin-import/pull/2754
@@ -1942,6 +1944,7 @@ for info on changes for earlier releases.
 [@pcorpet]: https://github.com/pcorpet
 [@Pearce-Ropion]: https://github.com/Pearce-Ropion
 [@Pessimistress]: https://github.com/Pessimistress
+[@phryneas]: https://github.com/phryneas
 [@pmcelhaney]: https://github.com/pmcelhaney
 [@preco21]: https://github.com/preco21
 [@pri1311]: https://github.com/pri1311
diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md
index 946ccb7bf8..5d15e93f15 100644
--- a/docs/rules/extensions.md
+++ b/docs/rules/extensions.md
@@ -56,6 +56,8 @@ For example, `["error", "never", { "svg": "always" }]` would require that all ex
 In that case, if you still want to specify extensions, you can do so inside the **pattern** property.
 Default value of `ignorePackages` is `false`.
 
+By default, `import type` and `export type` style imports/exports are ignored. If you want to check them as well, you can set the `checkTypeImports` option to `true`.
+
 ### Exception
 
 When disallowing the use of certain extensions this rule makes an exception and allows the use of extension when the file would not be resolvable without extension.
@@ -104,6 +106,14 @@ import express from 'express/index';
 import * as path from 'path';
 ```
 
+The following patterns are considered problems when the configuration is set to "never" and the option "checkTypeImports" is set to `true`:
+
+```js
+import type { Foo } from './foo.ts';
+
+export type { Foo } from './foo.ts';
+```
+
 The following patterns are considered problems when configuration set to "always":
 
 ```js
@@ -167,6 +177,14 @@ import express from 'express';
 import foo from '@/foo';
 ```
 
+The following patterns are considered problems when the configuration is set to "always" and the option "checkTypeImports" is set to `true`:
+
+```js
+import type { Foo } from './foo';
+
+export type { Foo } from './foo';
+```
+
 ## When Not To Use It
 
 If you are not concerned about a consistent usage of file extension.
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index b1e5c6d9f1..c2c03a2b17 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -14,6 +14,7 @@ const properties = {
   type: 'object',
   properties: {
     pattern: patternProperties,
+    checkTypeImports: { type: 'boolean' },
     ignorePackages: { type: 'boolean' },
   },
 };
@@ -35,7 +36,7 @@ function buildProperties(context) {
     }
 
     // If this is not the new structure, transfer all props to result.pattern
-    if (obj.pattern === undefined && obj.ignorePackages === undefined) {
+    if (obj.pattern === undefined && obj.ignorePackages === undefined && obj.checkTypeImports === undefined) {
       Object.assign(result.pattern, obj);
       return;
     }
@@ -49,6 +50,10 @@ function buildProperties(context) {
     if (obj.ignorePackages !== undefined) {
       result.ignorePackages = obj.ignorePackages;
     }
+
+    if (obj.checkTypeImports !== undefined) {
+      result.checkTypeImports = obj.checkTypeImports;
+    }
   });
 
   if (result.defaultConfig === 'ignorePackages') {
@@ -168,7 +173,7 @@ module.exports = {
 
       if (!extension || !importPath.endsWith(`.${extension}`)) {
         // ignore type-only imports and exports
-        if (node.importKind === 'type' || node.exportKind === 'type') { return; }
+        if (!props.checkTypeImports && (node.importKind === 'type' || node.exportKind === 'type')) { return; }
         const extensionRequired = isUseOfExtensionRequired(extension, isPackage);
         const extensionForbidden = isUseOfExtensionForbidden(extension);
         if (extensionRequired && !extensionForbidden) {
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 97267832c5..883dfab657 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -3,6 +3,15 @@ import rule from 'rules/extensions';
 import { getTSParsers, test, testFilePath, parsers } from '../utils';
 
 const ruleTester = new RuleTester();
+const ruleTesterWithTypeScriptImports = new RuleTester({
+  settings: {
+    'import/resolver': {
+      typescript: {
+        alwaysTryTypes: true,
+      },
+    },
+  },
+});
 
 ruleTester.run('extensions', rule, {
   valid: [
@@ -689,6 +698,64 @@ describe('TypeScript', () => {
             ],
             parser,
           }),
+          test({
+            code: 'import type T from "./typescript-declare";',
+            errors: ['Missing file extension for "./typescript-declare"'],
+            options: [
+              'always',
+              { ts: 'never', tsx: 'never', js: 'never', jsx: 'never', checkTypeImports: true },
+            ],
+            parser,
+          }),
+          test({
+            code: 'export type { MyType } from "./typescript-declare";',
+            errors: ['Missing file extension for "./typescript-declare"'],
+            options: [
+              'always',
+              { ts: 'never', tsx: 'never', js: 'never', jsx: 'never', checkTypeImports: true },
+            ],
+            parser,
+          }),
+        ],
+      });
+      ruleTesterWithTypeScriptImports.run(`${parser}: (with TS resolver) extensions are enforced for type imports/export when checkTypeImports is set`, rule, {
+        valid: [
+          test({
+            code: 'import type { MyType } from "./typescript-declare.ts";',
+            options: [
+              'always',
+              { checkTypeImports: true },
+            ],
+            parser,
+          }),
+          test({
+            code: 'export type { MyType } from "./typescript-declare.ts";',
+            options: [
+              'always',
+              { checkTypeImports: true },
+            ],
+            parser,
+          }),
+        ],
+        invalid: [
+          test({
+            code: 'import type { MyType } from "./typescript-declare";',
+            errors: ['Missing file extension "ts" for "./typescript-declare"'],
+            options: [
+              'always',
+              { checkTypeImports: true },
+            ],
+            parser,
+          }),
+          test({
+            code: 'export type { MyType } from "./typescript-declare";',
+            errors: ['Missing file extension "ts" for "./typescript-declare"'],
+            options: [
+              'always',
+              { checkTypeImports: true },
+            ],
+            parser,
+          }),
         ],
       });
     });

From 3f1ac249272db87f0191727beeaa368fcbe7aab4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 3 Oct 2024 13:15:10 +0700
Subject: [PATCH 740/767] [utils] [refactor] `parse`: avoid using a regex here

---
 utils/CHANGELOG.md | 3 +++
 utils/parse.js     | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index 619d050633..bb93725125 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Changed
+- [refactor] `parse`: avoid using a regex here (thanks [@ljharb])
+
 ## v2.12.0 - 2024-09-26
 
 ### Added
diff --git a/utils/parse.js b/utils/parse.js
index 03022ac401..793e37152e 100644
--- a/utils/parse.js
+++ b/utils/parse.js
@@ -33,7 +33,7 @@ function keysFromParser(parserPath, parserInstance, parsedResult) {
   // up with a `parsedResult` here.  It also doesn't expose the visitor keys on the parser itself,
   // so we have to try and infer the visitor-keys module from the parserPath.
   // This is NOT supported in flat config!
-  if (typeof parserPath === 'string' && (/.*babel-eslint.*/).test(parserPath)) {
+  if (typeof parserPath === 'string' && parserPath.indexOf('babel-eslint') > -1) {
     return getBabelEslintVisitorKeys(parserPath);
   }
   // The espree parser doesn't have the `parseForESLint` function, so we don't end up with a

From 91f809b28323bfbd27749bae84daed00511b07e5 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 3 Oct 2024 13:18:14 +0700
Subject: [PATCH 741/767] v2.31.0

---
 CHANGELOG.md | 5 ++++-
 package.json | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1dc35e798..cbf393750e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+## [2.31.0] - 2024-10-03
+
 ### Added
 - support eslint v9 ([#2996], thanks [@G-Rath] [@michaelfaith])
 - [`order`]: allow validating named imports ([#3043], thanks [@manuth])
@@ -1646,7 +1648,8 @@ for info on changes for earlier releases.
 [#119]: https://github.com/import-js/eslint-plugin-import/issues/119
 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89
 
-[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.30.0...HEAD
+[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.31.0...HEAD
+[2.31.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.30.0...v2.31.0
 [2.30.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.1...v2.30.0
 [2.29.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.0...v2.29.1
 [2.29.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.1...v2.29.0
diff --git a/package.json b/package.json
index 53997893aa..7852506bd4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-import",
-  "version": "2.30.0",
+  "version": "2.31.0",
   "description": "Import with sanity.",
   "engines": {
     "node": ">=4"

From 67cc79841fc823ad4af2532af2dc6704e4b3b03a Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 3 Oct 2024 17:36:09 +0700
Subject: [PATCH 742/767] [meta] add missing changelog links

---
 CHANGELOG.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cbf393750e..ab57069c42 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,11 +45,11 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`order`]: do not compare first path segment for relative paths ([#2682]) ([#2885], thanks [@mihkeleidast])
 
 ### Changed
-- [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
+- [Docs] [`no-extraneous-dependencies`]: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
 - [`no-unused-modules`]: add console message to help debug [#2866]
 - [Refactor] `ExportMap`: make procedures static instead of monkeypatching exportmap ([#2982], thanks [@soryy708])
 - [Refactor] `ExportMap`: separate ExportMap instance from its builder logic ([#2985], thanks [@soryy708])
-- [Docs] `order`: Add a quick note on how unbound imports and --fix ([#2640], thanks [@minervabot])
+- [Docs] [`order`]: Add a quick note on how unbound imports and --fix ([#2640], thanks [@minervabot])
 - [Tests] appveyor -> GHA (run tests on Windows in both pwsh and WSL + Ubuntu) ([#2987], thanks [@joeyguerra])
 - [actions] migrate OSX tests to GHA ([ljharb#37], thanks [@aks-])
 - [Refactor] `exportMapBuilder`: avoid hoisting ([#2989], thanks [@soryy708])
@@ -1831,6 +1831,7 @@ for info on changes for earlier releases.
 [@fsmaia]: https://github.com/fsmaia
 [@fson]: https://github.com/fson
 [@futpib]: https://github.com/futpib
+[@G-Rath]: https://github.com/G-Rath
 [@gajus]: https://github.com/gajus
 [@gausie]: https://github.com/gausie
 [@gavriguy]: https://github.com/gavriguy

From ac7d3966abdac247deabc373ff3f73dcca765c44 Mon Sep 17 00:00:00 2001
From: seiya <20365512+seiyab@users.noreply.github.com>
Date: Tue, 12 Nov 2024 22:24:47 +0000
Subject: [PATCH 743/767] [resolvers/webpack] [new] add cache option

---
 resolvers/webpack/CHANGELOG.md                |  3 ++
 resolvers/webpack/README.md                   | 11 +++++
 resolvers/webpack/index.js                    | 21 +++++++-
 resolvers/webpack/test/cache.js               | 48 +++++++++++++++++++
 .../files/webpack.function.config.multiple.js |  1 +
 5 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 resolvers/webpack/test/cache.js

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 79b2837e3d..1d23bf6fdd 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -4,6 +4,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
+- [new] add cache option ([#3100], thanks [@seiyab])
 
 ## 0.13.9 - 2024-09-02
 - [refactor] simplify loop ([#3029], thanks [@fregante])
@@ -182,6 +183,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
  - `interpret` configs (such as `.babel.js`). Thanks to [@gausie] for the initial PR ([#164], ages ago! 😅) and [@jquense] for tests ([#278]).
 
+[#3100]: https://github.com/import-js/eslint-plugin-import/pull/3100
 [#3029]: https://github.com/import-js/eslint-plugin-import/pull/3029
 [#2287]: https://github.com/import-js/eslint-plugin-import/pull/2287
 [#2023]: https://github.com/import-js/eslint-plugin-import/pull/2023
@@ -247,6 +249,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 [@Rogeres]: https://github.com/Rogeres
 [@Satyam]: https://github.com/Satyam
 [@Schweinepriester]: https://github.com/Schweinepriester
+[@seiyab]: https://github.com/seiyab
 [@SkeLLLa]: https://github.com/SkeLLLa
 [@taion]: https://github.com/taion
 [@toshafed]: https://github.com/toshafed
diff --git a/resolvers/webpack/README.md b/resolvers/webpack/README.md
index 06513ba141..9b01396898 100644
--- a/resolvers/webpack/README.md
+++ b/resolvers/webpack/README.md
@@ -94,6 +94,17 @@ settings:
         production: true
 ```
 
+If your config is set as a function, it will be evaluated at every resolution. You have an option to prevent this by caching it using the `cache` parameter:
+
+```yaml
+---
+settings:
+  import/resolver:
+    webpack:
+      config: 'webpack.config.js'
+      cache: true
+```
+
 ## Support
 
 [Get supported eslint-import-resolver-webpack with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-eslint-import-resolver-webpack?utm_source=npm-eslint-import-resolver-webpack&utm_medium=referral&utm_campaign=readme)
diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js
index 83297cd185..ae736abe76 100644
--- a/resolvers/webpack/index.js
+++ b/resolvers/webpack/index.js
@@ -311,6 +311,22 @@ function getResolveSync(configPath, webpackConfig, cwd) {
   return cached.value;
 }
 
+const _evalCache = new Map();
+function evaluateFunctionConfigCached(configPath, webpackConfig, env, argv) {
+  const cacheKey = JSON.stringify({ configPath, args: [env, argv] });
+  if (_evalCache.has(cacheKey)) {
+    return _evalCache.get(cacheKey);
+  }
+  const cached = webpackConfig(env, argv);
+  _evalCache.set(cacheKey, cached);
+
+  while (_evalCache.size > MAX_CACHE) {
+    // remove oldest item
+    _evalCache.delete(_evalCache.keys().next().value);
+  }
+  return cached;
+}
+
 /**
  * Find the full path to 'source', given 'file' as a full reference path.
  *
@@ -354,6 +370,7 @@ exports.resolve = function (source, file, settings) {
   const configIndex = settings && settings['config-index'];
   const env = settings && settings.env;
   const argv = settings && typeof settings.argv !== 'undefined' ? settings.argv : {};
+  const shouldCacheFunctionConfig = settings && settings.cache;
   let packageDir;
 
   let configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
@@ -398,7 +415,9 @@ exports.resolve = function (source, file, settings) {
   }
 
   if (typeof webpackConfig === 'function') {
-    webpackConfig = webpackConfig(env, argv);
+    webpackConfig = shouldCacheFunctionConfig
+      ? evaluateFunctionConfigCached(configPath, webpackConfig, env, argv)
+      : webpackConfig(env, argv);
   }
 
   if (isArray(webpackConfig)) {
diff --git a/resolvers/webpack/test/cache.js b/resolvers/webpack/test/cache.js
new file mode 100644
index 0000000000..04d6de0577
--- /dev/null
+++ b/resolvers/webpack/test/cache.js
@@ -0,0 +1,48 @@
+'use strict';
+
+const chai =  require('chai');
+const expect = chai.expect;
+const path = require('path');
+
+const resolve = require('../index').resolve;
+
+const file = path.join(__dirname, 'files', 'src', 'jsx', 'dummy.js');
+
+describe('cache', function () {
+  it('can distinguish different config files', function () {
+    const setting1 = {
+      config: require(path.join(__dirname, './files/webpack.function.config.js')),
+      argv: {
+        mode: 'test',
+      },
+      cache: true,
+    };
+    expect(resolve('baz', file, setting1)).to.have.property('path')
+      .and.equal(path.join(__dirname, 'files', 'some', 'bar', 'bar.js'));
+    const setting2 = {
+      config: require(path.join(__dirname, './files/webpack.function.config.multiple.js')),
+      cache: true,
+    };
+    expect(resolve('baz', file, setting2)).to.have.property('path')
+      .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js'));
+  });
+
+  it('can distinguish different config', function () {
+    const setting1 = {
+      config: require(path.join(__dirname, './files/webpack.function.config.js')),
+      env: {
+        dummy: true,
+      },
+      cache: true,
+    };
+    expect(resolve('bar', file, setting1)).to.have.property('path')
+      .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'bar.js'));
+    const setting2 = {
+      config: require(path.join(__dirname, './files/webpack.function.config.multiple.js')),
+      cache: true,
+    };
+    const result = resolve('bar', file, setting2);
+    expect(result).not.to.have.property('path');
+    expect(result).to.have.property('found').to.be.false;
+  });
+});
diff --git a/resolvers/webpack/test/files/webpack.function.config.multiple.js b/resolvers/webpack/test/files/webpack.function.config.multiple.js
index 4dbc94bbc9..8ab982bbc6 100644
--- a/resolvers/webpack/test/files/webpack.function.config.multiple.js
+++ b/resolvers/webpack/test/files/webpack.function.config.multiple.js
@@ -7,6 +7,7 @@ module.exports = [function(env) {
       alias: {
         'foo': path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'),
         'bar': env ? path.join(__dirname, 'some', 'goofy', 'path', 'bar.js') : undefined,
+        'baz': path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'),
         'some-alias': path.join(__dirname, 'some'),
       },
       modules: [

From a20d84398a7946f53f2f20a83d6ff028bebbce62 Mon Sep 17 00:00:00 2001
From: Yuri Mikushov <mikushov.yu@gmail.com>
Date: Fri, 15 Nov 2024 09:38:43 +0100
Subject: [PATCH 744/767] [Docs] `dynamic-import-chunkname`:  fix typo in usage
 of the rule

---
 docs/rules/dynamic-import-chunkname.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/rules/dynamic-import-chunkname.md b/docs/rules/dynamic-import-chunkname.md
index de554148ee..d9ee8d15e2 100644
--- a/docs/rules/dynamic-import-chunkname.md
+++ b/docs/rules/dynamic-import-chunkname.md
@@ -15,7 +15,7 @@ You can also configure the regex format you'd like to accept for the webpackChun
 
  ```javascript
 {
-  "dynamic-import-chunkname": [2, {
+  "import/dynamic-import-chunkname": [2, {
     importFunctions: ["dynamicImport"],
     webpackChunknameFormat: "[a-zA-Z0-57-9-/_]+",
     allowEmpty: false

From d5f295081ed1fcf9ff1b21a1a586cc50caebe36f Mon Sep 17 00:00:00 2001
From: "Xunnamius (Romulus)" <Xunnamius@users.noreply.github.com>
Date: Mon, 18 Nov 2024 03:06:33 -0800
Subject: [PATCH 745/767] [Docs] `extensions`, `order`: improve documentation

---
 .markdownlint.json       |   3 +
 CHANGELOG.md             |   5 +
 docs/rules/extensions.md |  55 ++-
 docs/rules/order.md      | 915 ++++++++++++++++++++++++++++++++-------
 4 files changed, 815 insertions(+), 163 deletions(-)

diff --git a/.markdownlint.json b/.markdownlint.json
index d179615f45..02a066730b 100644
--- a/.markdownlint.json
+++ b/.markdownlint.json
@@ -1,5 +1,8 @@
 {
   "line-length": false,
+  "no-duplicate-heading": {
+    "siblings_only": true
+  },
   "ul-indent": {
     "start_indent": 1,
     "start_indented": true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab57069c42..2174fc46bf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Changed
+- [Docs] `extensions`, `order`: improve documentation ([#3106], thanks [@Xunnamius])
+
 ## [2.31.0] - 2024-10-03
 
 ### Added
@@ -1152,6 +1155,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3106]: https://github.com/import-js/eslint-plugin-import/pull/3106
 [#3073]: https://github.com/import-js/eslint-plugin-import/pull/3073
 [#3072]: https://github.com/import-js/eslint-plugin-import/pull/3072
 [#3071]: https://github.com/import-js/eslint-plugin-import/pull/3071
@@ -2018,6 +2022,7 @@ for info on changes for earlier releases.
 [@wtgtybhertgeghgtwtg]: https://github.com/wtgtybhertgeghgtwtg
 [@xM8WVqaG]: https://github.com/xM8WVqaG
 [@xpl]: https://github.com/xpl
+[@Xunnamius]: https://github.com/Xunnamius
 [@yesl-kim]: https://github.com/yesl-kim
 [@yndajas]: https://github.com/yndajas
 [@yordis]: https://github.com/yordis
diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md
index 5d15e93f15..bd9f3f3584 100644
--- a/docs/rules/extensions.md
+++ b/docs/rules/extensions.md
@@ -10,13 +10,13 @@ In order to provide a consistent use of file extensions across your code base, t
 
 This rule either takes one string option, one object option, or a string and an object option. If it is the string `"never"` (the default value), then the rule forbids the use for any extension. If it is the string `"always"`, then the rule enforces the use of extensions for all import statements. If it is the string `"ignorePackages"`, then the rule enforces the use of extensions for all import statements except package imports.
 
-```json
+```jsonc
 "import/extensions": [<severity>, "never" | "always" | "ignorePackages"]
 ```
 
 By providing an object you can configure each extension separately.
 
-```json
+```jsonc
 "import/extensions": [<severity>, {
   <extension>: "never" | "always" | "ignorePackages"
 }]
@@ -26,7 +26,7 @@ By providing an object you can configure each extension separately.
 
 By providing both a string and an object, the string will set the default setting for all extensions, and the object can be used to set granular overrides for specific extensions.
 
-```json
+```jsonc
 "import/extensions": [
   <severity>,
   "never" | "always" | "ignorePackages",
@@ -40,7 +40,7 @@ For example, `["error", "never", { "svg": "always" }]` would require that all ex
 
 `ignorePackages` can be set as a separate boolean option like this:
 
-```json
+```jsonc
 "import/extensions": [
   <severity>,
   "never" | "always" | "ignorePackages",
@@ -58,6 +58,50 @@ Default value of `ignorePackages` is `false`.
 
 By default, `import type` and `export type` style imports/exports are ignored. If you want to check them as well, you can set the `checkTypeImports` option to `true`.
 
+Unfortunately, in more advanced linting setups, such as when employing custom specifier aliases (e.g. you're using `eslint-import-resolver-alias`, `paths` in `tsconfig.json`, etc), this rule can be too coarse-grained when determining which imports to ignore and on which to enforce the config.
+This is especially troublesome if you have import specifiers that [look like externals or builtins](./order.md#how-imports-are-grouped).
+
+Set `pathGroupOverrides` to force this rule to always ignore certain imports and never ignore others.
+`pathGroupOverrides` accepts an array of one or more [`PathGroupOverride`](#pathgroupoverride) objects.
+
+For example:
+
+```jsonc
+"import/extensions": [
+  <severity>,
+  "never" | "always" | "ignorePackages",
+  {
+    ignorePackages: true | false,
+    pattern: {
+      <extension>: "never" | "always" | "ignorePackages"
+    },
+    pathGroupOverrides: [
+      {
+        pattern: "package-name-to-ignore",
+        action: "ignore",
+      },
+      {
+        pattern: "bespoke+alias:{*,*/**}",
+        action: "enforce",
+      }
+    ]
+  }
+]
+```
+
+> \[!NOTE]
+>
+> `pathGroupOverrides` is inspired by [`pathGroups` in `'import/order'`](./order.md#pathgroups) and shares a similar interface.
+> If you're using `pathGroups` already, you may find `pathGroupOverrides` very useful.
+
+### `PathGroupOverride`
+
+|     property     | required |          type           | description                                                     |
+| :--------------: | :------: | :---------------------: | --------------------------------------------------------------- |
+|     `pattern`    |    ☑️     |        `string`         | [Minimatch pattern][16] for specifier matching                  |
+| `patternOptions` |          |        `object`         | [Minimatch options][17]; default: `{nocomment: true}`           |
+|      `action`    |    ☑️     | `"enforce" \| "ignore"` | What action to take on imports whose specifiers match `pattern` |
+
 ### Exception
 
 When disallowing the use of certain extensions this rule makes an exception and allows the use of extension when the file would not be resolvable without extension.
@@ -190,3 +234,6 @@ export type { Foo } from './foo';
 If you are not concerned about a consistent usage of file extension.
 
 In the future, when this rule supports native node ESM resolution, and the plugin is configured to use native rather than transpiled ESM (a config option that is not yet available) - setting this to `always` will have no effect.
+
+[16]: https://www.npmjs.com/package/minimatch#features
+[17]: https://www.npmjs.com/package/minimatch#options
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 6762799534..fcdd4fda7e 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -6,7 +6,7 @@
 
 Enforce a convention in the order of `require()` / `import` statements.
 
-With the [`groups`](#groups-array) option set to `["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"]` the order is as shown in the following example:
+With the [`groups`][18] option set to `["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"]` the order is as shown in the following example:
 
 ```ts
 // 1. node "builtin" modules
@@ -32,9 +32,7 @@ import log = console.log;
 import type { Foo } from 'foo';
 ```
 
-Unassigned imports are ignored, as the order they are imported in may be important.
-
-Statements using the ES6 `import` syntax must appear before any `require()` statements.
+See [here][3] for further details on how imports are grouped.
 
 ## Fail
 
@@ -98,86 +96,151 @@ import 'format2.css';  // OK
 
 ## Options
 
-This rule supports the following options:
+This rule supports the following options (none of which are required):
 
-### `groups: [array]`
+ - [`groups`][18]
+ - [`pathGroups`][8]
+ - [`pathGroupsExcludedImportTypes`][9]
+ - [`distinctGroup`][32]
+ - [`newlines-between`][20]
+ - [`alphabetize`][30]
+ - [`named`][33]
+ - [`warnOnUnassignedImports`][5]
+ - [`sortTypesAmongThemselves`][7]
+ - [`newlines-between-types`][27]
+ - [`consolidateIslands`][25]
 
-How groups are defined, and the order to respect. `groups` must be an array of `string` or [`string`]. The only allowed `string`s are:
-`"builtin"`, `"external"`, `"internal"`, `"unknown"`, `"parent"`, `"sibling"`, `"index"`, `"object"`, `"type"`.
-The enforced order is the same as the order of each element in a group. Omitted types are implicitly grouped together as the last element. Example:
+---
 
-```ts
-[
-  'builtin', // Built-in types are first
-  ['sibling', 'parent'], // Then sibling and parent types. They can be mingled together
-  'index', // Then the index file
-  'object',
-  // Then the rest: internal and external type
-]
-```
+### `groups`
 
-The default value is `["builtin", "external", "parent", "sibling", "index"]`.
+Valid values: `("builtin" | "external" | "internal" | "unknown" | "parent" | "sibling" | "index" | "object" | "type")[]` \
+Default: `["builtin", "external", "parent", "sibling", "index"]`
 
-You can set the options like this:
+Determines which imports are subject to ordering, and how to order
+them. The predefined groups are: `"builtin"`, `"external"`, `"internal"`,
+`"unknown"`, `"parent"`, `"sibling"`, `"index"`, `"object"`, and `"type"`.
 
-```ts
-"import/order": [
-  "error",
-  {
+The import order enforced by this rule is the same as the order of each group
+in `groups`. Imports belonging to groups omitted from `groups` are lumped
+together at the end.
+
+#### Example
+
+```jsonc
+{
+  "import/order": ["error", {
     "groups": [
-      "index",
-      "sibling",
-      "parent",
-      "internal",
-      "external",
+      // Imports of builtins are first
       "builtin",
+      // Then sibling and parent imports. They can be mingled together
+      ["sibling", "parent"],
+      // Then index file imports
+      "index",
+      // Then any arcane TypeScript imports
       "object",
-      "type"
-    ]
-  }
-]
+      // Then the omitted imports: internal, external, type, unknown
+    ],
+  }],
+}
 ```
 
-### `pathGroups: [array of objects]`
+#### How Imports Are Grouped
 
-To be able to group by paths mostly needed with aliases pathGroups can be defined.
+An import (a `ImportDeclaration`, `TSImportEqualsDeclaration`, or `require()` `CallExpression`) is grouped by its type (`"require"` vs `"import"`), its [specifier][4], and any corresponding identifiers.
 
-Properties of the objects
-
-| property       | required | type   | description   |
-|----------------|:--------:|--------|---------------|
-| pattern        |     x    | string | minimatch pattern for the paths to be in this group (will not be used for builtins or externals) |
-| patternOptions |          | object | options for minimatch, default: { nocomment: true } |
-| group          |     x    | string | one of the allowed groups, the pathGroup will be positioned relative to this group |
-| position       |          | string | defines where around the group the pathGroup will be positioned, can be 'after' or 'before', if not provided pathGroup will be positioned like the group |
+```ts
+import { identifier1, identifier2 } from 'specifier1';
+import type { MyType } from 'specifier2';
+const identifier3 = require('specifier3');
+```
 
-```json
+Roughly speaking, the grouping algorithm is as follows:
+
+1. If the import has no corresponding identifiers (e.g. `import './my/thing.js'`), is otherwise "unassigned," or is an unsupported use of `require()`, and [`warnOnUnassignedImports`][5] is disabled, it will be ignored entirely since the order of these imports may be important for their [side-effects][31]
+2. If the import is part of an arcane TypeScript declaration (e.g. `import log = console.log`), it will be considered **object**. However, note that external module references (e.g. `import x = require('z')`) are treated as normal `require()`s and import-exports (e.g. `export import w = y;`) are ignored entirely
+3. If the import is [type-only][6], `"type"` is in `groups`, and [`sortTypesAmongThemselves`][7] is disabled, it will be considered **type** (with additional implications if using [`pathGroups`][8] and `"type"` is in [`pathGroupsExcludedImportTypes`][9])
+4. If the import's specifier matches [`import/internal-regex`][28], it will be considered **internal**
+5. If the import's specifier is an absolute path, it will be considered **unknown**
+6. If the import's specifier has the name of a Node.js core module (using [is-core-module][10]), it will be considered **builtin**
+7. If the import's specifier matches [`import/core-modules`][11], it will be considered **builtin**
+8. If the import's specifier is a path relative to the parent directory of its containing file (e.g. starts with `../`), it will be considered **parent**
+9. If the import's specifier is one of `['.', './', './index', './index.js']`, it will be considered **index**
+10. If the import's specifier is a path relative to its containing file (e.g. starts with `./`), it will be considered **sibling**
+11. If the import's specifier is a path pointing to a file outside the current package's root directory (determined using [package-up][12]), it will be considered **external**
+12. If the import's specifier matches [`import/external-module-folders`][29] (defaults to matching anything pointing to files within the current package's `node_modules` directory), it will be considered **external**
+13. If the import's specifier is a path pointing to a file within the current package's root directory (determined using [package-up][12]), it will be considered **internal**
+14. If the import's specifier has a name that looks like a scoped package (e.g. `@scoped/package-name`), it will be considered **external**
+15. If the import's specifier has a name that starts with a word character, it will be considered **external**
+16. If this point is reached, the import will be ignored entirely
+
+At the end of the process, if they co-exist in the same file, all top-level `require()` statements that haven't been ignored are shifted (with respect to their order) below any ES6 `import` or similar declarations. Finally, any type-only declarations are potentially reorganized according to [`sortTypesAmongThemselves`][7].
+
+### `pathGroups`
+
+Valid values: `PathGroup[]` \
+Default: `[]`
+
+Sometimes [the predefined groups][18] are not fine-grained
+enough, especially when using import aliases. `pathGroups` defines one or more
+[`PathGroup`][13]s relative to a predefined group. Imports are associated with a
+[`PathGroup`][13] based on path matching against the import specifier (using
+[minimatch][14]).
+
+> \[!IMPORTANT]
+>
+> Note that, by default, imports grouped as `"builtin"`, `"external"`, or `"object"` will not be considered for further `pathGroups` matching unless they are removed from [`pathGroupsExcludedImportTypes`][9].
+
+#### `PathGroup`
+
+|     property     | required |          type          | description                                                                                                                     |
+| :--------------: | :------: | :--------------------: | ------------------------------------------------------------------------------------------------------------------------------- |
+|     `pattern`    |    ☑️    |        `string`        | [Minimatch pattern][16] for specifier matching                                                                                  |
+| `patternOptions` |          |        `object`        | [Minimatch options][17]; default: `{nocomment: true}`                                                                           |
+|      `group`     |    ☑️    | [predefined group][18] | One of the [predefined groups][18] to which matching imports will be positioned relatively                                      |
+|    `position`    |          |  `"after" \| "before"` | Where, in relation to `group`, matching imports will be positioned; default: same position as `group` (neither before or after) |
+
+#### Example
+
+```jsonc
 {
   "import/order": ["error", {
     "pathGroups": [
       {
+        // Minimatch pattern used to match against specifiers
         "pattern": "~/**",
-        "group": "external"
+        // The predefined group this PathGroup is defined in relation to
+        "group": "external",
+        // How matching imports will be positioned relative to "group"
+        "position": "after"
       }
     ]
   }]
 }
 ```
 
-### `distinctGroup: [boolean]`
+### `pathGroupsExcludedImportTypes`
 
-This changes how `pathGroups[].position` affects grouping. The property is most useful when `newlines-between` is set to `always` and at least 1 `pathGroups` entry has a `position` property set.
+Valid values: `("builtin" | "external" | "internal" | "unknown" | "parent" | "sibling" | "index" | "object" | "type")[]` \
+Default: `["builtin", "external", "object"]`
 
-By default, in the context of a particular `pathGroup` entry, when setting `position`, a new "group" will silently be created. That is, even if the `group` is specified, a newline will still separate imports that match that `pattern` with the rest of the group (assuming `newlines-between` is `always`). This is undesirable if your intentions are to use `position` to position _within_ the group (and not create a new one). Override this behavior by setting `distinctGroup` to `false`; this will keep imports within the same group as intended.
+By default, imports in certain [groups][18] are excluded
+from being matched against [`pathGroups`][8] to prevent overeager sorting. Use
+`pathGroupsExcludedImportTypes` to modify which groups are excluded.
 
-Note that currently, `distinctGroup` defaults to `true`. However, in a later update, the default will change to `false`
+> \[!TIP]
+>
+> If using imports with custom specifier aliases (e.g.
+> you're using `eslint-import-resolver-alias`, `paths` in `tsconfig.json`, etc) that [end up
+> grouped][3] as `"builtin"` or `"external"` imports,
+> remove them from  `pathGroupsExcludedImportTypes` to ensure they are ordered
+> correctly.
 
-Example:
+#### Example
 
-```json
+```jsonc
 {
   "import/order": ["error", {
-    "newlines-between": "always",
     "pathGroups": [
       {
         "pattern": "@app/**",
@@ -185,54 +248,74 @@ Example:
         "position": "after"
       }
     ],
-    "distinctGroup": false
+    "pathGroupsExcludedImportTypes": ["builtin"]
   }]
 }
 ```
 
-### `pathGroupsExcludedImportTypes: [array]`
+### `distinctGroup`
+
+Valid values: `boolean` \
+Default: `true`
+
+> \[!CAUTION]
+>
+> Currently, `distinctGroup` defaults to `true`. However, in a later update, the
+> default will change to `false`.
 
-This defines import types that are not handled by configured pathGroups.
-If you have added path groups with patterns that look like `"builtin"` or `"external"` imports, you have to remove this group (`"builtin"` and/or `"external"`) from the default exclusion list (e.g., `["builtin", "external", "object"]`, etc) to sort these path groups correctly.
+This changes how [`PathGroup.position`][13] affects grouping, and is most useful when [`newlines-between`][20] is set to `always` and at least one [`PathGroup`][13] has a `position` property set.
 
-Example:
+When [`newlines-between`][20] is set to `always` and an import matching a specific [`PathGroup.pattern`][13] is encountered, that import is added to a sort of "sub-group" associated with that [`PathGroup`][13]. Thanks to [`newlines-between`][20], imports in this "sub-group" will have a new line separating them from the rest of the imports in [`PathGroup.group`][13].
 
-```json
+This behavior can be undesirable when using [`PathGroup.position`][13] to order imports _within_ [`PathGroup.group`][13] instead of creating a distinct "sub-group". Set `distinctGroup` to `false` to disable the creation of these "sub-groups".
+
+#### Example
+
+```jsonc
 {
   "import/order": ["error", {
+    "distinctGroup": false,
+    "newlines-between": "always",
     "pathGroups": [
       {
         "pattern": "@app/**",
         "group": "external",
         "position": "after"
       }
-    ],
-    "pathGroupsExcludedImportTypes": ["builtin"]
+    ]
   }]
 }
 ```
 
-[Import Type](https://github.com/import-js/eslint-plugin-import/blob/HEAD/src/core/importType.js#L90) is resolved as a fixed string in predefined set, it can't be a `patterns`(e.g., `react`, `react-router-dom`, etc). See [#2156] for details.
+### `newlines-between`
+
+Valid values: `"ignore" | "always" | "always-and-inside-groups" | "never"` \
+Default: `"ignore"`
+
+Enforces or forbids new lines between import groups.
 
-### `newlines-between: [ignore|always|always-and-inside-groups|never]`
+ - If set to `ignore`, no errors related to new lines between import groups will be reported
 
-Enforces or forbids new lines between import groups:
+ - If set to `always`, at least one new line between each group will be enforced, and new lines inside a group will be forbidden
 
- - If set to `ignore`, no errors related to new lines between import groups will be reported.
- - If set to `always`, at least one new line between each group will be enforced, and new lines inside a group will be forbidden. To prevent multiple lines between imports, core `no-multiple-empty-lines` rule can be used.
- - If set to `always-and-inside-groups`, it will act like `always` except newlines are allowed inside import groups.
- - If set to `never`, no new lines are allowed in the entire import section.
+  > [!TIP]
+  >
+  > To prevent multiple lines between imports, the [`no-multiple-empty-lines` rule][21], or a tool like [Prettier][22], can be used.
 
-The default value is `"ignore"`.
+ - If set to `always-and-inside-groups`, it will act like `always` except new lines are allowed inside import groups
 
-With the default group setting, the following will be invalid:
+ - If set to `never`, no new lines are allowed in the entire import section
+
+#### Example
+
+With the default [`groups`][18] setting, the following will fail the rule check:
 
 ```ts
 /* eslint import/order: ["error", {"newlines-between": "always"}] */
 import fs from 'fs';
 import path from 'path';
-import index from './';
 import sibling from './foo';
+import index from './';
 ```
 
 ```ts
@@ -240,8 +323,8 @@ import sibling from './foo';
 import fs from 'fs';
 
 import path from 'path';
-import index from './';
 import sibling from './foo';
+import index from './';
 ```
 
 ```ts
@@ -249,21 +332,21 @@ import sibling from './foo';
 import fs from 'fs';
 import path from 'path';
 
-import index from './';
-
 import sibling from './foo';
+
+import index from './';
 ```
 
-while those will be valid:
+While this will pass:
 
 ```ts
 /* eslint import/order: ["error", {"newlines-between": "always"}] */
 import fs from 'fs';
 import path from 'path';
 
-import index from './';
-
 import sibling from './foo';
+
+import index from './';
 ```
 
 ```ts
@@ -272,163 +355,677 @@ import fs from 'fs';
 
 import path from 'path';
 
-import index from './';
-
 import sibling from './foo';
+
+import index from './';
 ```
 
 ```ts
 /* eslint import/order: ["error", {"newlines-between": "never"}] */
 import fs from 'fs';
 import path from 'path';
-import index from './';
 import sibling from './foo';
+import index from './';
 ```
 
-### `named: true|false|{ enabled: true|false, import: true|false, export: true|false, require: true|false, cjsExports: true|false, types: mixed|types-first|types-last }`
+### `alphabetize`
 
-Enforce ordering of names within imports and exports:
+Valid values: `{ order?: "asc" | "desc" | "ignore", orderImportKind?: "asc" | "desc" | "ignore", caseInsensitive?: boolean }` \
+Default: `{ order: "ignore", orderImportKind: "ignore", caseInsensitive: false }`
 
- - If set to `true`, named imports must be ordered according to the `alphabetize` options
- - If set to `false`, named imports can occur in any order
+Determine the sort order of imports within each [predefined group][18] or [`PathGroup`][8] alphabetically based on specifier.
 
-`enabled` enables the named ordering for all expressions by default.
-Use `import`, `export` and `require` and `cjsExports` to override the enablement for the following kind of expressions:
+> \[!NOTE]
+>
+> Imports will be alphabetized based on their _specifiers_, not by their
+> identifiers. For example, `const a = require('z');` will come _after_ `const z = require('a');` when `alphabetize` is set to `{ order: "asc" }`.
+
+Valid properties and their values include:
+
+ - **`order`**: use `"asc"` to sort in ascending order, `"desc"` to sort in descending order, or "ignore" to prevent sorting
+
+ - **`orderImportKind`**: use `"asc"` to sort various _import kinds_, e.g. [type-only and typeof imports][6], in ascending order, `"desc"` to sort them in descending order, or "ignore" to prevent sorting
+
+ - **`caseInsensitive`**: use `true` to ignore case and `false` to consider case when sorting
+
+#### Example
+
+Given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "alphabetize": {
+      "order": "asc",
+      "caseInsensitive": true
+    }
+  }]
+}
+```
+
+This will fail the rule check:
+
+```ts
+import React, { PureComponent } from 'react';
+import aTypes from 'prop-types';
+import { compose, apply } from 'xcompose';
+import * as classnames from 'classnames';
+import blist from 'BList';
+```
+
+While this will pass:
+
+```ts
+import blist from 'BList';
+import * as classnames from 'classnames';
+import aTypes from 'prop-types';
+import React, { PureComponent } from 'react';
+import { compose, apply } from 'xcompose';
+```
+
+### `named`
+
+Valid values: `boolean | { enabled: boolean, import?: boolean, export?: boolean, require?: boolean, cjsExports?: boolean, types?: "mixed" | "types-first" | "types-last" }` \
+Default: `false`
+
+Enforce ordering of names within imports and exports.
+
+If set to `true` or `{ enabled: true }`, _all_ named imports must be ordered
+according to [`alphabetize`][30]. If set to `false` or `{ enabled:
+false }`, named imports can occur in any order.
+
+If set to `{ enabled: true, ... }`, and any of the properties `import`,
+`export`, `require`, or `cjsExports` are set to `false`, named ordering is
+disabled with respect to the following kind of expressions:
 
  - `import`:
 
-   ```ts
-   import { Readline } from "readline";
-   ```
+  ```ts
+  import { Readline } from "readline";
+  ```
 
  - `export`:
 
-   ```ts
-   export { Readline };
-   // and
-   export { Readline } from "readline";
-   ```
+  ```ts
+  export { Readline };
+  // and
+  export { Readline } from "readline";
+  ```
 
- - `require`
+ - `require`:
 
-   ```ts
-   const { Readline } = require("readline");
-   ```
+  ```ts
+  const { Readline } = require("readline");
+  ```
 
- - `cjsExports`
+ - `cjsExports`:
 
-   ```ts
-   module.exports.Readline = Readline;
-   // and
-   module.exports = { Readline };
-   ```
+  ```ts
+  module.exports.Readline = Readline;
+  // and
+  module.exports = { Readline };
+  ```
 
-The `types` option allows you to specify the order of `import`s and `export`s of `type` specifiers.
-Following values are possible:
+Further, the `named.types` option allows you to specify the order of [import identifiers with inline type qualifiers][23] (or "type-only" identifiers/names), e.g. `import { type TypeIdentifier1, normalIdentifier2 } from 'specifier';`.
 
- - `types-first`: forces `type` specifiers to occur first
- - `types-last`: forces value specifiers to occur first
- - `mixed`: sorts all specifiers in alphabetical order
+`named.types` accepts the following values:
 
-The default value is `false`.
+ - `types-first`: forces type-only identifiers to occur first
+ - `types-last`: forces type-only identifiers to occur last
+ - `mixed`: sorts all identifiers in alphabetical order
 
-Example setting:
+#### Example
 
-```ts
+Given the following settings:
+
+```jsonc
 {
-  named: true,
-  alphabetize: {
-    order: 'asc'
-  }
+  "import/order": ["error", {
+    "named": true,
+    "alphabetize": {
+      "order": "asc"
+    }
+  }]
 }
 ```
 
 This will fail the rule check:
 
 ```ts
-/* eslint import/order: ["error", {"named": true, "alphabetize": {"order": "asc"}}] */
 import { compose, apply } from 'xcompose';
 ```
 
 While this will pass:
 
 ```ts
-/* eslint import/order: ["error", {"named": true, "alphabetize": {"order": "asc"}}] */
 import { apply, compose } from 'xcompose';
 ```
 
-### `alphabetize: {order: asc|desc|ignore, orderImportKind: asc|desc|ignore, caseInsensitive: true|false}`
+### `warnOnUnassignedImports`
 
-Sort the order within each group in alphabetical manner based on **import path**:
+Valid values: `boolean` \
+Default: `false`
 
- - `order`: use `asc` to sort in ascending order, and `desc` to sort in descending order (default: `ignore`).
- - `orderImportKind`: use `asc` to sort in ascending order various import kinds, e.g. imports prefixed with `type` or `typeof`, with same import path. Use `desc` to sort in descending order (default: `ignore`).
- - `caseInsensitive`: use `true` to ignore case, and `false` to consider case (default: `false`).
+Warn when "unassigned" imports are out of order. Unassigned imports are imports
+with no corresponding identifiers (e.g. `import './my/thing.js'` or
+`require('./side-effects.js')`).
 
-Example setting:
+> \[!NOTE]
+>
+> These warnings are not fixable with `--fix` since unassigned imports might be
+> used for their
+> [side-effects][31],
+> and changing the order of such imports cannot be done safely.
 
-```ts
-alphabetize: {
-  order: 'asc', /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */
-  caseInsensitive: true /* ignore case. Options: [true, false] */
+#### Example
+
+Given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "warnOnUnassignedImports": true
+  }]
 }
 ```
 
 This will fail the rule check:
 
 ```ts
-/* eslint import/order: ["error", {"alphabetize": {"order": "asc", "caseInsensitive": true}}] */
-import React, { PureComponent } from 'react';
-import aTypes from 'prop-types';
-import { compose, apply } from 'xcompose';
-import * as classnames from 'classnames';
-import blist from 'BList';
+import fs from 'fs';
+import './styles.css';
+import path from 'path';
 ```
 
 While this will pass:
 
 ```ts
-/* eslint import/order: ["error", {"alphabetize": {"order": "asc", "caseInsensitive": true}}] */
-import blist from 'BList';
-import * as classnames from 'classnames';
-import aTypes from 'prop-types';
-import React, { PureComponent } from 'react';
-import { compose, apply } from 'xcompose';
+import fs from 'fs';
+import path from 'path';
+import './styles.css';
 ```
 
-### `warnOnUnassignedImports: true|false`
+### `sortTypesAmongThemselves`
+
+Valid values: `boolean` \
+Default: `false`
+
+> \[!NOTE]
+>
+> This setting is only meaningful when `"type"` is included in [`groups`][18].
+
+Sort [type-only imports][6] separately from normal non-type imports.
 
- - default: `false`
+When enabled, the intragroup sort order of [type-only imports][6] will mirror the intergroup ordering of normal imports as defined by [`groups`][18], [`pathGroups`][8], etc.
 
-Warns when unassigned imports are out of order.  These warning will not be fixed
-with `--fix` because unassigned imports are used for side-effects and changing the
-import of order of modules with side effects can not be done automatically in a
-way that is safe.
+#### Example
+
+Given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "alphabetize": { "order": "asc" }
+  }]
+}
+```
+
+This will fail the rule check even though it's logically ordered as we expect (builtins come before parents, parents come before siblings, siblings come before indices), the only difference is we separated type-only imports from normal imports:
+
+```ts
+import type A from "fs";
+import type B from "path";
+import type C from "../foo.js";
+import type D from "./bar.js";
+import type E from './';
+
+import a from "fs";
+import b from "path";
+import c from "../foo.js";
+import d from "./bar.js";
+import e from "./";
+```
+
+This happens because [type-only imports][6] are considered part of one global
+[`"type"` group](#how-imports-are-grouped) by default. However, if we set
+`sortTypesAmongThemselves` to `true`:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "alphabetize": { "order": "asc" },
+    "sortTypesAmongThemselves": true
+  }]
+}
+```
+
+The same example will pass.
+
+### `newlines-between-types`
+
+Valid values: `"ignore" | "always" | "always-and-inside-groups" | "never"` \
+Default: the value of [`newlines-between`][20]
+
+> \[!NOTE]
+>
+> This setting is only meaningful when [`sortTypesAmongThemselves`][7] is enabled.
+
+`newlines-between-types` is functionally identical to [`newlines-between`][20] except it only enforces or forbids new lines between _[type-only][6] import groups_, which exist only when [`sortTypesAmongThemselves`][7] is enabled.
+
+In addition, when determining if a new line is enforceable or forbidden between the type-only imports and the normal imports, `newlines-between-types` takes precedence over [`newlines-between`][20].
+
+#### Example
+
+Given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "sortTypesAmongThemselves": true,
+    "newlines-between": "always"
+  }]
+}
+```
 
 This will fail the rule check:
 
 ```ts
-/* eslint import/order: ["error", {"warnOnUnassignedImports": true}] */
-import fs from 'fs';
-import './styles.css';
-import path from 'path';
+import type A from "fs";
+import type B from "path";
+import type C from "../foo.js";
+import type D from "./bar.js";
+import type E from './';
+
+import a from "fs";
+import b from "path";
+
+import c from "../foo.js";
+
+import d from "./bar.js";
+
+import e from "./";
 ```
 
-While this will pass:
+However, if we set `newlines-between-types` to `"ignore"`:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "sortTypesAmongThemselves": true,
+    "newlines-between": "always",
+    "newlines-between-types": "ignore"
+  }]
+}
+```
+
+The same example will pass.
+
+Note the new line after `import type E from './';` but before `import a from "fs";`. This new line separates the type-only imports from the normal imports. Its existence is governed by [`newlines-between-types`][27] and _not `newlines-between`_.
+
+> \[!IMPORTANT]
+>
+> In certain situations, [`consolidateIslands: true`][25] will take precedence over `newlines-between-types: "never"`, if used, when it comes to the new line separating type-only imports from normal imports.
+
+The next example will pass even though there's a new line preceding the normal import and [`newlines-between`][20] is set to `"never"`:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "sortTypesAmongThemselves": true,
+    "newlines-between": "never",
+    "newlines-between-types": "always"
+  }]
+}
+```
 
 ```ts
-/* eslint import/order: ["error", {"warnOnUnassignedImports": true}] */
-import fs from 'fs';
-import path from 'path';
-import './styles.css';
+import type A from "fs";
+
+import type B from "path";
+
+import type C from "../foo.js";
+
+import type D from "./bar.js";
+
+import type E from './';
+
+import a from "fs";
+import b from "path";
+import c from "../foo.js";
+import d from "./bar.js";
+import e from "./";
 ```
 
-## Related
+While the following fails due to the new line between the last type import and the first normal import:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "sortTypesAmongThemselves": true,
+    "newlines-between": "always",
+    "newlines-between-types": "never"
+  }]
+}
+```
+
+```ts
+import type A from "fs";
+import type B from "path";
+import type C from "../foo.js";
+import type D from "./bar.js";
+import type E from './';
+
+import a from "fs";
+
+import b from "path";
+
+import c from "../foo.js";
+
+import d from "./bar.js";
+
+import e from "./";
+```
+
+### `consolidateIslands`
 
- - [`import/external-module-folders`] setting
+Valid values: `"inside-groups" | "never"` \
+Default: `"never"`
 
- - [`import/internal-regex`] setting
+> \[!NOTE]
+>
+> This setting is only meaningful when [`newlines-between`][20] and/or [`newlines-between-types`][27] is set to `"always-and-inside-groups"`.
 
-[`import/external-module-folders`]: ../../README.md#importexternal-module-folders
+When set to `"inside-groups"`, this ensures imports spanning multiple lines are separated from other imports with a new line while single-line imports are grouped together (and the space between them consolidated) if they belong to the same [group][18] or [`pathGroups`][8].
+
+> \[!IMPORTANT]
+>
+> When all of the following are true:
+>
+>  - `consolidateIslands` is set to `"inside-groups"`
+>  - [`newlines-between`][20] is set to `"always-and-inside-groups"`
+>  - [`newlines-between-types`][27] is set to `"never"`
+>  - [`sortTypesAmongThemselves`][7] is set to `true`
+>
+> Then [`newlines-between-types`][27] will yield to `consolidateIslands` and allow new lines to separate multi-line imports and a single new line to separate all [type-only imports][6] from all normal imports. Other than that, [`newlines-between-types: "never"`][27] functions as described.
+>
+> This configuration is useful to keep type-only imports stacked tightly
+> together at the bottom of your import block to preserve space while still
+> logically organizing normal imports for quick and pleasant reference.
+
+#### Example
+
+Given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "newlines-between": "always-and-inside-groups",
+    "consolidateIslands": "inside-groups"
+  }]
+}
+```
+
+This will fail the rule check:
+
+```ts
+var fs = require('fs');
+var path = require('path');
+var { util1, util2, util3 } = require('util');
+var async = require('async');
+var relParent1 = require('../foo');
+var {
+  relParent21,
+  relParent22,
+  relParent23,
+  relParent24,
+} = require('../');
+var relParent3 = require('../bar');
+var { sibling1,
+  sibling2, sibling3 } = require('./foo');
+var sibling2 = require('./bar');
+var sibling3 = require('./foobar');
+```
+
+While this will succeed (and is what `--fix` would yield):
+
+```ts
+var fs = require('fs');
+var path = require('path');
+var { util1, util2, util3 } = require('util');
+
+var async = require('async');
+
+var relParent1 = require('../foo');
+
+var {
+  relParent21,
+  relParent22,
+  relParent23,
+  relParent24,
+} = require('../');
+
+var relParent3 = require('../bar');
+
+var { sibling1,
+  sibling2, sibling3 } = require('./foo');
+
+var sibling2 = require('./bar');
+var sibling3 = require('./foobar');
+```
+
+Note the intragroup "islands" of grouped single-line imports, as well as multi-line imports, are surrounded by new lines. At the same time, note the typical new lines separating different groups are still maintained thanks to [`newlines-between`][20].
+
+The same holds true for the next example; when given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "alphabetize": { "order": "asc" },
+    "groups": ["external", "internal", "index", "type"],
+    "pathGroups": [
+      {
+        "pattern": "dirA/**",
+        "group": "internal",
+        "position": "after"
+      },
+      {
+        "pattern": "dirB/**",
+        "group": "internal",
+        "position": "before"
+      },
+      {
+        "pattern": "dirC/**",
+        "group": "internal"
+      }
+    ],
+    "newlines-between": "always-and-inside-groups",
+    "newlines-between-types": "never",
+    "pathGroupsExcludedImportTypes": [],
+    "sortTypesAmongThemselves": true,
+    "consolidateIslands": "inside-groups"
+  }]
+}
+```
+
+> [!IMPORTANT]
+>
+> **Pay special attention to the value of [`pathGroupsExcludedImportTypes`][9]** in this example's settings.
+> Without it, the successful example below would fail.
+> This is because the imports with specifiers starting with "dirA/", "dirB/", and "dirC/" are all [considered part of the `"external"` group](#how-imports-are-grouped), and imports in that group are excluded from [`pathGroups`][8] matching by default.
+>
+> The fix is to remove `"external"` (and, in this example, the others) from [`pathGroupsExcludedImportTypes`][9].
+
+This will fail the rule check:
+
+```ts
+import c from 'Bar';
+import d from 'bar';
+import {
+  aa,
+  bb,
+  cc,
+  dd,
+  ee,
+  ff,
+  gg
+} from 'baz';
+import {
+  hh,
+  ii,
+  jj,
+  kk,
+  ll,
+  mm,
+  nn
+} from 'fizz';
+import a from 'foo';
+import b from 'dirA/bar';
+import index from './';
+import type { AA,
+  BB, CC } from 'abc';
+import type { Z } from 'fizz';
+import type {
+  A,
+  B
+} from 'foo';
+import type { C2 } from 'dirB/Bar';
+import type {
+  D2,
+  X2,
+  Y2
+} from 'dirB/bar';
+import type { E2 } from 'dirB/baz';
+import type { C3 } from 'dirC/Bar';
+import type {
+  D3,
+  X3,
+  Y3
+} from 'dirC/bar';
+import type { E3 } from 'dirC/baz';
+import type { F3 } from 'dirC/caz';
+import type { C1 } from 'dirA/Bar';
+import type {
+  D1,
+  X1,
+  Y1
+} from 'dirA/bar';
+import type { E1 } from 'dirA/baz';
+import type { F } from './index.js';
+import type { G } from './aaa.js';
+import type { H } from './bbb';
+```
+
+While this will succeed (and is what `--fix` would yield):
+
+```ts
+import c from 'Bar';
+import d from 'bar';
+
+import {
+  aa,
+  bb,
+  cc,
+  dd,
+  ee,
+  ff,
+  gg
+} from 'baz';
+
+import {
+  hh,
+  ii,
+  jj,
+  kk,
+  ll,
+  mm,
+  nn
+} from 'fizz';
+
+import a from 'foo';
+
+import b from 'dirA/bar';
+
+import index from './';
+
+import type { AA,
+  BB, CC } from 'abc';
+
+import type { Z } from 'fizz';
+
+import type {
+  A,
+  B
+} from 'foo';
+
+import type { C2 } from 'dirB/Bar';
+
+import type {
+  D2,
+  X2,
+  Y2
+} from 'dirB/bar';
+
+import type { E2 } from 'dirB/baz';
+import type { C3 } from 'dirC/Bar';
+
+import type {
+  D3,
+  X3,
+  Y3
+} from 'dirC/bar';
+
+import type { E3 } from 'dirC/baz';
+import type { F3 } from 'dirC/caz';
+import type { C1 } from 'dirA/Bar';
+
+import type {
+  D1,
+  X1,
+  Y1
+} from 'dirA/bar';
+
+import type { E1 } from 'dirA/baz';
+import type { F } from './index.js';
+import type { G } from './aaa.js';
+import type { H } from './bbb';
+```
+
+## Related
 
-[`import/internal-regex`]: ../../README.md#importinternal-regex
+ - [`import/external-module-folders`][29]
+ - [`import/internal-regex`][28]
+ - [`import/core-modules`][11]
+
+[3]: #how-imports-are-grouped
+[4]: https://nodejs.org/api/esm.html#terminology
+[5]: #warnonunassignedimports
+[6]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export
+[7]: #sorttypesamongthemselves
+[8]: #pathgroups
+[9]: #pathgroupsexcludedimporttypes
+[10]: https://www.npmjs.com/package/is-core-module
+[11]: ../../README.md#importcore-modules
+[12]: https://www.npmjs.com/package/package-up
+[13]: #pathgroup
+[14]: https://www.npmjs.com/package/minimatch
+[16]: https://www.npmjs.com/package/minimatch#features
+[17]: https://www.npmjs.com/package/minimatch#options
+[18]: #groups
+[20]: #newlines-between
+[21]: https://eslint.org/docs/latest/rules/no-multiple-empty-lines
+[22]: https://prettier.io
+[23]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#type-modifiers-on-import-names
+[25]: #consolidateislands
+[27]: #newlines-between-types
+[28]: ../../README.md#importinternal-regex
+[29]: ../../README.md#importexternal-module-folders
+[30]: #alphabetize
+[31]: https://webpack.js.org/guides/tree-shaking#mark-the-file-as-side-effect-free
+[32]: #distinctgroup
+[33]: #named

From 8c8058cfe96c52ed3f718580e085140f51f03510 Mon Sep 17 00:00:00 2001
From: Mikhail Pertsev <mikhail.pertsev@brightpattern.com>
Date: Thu, 4 Jul 2024 10:49:15 +0200
Subject: [PATCH 746/767] [New] add `enforce-node-protocol-usage` rule and
 `import/node-version` setting

Co-authored-by: Mikhail Pertsev <mikhail.pertsev@brightpattern.com>
Co-authored-by: sevenc-nanashi <sevenc7c@sevenc7c.com>
---
 .markdownlint.json                            |   1 +
 CHANGELOG.md                                  |  14 +-
 README.md                                     |  47 ++-
 docs/rules/enforce-node-protocol-usage.md     |  81 ++++
 src/index.js                                  |   1 +
 src/rules/enforce-node-protocol-usage.js      | 147 ++++++++
 .../src/rules/enforce-node-protocol-usage.js  | 345 ++++++++++++++++++
 7 files changed, 617 insertions(+), 19 deletions(-)
 create mode 100644 docs/rules/enforce-node-protocol-usage.md
 create mode 100644 src/rules/enforce-node-protocol-usage.js
 create mode 100644 tests/src/rules/enforce-node-protocol-usage.js

diff --git a/.markdownlint.json b/.markdownlint.json
index 02a066730b..f434832d2b 100644
--- a/.markdownlint.json
+++ b/.markdownlint.json
@@ -1,5 +1,6 @@
 {
   "line-length": false,
+  "ignore_case": true,
   "no-duplicate-heading": {
     "siblings_only": true
   },
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2174fc46bf..b3a92d015c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,8 +6,11 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## [Unreleased]
 
+### Added
+- add [`enforce-node-protocol-usage`] rule and `import/node-version` setting ([#3024], thanks [@GoldStrikeArch] and [@sevenc-nanashi])
+
 ### Changed
-- [Docs] `extensions`, `order`: improve documentation ([#3106], thanks [@Xunnamius])
+- [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
 
 ## [2.31.0] - 2024-10-03
 
@@ -1106,10 +1109,12 @@ for info on changes for earlier releases.
 [`import/core-modules` setting]: ./README.md#importcore-modules
 [`import/external-module-folders` setting]: ./README.md#importexternal-module-folders
 [`internal-regex` setting]: ./README.md#importinternal-regex
+[`import/node-version` setting]: ./README.md#importnode-version
 
 [`consistent-type-specifier-style`]: ./docs/rules/consistent-type-specifier-style.md
 [`default`]: ./docs/rules/default.md
 [`dynamic-import-chunkname`]: ./docs/rules/dynamic-import-chunkname.md
+[`enforce-node-protocol-usage`]: ./docs/rules/enforce-node-protocol-usage.md
 [`export`]: ./docs/rules/export.md
 [`exports-last`]: ./docs/rules/exports-last.md
 [`extensions`]: ./docs/rules/extensions.md
@@ -1169,6 +1174,7 @@ for info on changes for earlier releases.
 [#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
 [#3033]: https://github.com/import-js/eslint-plugin-import/pull/3033
 [#3032]: https://github.com/import-js/eslint-plugin-import/pull/3032
+[#3024]: https://github.com/import-js/eslint-plugin-import/pull/3024
 [#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
 [#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
 [#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
@@ -1788,7 +1794,6 @@ for info on changes for earlier releases.
 [@bicstone]: https://github.com/bicstone
 [@Blasz]: https://github.com/Blasz
 [@bmish]: https://github.com/bmish
-[@developer-bandi]: https://github.com/developer-bandi
 [@borisyankov]: https://github.com/borisyankov
 [@bradennapier]: https://github.com/bradennapier
 [@bradzacher]: https://github.com/bradzacher
@@ -1808,6 +1813,7 @@ for info on changes for earlier releases.
 [@darkartur]: https://github.com/darkartur
 [@davidbonnet]: https://github.com/davidbonnet
 [@dbrewer5]: https://github.com/dbrewer5
+[@developer-bandi]: https://github.com/developer-bandi
 [@devinrhode2]: https://github.com/devinrhode2
 [@devongovett]: https://github.com/devongovett
 [@dmnd]: https://github.com/dmnd
@@ -1842,6 +1848,7 @@ for info on changes for earlier releases.
 [@georeith]: https://github.com/georeith
 [@giodamelio]: https://github.com/giodamelio
 [@gnprice]: https://github.com/gnprice
+[@GoldStrikeArch]: https://github.com/GoldStrikeArch
 [@golergka]: https://github.com/golergka
 [@golopot]: https://github.com/golopot
 [@GoodForOneFare]: https://github.com/GoodForOneFare
@@ -1901,9 +1908,9 @@ for info on changes for earlier releases.
 [@Librazy]: https://github.com/Librazy
 [@liby]: https://github.com/liby
 [@lilling]: https://github.com/lilling
+[@liuxingbaoyu]: https://github.com/liuxingbaoyu
 [@ljharb]: https://github.com/ljharb
 [@ljqx]: https://github.com/ljqx
-[@liuxingbaoyu]: https://github.com/liuxingbaoyu
 [@lo1tuma]: https://github.com/lo1tuma
 [@loganfsmyth]: https://github.com/loganfsmyth
 [@luczsoma]: https://github.com/luczsoma
@@ -1977,6 +1984,7 @@ for info on changes for earlier releases.
 [@Schweinepriester]: https://github.com/Schweinepriester
 [@scottnonnenberg]: https://github.com/scottnonnenberg
 [@sergei-startsev]: https://github.com/sergei-startsev
+[@sevenc-nanashi]: https://github.com/sevenc-nanashi
 [@sharmilajesupaul]: https://github.com/sharmilajesupaul
 [@sheepsteak]: https://github.com/sheepsteak
 [@silverwind]: https://github.com/silverwind
diff --git a/README.md b/README.md
index 8cc723423f..81dedf65be 100644
--- a/README.md
+++ b/README.md
@@ -51,22 +51,23 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
 
 ### Static analysis
 
-| Name                                                                   | Description                                                                          | 💼   | ⚠️ | 🚫 | 🔧 | 💡 | ❌  |
-| :--------------------------------------------------------------------- | :----------------------------------------------------------------------------------- | :--- | :- | :- | :- | :- | :- |
-| [default](docs/rules/default.md)                                       | Ensure a default export is present, given a default import.                          | ❗ ☑️ |    |    |    |    |    |
-| [named](docs/rules/named.md)                                           | Ensure named imports correspond to a named export in the remote file.                | ❗ ☑️ |    | ⌨️ |    |    |    |
-| [namespace](docs/rules/namespace.md)                                   | Ensure imported namespaces contain dereferenced properties as they are dereferenced. | ❗ ☑️ |    |    |    |    |    |
-| [no-absolute-path](docs/rules/no-absolute-path.md)                     | Forbid import of modules using absolute paths.                                       |      |    |    | 🔧 |    |    |
-| [no-cycle](docs/rules/no-cycle.md)                                     | Forbid a module from importing a module with a dependency path back to itself.       |      |    |    |    |    |    |
-| [no-dynamic-require](docs/rules/no-dynamic-require.md)                 | Forbid `require()` calls with expressions.                                           |      |    |    |    |    |    |
-| [no-internal-modules](docs/rules/no-internal-modules.md)               | Forbid importing the submodules of other modules.                                    |      |    |    |    |    |    |
-| [no-relative-packages](docs/rules/no-relative-packages.md)             | Forbid importing packages through relative paths.                                    |      |    |    | 🔧 |    |    |
-| [no-relative-parent-imports](docs/rules/no-relative-parent-imports.md) | Forbid importing modules from parent directories.                                    |      |    |    |    |    |    |
-| [no-restricted-paths](docs/rules/no-restricted-paths.md)               | Enforce which files can be imported in a given folder.                               |      |    |    |    |    |    |
-| [no-self-import](docs/rules/no-self-import.md)                         | Forbid a module from importing itself.                                               |      |    |    |    |    |    |
-| [no-unresolved](docs/rules/no-unresolved.md)                           | Ensure imports point to a file/module that can be resolved.                          | ❗ ☑️ |    |    |    |    |    |
-| [no-useless-path-segments](docs/rules/no-useless-path-segments.md)     | Forbid unnecessary path segments in import and require statements.                   |      |    |    | 🔧 |    |    |
-| [no-webpack-loader-syntax](docs/rules/no-webpack-loader-syntax.md)     | Forbid webpack loader syntax in imports.                                             |      |    |    |    |    |    |
+| Name                                                                     | Description                                                                                     | 💼   | ⚠️ | 🚫 | 🔧 | 💡 | ❌  |
+| :----------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------- | :--- | :- | :- | :- | :- | :- |
+| [default](docs/rules/default.md)                                         | Ensure a default export is present, given a default import.                                     | ❗ ☑️ |    |    |    |    |    |
+| [enforce-node-protocol-usage](docs/rules/enforce-node-protocol-usage.md) | Enforce either using, or omitting, the `node:` protocol when importing Node.js builtin modules. |      |    |    | 🔧 |    |    |
+| [named](docs/rules/named.md)                                             | Ensure named imports correspond to a named export in the remote file.                           | ❗ ☑️ |    | ⌨️ |    |    |    |
+| [namespace](docs/rules/namespace.md)                                     | Ensure imported namespaces contain dereferenced properties as they are dereferenced.            | ❗ ☑️ |    |    |    |    |    |
+| [no-absolute-path](docs/rules/no-absolute-path.md)                       | Forbid import of modules using absolute paths.                                                  |      |    |    | 🔧 |    |    |
+| [no-cycle](docs/rules/no-cycle.md)                                       | Forbid a module from importing a module with a dependency path back to itself.                  |      |    |    |    |    |    |
+| [no-dynamic-require](docs/rules/no-dynamic-require.md)                   | Forbid `require()` calls with expressions.                                                      |      |    |    |    |    |    |
+| [no-internal-modules](docs/rules/no-internal-modules.md)                 | Forbid importing the submodules of other modules.                                               |      |    |    |    |    |    |
+| [no-relative-packages](docs/rules/no-relative-packages.md)               | Forbid importing packages through relative paths.                                               |      |    |    | 🔧 |    |    |
+| [no-relative-parent-imports](docs/rules/no-relative-parent-imports.md)   | Forbid importing modules from parent directories.                                               |      |    |    |    |    |    |
+| [no-restricted-paths](docs/rules/no-restricted-paths.md)                 | Enforce which files can be imported in a given folder.                                          |      |    |    |    |    |    |
+| [no-self-import](docs/rules/no-self-import.md)                           | Forbid a module from importing itself.                                                          |      |    |    |    |    |    |
+| [no-unresolved](docs/rules/no-unresolved.md)                             | Ensure imports point to a file/module that can be resolved.                                     | ❗ ☑️ |    |    |    |    |    |
+| [no-useless-path-segments](docs/rules/no-useless-path-segments.md)       | Forbid unnecessary path segments in import and require statements.                              |      |    |    | 🔧 |    |    |
+| [no-webpack-loader-syntax](docs/rules/no-webpack-loader-syntax.md)       | Forbid webpack loader syntax in imports.                                                        |      |    |    |    |    |    |
 
 ### Style guide
 
@@ -495,6 +496,20 @@ For example, if your packages in a monorepo are all in `@scope`, you can configu
 }
 ```
 
+### `import/node-version`
+
+A string that represents the version of Node.js that you are using.
+A falsy value will imply the version of Node.js that you are running ESLint with.
+
+```jsonc
+// .eslintrc
+{
+  "settings": {
+    "import/node-version": "22.3.4",
+  },
+}
+```
+
 ## SublimeLinter-eslint
 
 SublimeLinter-eslint introduced a change to support `.eslintignore` files
diff --git a/docs/rules/enforce-node-protocol-usage.md b/docs/rules/enforce-node-protocol-usage.md
new file mode 100644
index 0000000000..8d023b4e9c
--- /dev/null
+++ b/docs/rules/enforce-node-protocol-usage.md
@@ -0,0 +1,81 @@
+# import/enforce-node-protocol-usage
+
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+<!-- end auto-generated rule header -->
+
+Enforce either using, or omitting, the `node:` protocol when importing Node.js builtin modules.
+
+## Rule Details
+
+This rule enforces that builtins node imports are using, or omitting, the `node:` protocol.
+
+Determining whether a specifier is a core module depends on the node version being used to run `eslint`.
+This version can be specified in the configuration with the [`import/node-version` setting](../../README.md#importnode-version).
+
+Reasons to prefer using the protocol include:
+
+ - the code is more explicitly and clearly referencing a Node.js built-in module
+
+Reasons to prefer omitting the protocol include:
+
+ - some tools don't support the `node:` protocol
+ - the code is more portable, because import maps and automatic polyfilling can be used
+
+## Options
+
+The rule requires a single string option which may be one of:
+
+ - `'always'` - enforces that builtins node imports are using the `node:` protocol.
+ - `'never'` - enforces that builtins node imports are not using the `node:` protocol.
+
+## Examples
+
+### `'always'`
+
+❌ Invalid
+
+```js
+import fs from 'fs';
+export { promises } from 'fs';
+// require
+const fs = require('fs/promises');
+```
+
+✅ Valid
+
+```js
+import fs from 'node:fs';
+export { promises } from 'node:fs';
+import * as test from 'node:test';
+// require
+const fs = require('node:fs/promises');
+```
+
+### `'never'`
+
+❌ Invalid
+
+```js
+import fs from 'node:fs';
+export { promises } from 'node:fs';
+// require
+const fs = require('node:fs/promises');
+```
+
+✅ Valid
+
+```js
+import fs from 'fs';
+export { promises } from 'fs';
+
+// require
+const fs = require('fs/promises');
+
+// This rule will not enforce not using `node:` protocol when the module is only available under the `node:` protocol.
+import * as test from 'node:test';
+```
+
+## When Not To Use It
+
+If you don't want to consistently enforce using, or omitting, the `node:` protocol when importing Node.js builtin modules.
diff --git a/src/index.js b/src/index.js
index 0ab82ebee8..6252620605 100644
--- a/src/index.js
+++ b/src/index.js
@@ -45,6 +45,7 @@ export const rules = {
   'dynamic-import-chunkname': require('./rules/dynamic-import-chunkname'),
   'no-import-module-exports': require('./rules/no-import-module-exports'),
   'no-empty-named-blocks': require('./rules/no-empty-named-blocks'),
+  'enforce-node-protocol-usage': require('./rules/enforce-node-protocol-usage'),
 
   // export
   'exports-last': require('./rules/exports-last'),
diff --git a/src/rules/enforce-node-protocol-usage.js b/src/rules/enforce-node-protocol-usage.js
new file mode 100644
index 0000000000..88c31fc727
--- /dev/null
+++ b/src/rules/enforce-node-protocol-usage.js
@@ -0,0 +1,147 @@
+'use strict';
+
+const isCoreModule = require('is-core-module');
+const { default: docsUrl } = require('../docsUrl');
+
+const DO_PREFER_MESSAGE_ID = 'requireNodeProtocol';
+const NEVER_PREFER_MESSAGE_ID = 'forbidNodeProtocol';
+const messages = {
+  [DO_PREFER_MESSAGE_ID]: 'Prefer `node:{{moduleName}}` over `{{moduleName}}`.',
+  [NEVER_PREFER_MESSAGE_ID]: 'Prefer `{{moduleName}}` over `node:{{moduleName}}`.',
+};
+
+function replaceStringLiteral(
+  fixer,
+  node,
+  text,
+  relativeRangeStart,
+  relativeRangeEnd,
+) {
+  const firstCharacterIndex = node.range[0] + 1;
+  const start = Number.isInteger(relativeRangeEnd)
+    ? relativeRangeStart + firstCharacterIndex
+    : firstCharacterIndex;
+  const end = Number.isInteger(relativeRangeEnd)
+    ? relativeRangeEnd + firstCharacterIndex
+    : node.range[1] - 1;
+
+  return fixer.replaceTextRange([start, end], text);
+}
+
+function isStringLiteral(node) {
+  return node.type === 'Literal' && typeof node.value === 'string';
+}
+
+function isStaticRequireWith1Param(node) {
+  return !node.optional
+    && node.callee.type === 'Identifier'
+    && node.callee.name === 'require'
+    // check for only 1 argument
+    && node.arguments.length === 1
+    && node.arguments[0]
+    && isStringLiteral(node.arguments[0]);
+}
+
+function checkAndReport(src, context) {
+  // TODO use src.quasis[0].value.raw
+  if (src.type === 'TemplateLiteral') { return; }
+  const moduleName = 'value' in src ? src.value : src.name;
+  if (typeof moduleName !== 'string') { console.log(src, moduleName); }
+  const { settings } = context;
+  const nodeVersion = settings && settings['import/node-version'];
+  if (
+    typeof nodeVersion !== 'undefined'
+    && (
+      typeof nodeVersion !== 'string'
+      || !(/^[0-9]+\.[0-9]+\.[0-9]+$/).test(nodeVersion)
+    )
+  ) {
+    throw new TypeError('`import/node-version` setting must be a string in the format "10.23.45" (a semver version, with no leading zero)');
+  }
+
+  if (context.options[0] === 'never') {
+    if (!moduleName.startsWith('node:')) { return; }
+
+    const actualModuleName = moduleName.slice(5);
+    if (!isCoreModule(actualModuleName, nodeVersion || undefined)) { return; }
+
+    context.report({
+      node: src,
+      message: messages[NEVER_PREFER_MESSAGE_ID],
+      data: { moduleName: actualModuleName },
+      /** @param {import('eslint').Rule.RuleFixer} fixer */
+      fix(fixer) {
+        return replaceStringLiteral(fixer, src, '', 0, 5);
+      },
+    });
+  } else if (context.options[0] === 'always') {
+    if (
+      moduleName.startsWith('node:')
+      || !isCoreModule(moduleName, nodeVersion || undefined)
+      || !isCoreModule(`node:${moduleName}`, nodeVersion || undefined)
+    ) {
+      return;
+    }
+
+    context.report({
+      node: src,
+      message: messages[DO_PREFER_MESSAGE_ID],
+      data: { moduleName },
+      /** @param {import('eslint').Rule.RuleFixer} fixer */
+      fix(fixer) {
+        return replaceStringLiteral(fixer, src, 'node:', 0, 0);
+      },
+    });
+  } else if (typeof context.options[0] === 'undefined') {
+    throw new Error('Missing option');
+  } else {
+    throw new Error(`Unexpected option: ${context.options[0]}`);
+  }
+}
+
+/** @type {import('eslint').Rule.RuleModule} */
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description: 'Enforce either using, or omitting, the `node:` protocol when importing Node.js builtin modules.',
+      recommended: true,
+      category: 'Static analysis',
+      url: docsUrl('enforce-node-protocol-usage'),
+    },
+    fixable: 'code',
+    schema: {
+      type: 'array',
+      minItems: 1,
+      maxItems: 1,
+      items: [
+        {
+          enum: ['always', 'never'],
+        },
+      ],
+    },
+    messages,
+  },
+  create(context) {
+    return {
+      CallExpression(node) {
+        if (!isStaticRequireWith1Param(node)) { return; }
+
+        const arg = node.arguments[0];
+
+        return checkAndReport(arg, context);
+      },
+      ExportNamedDeclaration(node) {
+        return checkAndReport(node.source, context);
+      },
+      ImportDeclaration(node) {
+        return checkAndReport(node.source, context);
+      },
+      ImportExpression(node) {
+        if (!isStringLiteral(node.source)) { return; }
+
+        return checkAndReport(node.source, context);
+      },
+    };
+  },
+};
diff --git a/tests/src/rules/enforce-node-protocol-usage.js b/tests/src/rules/enforce-node-protocol-usage.js
new file mode 100644
index 0000000000..f9bbcbad1f
--- /dev/null
+++ b/tests/src/rules/enforce-node-protocol-usage.js
@@ -0,0 +1,345 @@
+import { RuleTester } from '../rule-tester';
+import flatMap from 'array.prototype.flatmap';
+import { satisfies } from 'semver';
+
+import { test, testVersion } from '../utils';
+
+const ruleTester = new RuleTester();
+const rule = require('rules/enforce-node-protocol-usage');
+
+const preferUsingProtocol = ['always'];
+const preferNotUsingProtocol = ['never'];
+const useNewerParser = { ecmaVersion: 2021 };
+
+const actualModules = ['fs', 'fs/promises', 'buffer', 'child_process', 'timers/promises'];
+
+const settings = {
+  'import/node-version': '16.0.0', // the node: prefix is only available as of `^14.18 || >= 16`
+};
+
+const invalidTests = [].concat(
+  flatMap(actualModules, (moduleName) => [].concat(
+    {
+      code: `import x from "${moduleName}";`,
+      output: `import x from "node:${moduleName}";`,
+      options: preferUsingProtocol,
+      errors: [
+        { messageId: 'requireNodeProtocol', data: { moduleName } },
+      ],
+    },
+    {
+      code: `export {promises} from "${moduleName}";`,
+      output: `export {promises} from "node:${moduleName}";`,
+      options: preferUsingProtocol,
+      errors: [
+        { messageId: 'requireNodeProtocol', data: { moduleName } },
+      ],
+    },
+    testVersion('>= 7', () => ({
+      code: `
+        async function foo() {
+          const x = await import('${moduleName}');
+        }
+      `,
+      output: `
+        async function foo() {
+          const x = await import('node:${moduleName}');
+        }
+      `,
+      options: preferUsingProtocol,
+      parserOptions: useNewerParser,
+      errors: [
+        { messageId: 'requireNodeProtocol', data: { moduleName } },
+      ],
+    })),
+  )),
+
+  {
+    code: 'import fs from "fs/promises";',
+    output: 'import fs from "node:fs/promises";',
+    options: preferUsingProtocol,
+    errors: [
+      {
+        messageId: 'requireNodeProtocol',
+        data: { moduleName: 'fs/promises' },
+      },
+    ],
+    settings,
+  },
+  {
+    code: 'export {default} from "fs/promises";',
+    output: 'export {default} from "node:fs/promises";',
+    options: preferUsingProtocol,
+    errors: [
+      {
+        messageId: 'requireNodeProtocol',
+        data: { moduleName: 'fs/promises' },
+      },
+    ],
+    settings,
+  },
+  testVersion('>= 7', () => ({
+    code: `
+      async function foo() {
+        const fs = await import('fs/promises');
+      }
+    `,
+    output: `
+      async function foo() {
+        const fs = await import('node:fs/promises');
+      }
+    `,
+    options: preferUsingProtocol,
+    parserOptions: useNewerParser,
+    errors: [
+      {
+        messageId: 'requireNodeProtocol',
+        data: { moduleName: 'fs/promises' },
+      },
+    ],
+    settings,
+  })),
+  {
+    code: 'import {promises} from "fs";',
+    output: 'import {promises} from "node:fs";',
+    options: preferUsingProtocol,
+    errors: [
+      { messageId: 'requireNodeProtocol', data: { moduleName: 'fs' } },
+    ],
+  },
+  {
+    code: 'export {default as promises} from "fs";',
+    output: 'export {default as promises} from "node:fs";',
+    options: preferUsingProtocol,
+    errors: [
+      { messageId: 'requireNodeProtocol', data: { moduleName: 'fs' } },
+    ],
+  },
+  testVersion('>= 7', () => ({
+    code: `
+      async function foo() {
+        const fs = await import("fs/promises");
+      }
+    `,
+    output: `
+      async function foo() {
+        const fs = await import("node:fs/promises");
+      }
+    `,
+    options: preferUsingProtocol,
+    parserOptions: useNewerParser,
+    errors: [
+      {
+        messageId: 'requireNodeProtocol',
+        data: { moduleName: 'fs/promises' },
+      },
+    ],
+    settings,
+  })),
+  {
+    code: 'import "buffer";',
+    output: 'import "node:buffer";',
+    options: preferUsingProtocol,
+    errors: [
+      {
+        messageId: 'requireNodeProtocol',
+        data: { moduleName: 'buffer' },
+      },
+    ],
+  },
+  {
+    code: 'import "child_process";',
+    output: 'import "node:child_process";',
+    options: preferUsingProtocol,
+    errors: [
+      {
+        messageId: 'requireNodeProtocol',
+        data: { moduleName: 'child_process' },
+      },
+    ],
+  },
+  {
+    code: 'import "timers/promises";',
+    output: 'import "node:timers/promises";',
+    options: preferUsingProtocol,
+    errors: [
+      {
+        messageId: 'requireNodeProtocol',
+        data: { moduleName: 'timers/promises' },
+      },
+    ],
+    settings,
+  },
+  {
+    code: 'const {promises} = require("fs")',
+    output: 'const {promises} = require("node:fs")',
+    options: preferUsingProtocol,
+    errors: [
+      { messageId: 'requireNodeProtocol', data: { moduleName: 'fs' } },
+    ],
+  },
+  {
+    code: 'const fs = require("fs/promises")',
+    output: 'const fs = require("node:fs/promises")',
+    options: preferUsingProtocol,
+    errors: [
+      {
+        messageId: 'requireNodeProtocol',
+        data: { moduleName: 'fs/promises' },
+      },
+    ],
+    settings,
+  },
+);
+
+ruleTester.run('enforce-node-protocol-usage', rule, {
+  valid: [].concat(
+    test({
+      code: 'import unicorn from "unicorn";',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'import fs from "./fs";',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'import fs from "unknown-builtin-module";',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'import fs from "node:fs";',
+      options: preferUsingProtocol,
+    }),
+    testVersion('>= 7', () => ({
+      code: `
+        async function foo() {
+          const fs = await import(fs);
+        }
+      `,
+      options: preferUsingProtocol,
+      parserOptions: useNewerParser,
+    })),
+    testVersion('>= 7', () => ({
+      code: `
+        async function foo() {
+          const fs = await import(0);
+        }
+      `,
+      options: preferUsingProtocol,
+      parserOptions: useNewerParser,
+    })),
+    testVersion('>= 7', () => ({
+      code: `
+        async function foo() {
+          const fs = await import(\`fs\`);
+        }
+      `,
+      options: preferUsingProtocol,
+      parserOptions: useNewerParser,
+    })),
+    test({
+      code: 'import "punycode/";',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require("node:fs");',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require("node:fs/promises");',
+      options: preferUsingProtocol,
+      settings,
+    }),
+    test({
+      code: 'const fs = require(fs);',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = notRequire("fs");',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = foo.require("fs");',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require.resolve("fs");',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require(`fs`);',
+      options: preferUsingProtocol,
+    }),
+    testVersion('>= 7', () => ({
+      code: 'const fs = require?.("fs");',
+      parserOptions: useNewerParser,
+      options: preferUsingProtocol,
+    })),
+    test({
+      code: 'const fs = require("fs", extra);',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require();',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require(...["fs"]);',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require("unicorn");',
+      options: preferUsingProtocol,
+    }),
+    test({
+      code: 'import fs from "fs";',
+      options: preferNotUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require("fs");',
+      options: preferNotUsingProtocol,
+    }),
+    test({
+      code: 'const fs = require("fs/promises");',
+      options: preferNotUsingProtocol,
+      settings,
+    }),
+    test({
+      code: 'import "punycode/";',
+      options: preferNotUsingProtocol,
+    }),
+
+    // should not report if the module requires `node:` protocol
+    test({
+      code: 'const fs = require("node:test");',
+      options: preferNotUsingProtocol,
+      settings,
+    }),
+  ),
+
+  invalid: [].concat(
+    // Prefer using the protocol
+    // in node versions without `node:`, the rule should not report
+    satisfies('^14.18 || >= 16') ? invalidTests.map((testCase) => test({
+      ...testCase,
+      errors: testCase.errors.map(({ messageId, data, ...testCase }) => ({
+        ...testCase,
+        message: rule.meta.messages[messageId].replace(/{{moduleName}}/g, data.moduleName),
+      })),
+    })) : [],
+
+    // Prefer not using the protocol: flip the output and code
+    invalidTests.map((testCase) => test({
+      ...testCase,
+      code: testCase.output,
+      options: preferNotUsingProtocol,
+      output: testCase.code,
+      // eslint-disable-next-line no-unused-vars
+      errors: testCase.errors.map(({ messageId, data, ...testCase }) => ({
+        ...testCase,
+        message: rule.meta.messages.forbidNodeProtocol.replace(/{{moduleName}}/g, data.moduleName),
+      })),
+      settings,
+    })),
+  ),
+});

From 8c3c1bec09e3a7640998b226f19527ab98de624d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 10 Dec 2024 20:27:34 -0800
Subject: [PATCH 747/767] [resolvers/webpack] [deps] update `hasown`,
 `is-core-module`, `is-regex`

---
 resolvers/webpack/package.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 60e5c900f0..22f0e86930 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -34,10 +34,10 @@
     "debug": "^3.2.7",
     "enhanced-resolve": "^0.9.1",
     "find-root": "^1.1.0",
-    "hasown": "^2.0.0",
+    "hasown": "^2.0.2",
     "interpret": "^1.4.0",
-    "is-core-module": "^2.13.1",
-    "is-regex": "^1.1.4",
+    "is-core-module": "^2.15.1",
+    "is-regex": "^1.2.0",
     "lodash": "^4.17.21",
     "resolve": "^2.0.0-next.5",
     "semver": "^5.7.2"

From e159652f541ebcd49eafdc9202dc77ee043139da Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Tue, 10 Dec 2024 20:27:59 -0800
Subject: [PATCH 748/767] [resolvers/webpack] v0.13.10

---
 resolvers/webpack/CHANGELOG.md | 2 ++
 resolvers/webpack/package.json | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/resolvers/webpack/CHANGELOG.md b/resolvers/webpack/CHANGELOG.md
index 1d23bf6fdd..d904a60828 100644
--- a/resolvers/webpack/CHANGELOG.md
+++ b/resolvers/webpack/CHANGELOG.md
@@ -4,6 +4,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).
 
 ## Unreleased
+
+## 0.13.10 - 2024-12-10
 - [new] add cache option ([#3100], thanks [@seiyab])
 
 ## 0.13.9 - 2024-09-02
diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json
index 22f0e86930..057711e9bf 100644
--- a/resolvers/webpack/package.json
+++ b/resolvers/webpack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-import-resolver-webpack",
-  "version": "0.13.9",
+  "version": "0.13.10",
   "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",
   "main": "index.js",
   "scripts": {

From 9d1f639a3ff5acd2bd0a44dbac761f1b1f6d583b Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Fri, 8 Nov 2024 16:08:26 +1300
Subject: [PATCH 749/767] [New] add TypeScript types

---
 .github/workflows/node-pretest.yml | 13 ++++++++++++
 CHANGELOG.md                       |  2 ++
 index.d.ts                         | 33 ++++++++++++++++++++++++++++++
 package.json                       |  6 +++++-
 4 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 index.d.ts

diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml
index f8db36de57..e25b00e499 100644
--- a/.github/workflows/node-pretest.yml
+++ b/.github/workflows/node-pretest.yml
@@ -18,6 +18,19 @@ jobs:
   #         skip-ls-check: true
   #     - run: npm run pretest
 
+  types:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: ljharb/actions/node/install@main
+        name: 'npm install'
+        with:
+          skip-ls-check: true
+      # for some reason we've got to force typescript to install here
+      # even though the npm script has `typescript@latest`
+      - run: npm i --force typescript@latest
+      - run: npm run test-types
+
   posttest:
     runs-on: ubuntu-latest
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b3a92d015c..9bfb428d43 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Added
 - add [`enforce-node-protocol-usage`] rule and `import/node-version` setting ([#3024], thanks [@GoldStrikeArch] and [@sevenc-nanashi])
+- add TypeScript types ([#3097], thanks [@G-Rath])
 
 ### Changed
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
@@ -1161,6 +1162,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#3106]: https://github.com/import-js/eslint-plugin-import/pull/3106
+[#3097]: https://github.com/import-js/eslint-plugin-import/pull/3097
 [#3073]: https://github.com/import-js/eslint-plugin-import/pull/3073
 [#3072]: https://github.com/import-js/eslint-plugin-import/pull/3072
 [#3071]: https://github.com/import-js/eslint-plugin-import/pull/3071
diff --git a/index.d.ts b/index.d.ts
new file mode 100644
index 0000000000..2bef94ec2b
--- /dev/null
+++ b/index.d.ts
@@ -0,0 +1,33 @@
+import { ESLint, Linter, Rule } from 'eslint';
+
+declare const plugin: ESLint.Plugin & {
+  meta: {
+    name: string;
+    version: string;
+  };
+  configs: {
+    'recommended': Linter.LegacyConfig;
+    'errors': Linter.LegacyConfig;
+    'warnings': Linter.LegacyConfig;
+    'stage-0': Linter.LegacyConfig;
+    'react': Linter.LegacyConfig;
+    'react-native': Linter.LegacyConfig;
+    'electron': Linter.LegacyConfig;
+    'typescript': Linter.LegacyConfig;
+  };
+  flatConfigs: {
+    'recommended': Linter.FlatConfig;
+    'errors': Linter.FlatConfig;
+    'warnings': Linter.FlatConfig;
+    'stage-0': Linter.FlatConfig;
+    'react': Linter.FlatConfig;
+    'react-native': Linter.FlatConfig;
+    'electron': Linter.FlatConfig;
+    'typescript': Linter.FlatConfig;
+  };
+  rules: {
+    [key: string]: Rule.RuleModule;
+  };
+};
+
+export = plugin;
diff --git a/package.json b/package.json
index 7852506bd4..7eaf93b520 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
     "node": ">=4"
   },
   "main": "lib/index.js",
+  "types": "index.d.ts",
   "directories": {
     "test": "tests"
   },
@@ -16,7 +17,8 @@
     "docs",
     "lib",
     "config",
-    "memo-parser/{*.js,LICENSE,*.md}"
+    "memo-parser/{*.js,LICENSE,*.md}",
+    "index.d.ts"
   ],
   "scripts": {
     "prebuild": "rimraf lib",
@@ -34,6 +36,7 @@
     "test-examples": "npm run build && npm run test-example:legacy && npm run test-example:flat",
     "test-example:legacy": "cd examples/legacy && npm install && npm run lint",
     "test-example:flat": "cd examples/flat && npm install && npm run lint",
+    "test-types": "npx --package typescript@latest tsc --noEmit index.d.ts",
     "prepublishOnly": "safe-publish-latest && npm run build",
     "prepublish": "not-in-publish || npm run prepublishOnly",
     "preupdate:eslint-docs": "npm run build",
@@ -63,6 +66,7 @@
     "@angular-eslint/template-parser": "^13.5.0",
     "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped",
     "@test-scope/some-module": "file:./tests/files/symlinked-module",
+    "@types/eslint": "^8.56.12",
     "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3 || ^5.10.0",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",

From f0727a6b5a8524d35b160a9c4159844e3728e3f4 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 11 Dec 2024 11:34:33 -0800
Subject: [PATCH 750/767] [Deps] update `string.prototype.trimend`

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 7eaf93b520..f3053e1c11 100644
--- a/package.json
+++ b/package.json
@@ -130,7 +130,7 @@
     "object.groupby": "^1.0.3",
     "object.values": "^1.2.0",
     "semver": "^6.3.1",
-    "string.prototype.trimend": "^1.0.8",
+    "string.prototype.trimend": "^1.0.9",
     "tsconfig-paths": "^3.15.0"
   }
 }

From 8b2d57083b7ce895a9fbbcacea6ef3876eee7690 Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Sun, 15 Dec 2024 18:02:47 -0600
Subject: [PATCH 751/767] [utils] [fix] `unambiguous` detect modules exported
 from minified code

This change adjusts the regex pattern used to detect modules to support detection on minified code.

Fixes #3107
---
 tests/files/minified/no-newline.js               | 3 +++
 tests/files/minified/one-line-no-semi-renamed.js | 1 +
 tests/files/minified/one-line-no-semi.js         | 1 +
 tests/files/minified/one-line.js                 | 1 +
 tests/src/core/getExports.js                     | 4 ++++
 utils/CHANGELOG.md                               | 6 ++++++
 utils/unambiguous.js                             | 2 +-
 7 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 tests/files/minified/no-newline.js
 create mode 100644 tests/files/minified/one-line-no-semi-renamed.js
 create mode 100644 tests/files/minified/one-line-no-semi.js
 create mode 100644 tests/files/minified/one-line.js

diff --git a/tests/files/minified/no-newline.js b/tests/files/minified/no-newline.js
new file mode 100644
index 0000000000..261989a75c
--- /dev/null
+++ b/tests/files/minified/no-newline.js
@@ -0,0 +1,3 @@
+function y() {
+    console.log("y");
+}export {y};
diff --git a/tests/files/minified/one-line-no-semi-renamed.js b/tests/files/minified/one-line-no-semi-renamed.js
new file mode 100644
index 0000000000..601f9c7b71
--- /dev/null
+++ b/tests/files/minified/one-line-no-semi-renamed.js
@@ -0,0 +1 @@
+function a(){console.log('foo')}export{a as foo};
diff --git a/tests/files/minified/one-line-no-semi.js b/tests/files/minified/one-line-no-semi.js
new file mode 100644
index 0000000000..09a6328118
--- /dev/null
+++ b/tests/files/minified/one-line-no-semi.js
@@ -0,0 +1 @@
+function a(){return true}export{a};
diff --git a/tests/files/minified/one-line.js b/tests/files/minified/one-line.js
new file mode 100644
index 0000000000..b79898eb33
--- /dev/null
+++ b/tests/files/minified/one-line.js
@@ -0,0 +1 @@
+function a(){console.log("foo")};export{a};
diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js
index f11a261311..a02edb85c2 100644
--- a/tests/src/core/getExports.js
+++ b/tests/src/core/getExports.js
@@ -465,6 +465,10 @@ describe('ExportMap', function () {
       ['bar.js', true],
       ['deep-es7/b.js', true],
       ['common.js', false],
+      ['./minified/no-newline.js', true],
+      ['./minified/one-line-no-semi-renamed.js', true],
+      ['./minified/one-line-no-semi.js', true],
+      ['./minified/one-line.js', true],
     ];
 
     for (const [testFile, expectedRegexResult] of testFiles) {
diff --git a/utils/CHANGELOG.md b/utils/CHANGELOG.md
index bb93725125..fe7381a2d6 100644
--- a/utils/CHANGELOG.md
+++ b/utils/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ## Unreleased
 
+### Fixed
+- `unambiguous`: detect modules exported from minified code ([#3124], thanks [@michaelfaith])
+
 ### Changed
 - [refactor] `parse`: avoid using a regex here (thanks [@ljharb])
 
@@ -180,6 +183,7 @@ Yanked due to critical issue with cache key resulting from #839.
 ### Fixed
 - `unambiguous.test()` regex is now properly in multiline mode
 
+[#3124]: https://github.com/import-js/eslint-plugin-import/pull/3124
 [#3072]: https://github.com/import-js/eslint-plugin-import/pull/3072
 [#3061]: https://github.com/import-js/eslint-plugin-import/pull/3061
 [#3057]: https://github.com/import-js/eslint-plugin-import/pull/3057
@@ -230,6 +234,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@JounQin]: https://github.com/JounQin
 [@kaiyoma]: https://github.com/kaiyoma
 [@leipert]: https://github.com/leipert
+[@ljharb]: https://github.com/ljharb
 [@manuth]: https://github.com/manuth
 [@maxkomarychev]: https://github.com/maxkomarychev
 [@mgwalker]: https://github.com/mgwalker
@@ -238,6 +243,7 @@ Yanked due to critical issue with cache key resulting from #839.
 [@nicolo-ribaudo]: https://github.com/nicolo-ribaudo
 [@pmcelhaney]: https://github.com/pmcelhaney
 [@sergei-startsev]: https://github.com/sergei-startsev
+[@silverwind]: https://github.com/silverwind
 [@sompylasar]: https://github.com/sompylasar
 [@timkraut]: https://github.com/timkraut
 [@vikr01]: https://github.com/vikr01
diff --git a/utils/unambiguous.js b/utils/unambiguous.js
index 20aabd1bd4..df7b9be7a5 100644
--- a/utils/unambiguous.js
+++ b/utils/unambiguous.js
@@ -2,7 +2,7 @@
 
 exports.__esModule = true;
 
-const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))|import\(/m;
+const pattern = /(^|[;})])\s*(export|import)((\s+\w)|(\s*[{*=]))|import\(/m;
 /**
  * detect possible imports/exports without a full parse.
  *

From 1dc101b09c75b3b06fb39a84d0a8553f92203dc6 Mon Sep 17 00:00:00 2001
From: lnuvy <lnuvy.code@gmail.com>
Date: Sun, 22 Dec 2024 07:08:08 +0900
Subject: [PATCH 752/767] [Docs] add flat config guide for using
 `tseslint.config()`

---
 CHANGELOG.md |  3 +++
 README.md    | 20 ++++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9bfb428d43..37db85ba08 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Changed
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
+- [Docs] add flat config guide for using `tseslint.config()` ([#3125], thanks [@lnuvy])
 
 ## [2.31.0] - 2024-10-03
 
@@ -1161,6 +1162,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3125]: https://github.com/import-js/eslint-plugin-import/pull/3125
 [#3106]: https://github.com/import-js/eslint-plugin-import/pull/3106
 [#3097]: https://github.com/import-js/eslint-plugin-import/pull/3097
 [#3073]: https://github.com/import-js/eslint-plugin-import/pull/3073
@@ -1913,6 +1915,7 @@ for info on changes for earlier releases.
 [@liuxingbaoyu]: https://github.com/liuxingbaoyu
 [@ljharb]: https://github.com/ljharb
 [@ljqx]: https://github.com/ljqx
+[@lnuvy]: https://github.com/lnuvy
 [@lo1tuma]: https://github.com/lo1tuma
 [@loganfsmyth]: https://github.com/loganfsmyth
 [@luczsoma]: https://github.com/luczsoma
diff --git a/README.md b/README.md
index 81dedf65be..2138f59f6d 100644
--- a/README.md
+++ b/README.md
@@ -191,6 +191,26 @@ Make sure you have installed [`@typescript-eslint/parser`] and [`eslint-import-r
 [`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser
 [`eslint-import-resolver-typescript`]: https://github.com/import-js/eslint-import-resolver-typescript
 
+### Config - Flat with `config()` in `typescript-eslint`
+
+If you are using the `config` method from [`typescript-eslint`](https://github.com/typescript-eslint/typescript-eslint), ensure that the `flatConfig` is included within the `extends` array.
+
+```js
+import tseslint from 'typescript-eslint';
+import importPlugin from 'eslint-plugin-import';
+import js from '@eslint/js';
+
+export default tseslint.config(
+  js.configs.recommended,
+  // other configs...
+  {
+    files: ['**/*.{ts,tsx}'],
+    extends: [importPlugin.flatConfigs.recommended],
+    // other configs...
+  }
+);
+```
+
 ## Resolvers
 
 With the advent of module bundlers and the current state of modules and module

From aee018f961c8ec9781c305a82385e14e314ddc18 Mon Sep 17 00:00:00 2001
From: Ryan Machado <ryangst.hire@gmail.com>
Date: Thu, 19 Dec 2024 13:01:43 -0300
Subject: [PATCH 753/767] [Docs] add missing comma

---
 CHANGELOG.md | 3 +++
 README.md    | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 37db85ba08..3a57da91fb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Changed
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
 - [Docs] add flat config guide for using `tseslint.config()` ([#3125], thanks [@lnuvy])
+- [Docs] add missing comma ([#3122], thanks [@RyanGst])
 
 ## [2.31.0] - 2024-10-03
 
@@ -1163,6 +1164,7 @@ for info on changes for earlier releases.
 [`memo-parser`]: ./memo-parser/README.md
 
 [#3125]: https://github.com/import-js/eslint-plugin-import/pull/3125
+[#3122]: https://github.com/import-js/eslint-plugin-import/pull/3122
 [#3106]: https://github.com/import-js/eslint-plugin-import/pull/3106
 [#3097]: https://github.com/import-js/eslint-plugin-import/pull/3097
 [#3073]: https://github.com/import-js/eslint-plugin-import/pull/3073
@@ -1982,6 +1984,7 @@ for info on changes for earlier releases.
 [@rosswarren]: https://github.com/rosswarren
 [@rperello]: https://github.com/rperello
 [@rsolomon]: https://github.com/rsolomon
+[@RyanGst]: https://github.com/
 [@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w
 [@saschanaz]: https://github.com/saschanaz
 [@schmidsi]: https://github.com/schmidsi
diff --git a/README.md b/README.md
index 2138f59f6d..993d31399a 100644
--- a/README.md
+++ b/README.md
@@ -127,7 +127,7 @@ All rules are off by default. However, you may extend one of the preset configs,
 ```jsonc
 {
   "rules": {
-    "import/no-unresolved": ["error", { "commonjs": true, "amd": true }]
+    "import/no-unresolved": ["error", { "commonjs": true, "amd": true }],
     "import/named": "error",
     "import/namespace": "error",
     "import/default": "error",

From e5edf49ecdc745a947ef7931b5dee0ef858d6b93 Mon Sep 17 00:00:00 2001
From: michael faith <michaelfaith@users.noreply.github.com>
Date: Sun, 15 Dec 2024 09:06:33 -0600
Subject: [PATCH 754/767] [Fix] `no-unused-modules`: provide more meaningful
 error message when no eslintrc is present

This change adjusts what we're doing if an error is thrown while attempting to enumerate lintable files in the no-used-modules rule, when users are running with flat config. Now, if FileEnumerator throws due to a lack of eslintrc and the user is running with flat config, we catch the error and rethrow with a more informative message.

I also cleaned up the original aspects of the implementation that was using the proposed eslint context functions, since that proposal was walked back and the API was never introduced.

Note: This isn't an ideal state, since this rule still relies on the legacy api to understand what needs to be ignored. Remaining tethered to the legacy config system is going to need to be solved at some point.

Fixes #3079
---
 CHANGELOG.md                             |   4 +
 examples/v9/eslint.config.mjs            |  22 +++++
 examples/v9/package.json                 |  14 +++
 examples/v9/src/depth-zero.js            |   3 +
 examples/v9/src/es6/depth-one-dynamic.js |   3 +
 examples/v9/src/exports-unused.js        |   6 ++
 examples/v9/src/exports.js               |   6 ++
 examples/v9/src/imports.js               |   6 ++
 package.json                             |   4 +-
 src/core/fsWalk.js                       |  48 ---------
 src/rules/no-unused-modules.js           | 118 ++++++++++-------------
 tests/src/rules/no-unused-modules.js     |  39 ++++++++
 12 files changed, 157 insertions(+), 116 deletions(-)
 create mode 100644 examples/v9/eslint.config.mjs
 create mode 100644 examples/v9/package.json
 create mode 100644 examples/v9/src/depth-zero.js
 create mode 100644 examples/v9/src/es6/depth-one-dynamic.js
 create mode 100644 examples/v9/src/exports-unused.js
 create mode 100644 examples/v9/src/exports.js
 create mode 100644 examples/v9/src/imports.js
 delete mode 100644 src/core/fsWalk.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a57da91fb..5bcd7163ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - add [`enforce-node-protocol-usage`] rule and `import/node-version` setting ([#3024], thanks [@GoldStrikeArch] and [@sevenc-nanashi])
 - add TypeScript types ([#3097], thanks [@G-Rath])
 
+### Fixed
+- [`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks [@michaelfaith])
+
 ### Changed
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
 - [Docs] add flat config guide for using `tseslint.config()` ([#3125], thanks [@lnuvy])
@@ -1165,6 +1168,7 @@ for info on changes for earlier releases.
 
 [#3125]: https://github.com/import-js/eslint-plugin-import/pull/3125
 [#3122]: https://github.com/import-js/eslint-plugin-import/pull/3122
+[#3116]: https://github.com/import-js/eslint-plugin-import/pull/3116
 [#3106]: https://github.com/import-js/eslint-plugin-import/pull/3106
 [#3097]: https://github.com/import-js/eslint-plugin-import/pull/3097
 [#3073]: https://github.com/import-js/eslint-plugin-import/pull/3073
diff --git a/examples/v9/eslint.config.mjs b/examples/v9/eslint.config.mjs
new file mode 100644
index 0000000000..7b7534d140
--- /dev/null
+++ b/examples/v9/eslint.config.mjs
@@ -0,0 +1,22 @@
+import importPlugin from 'eslint-plugin-import';
+import js from '@eslint/js';
+
+export default [
+  js.configs.recommended,
+  importPlugin.flatConfigs.recommended,
+  {
+    files: ['**/*.{js,mjs,cjs}'],
+    languageOptions: {
+      ecmaVersion: 'latest',
+      sourceType: 'module',
+    },
+    ignores: ['eslint.config.mjs', 'node_modules/*'],
+    rules: {
+      'no-unused-vars': 'off',
+      'import/no-dynamic-require': 'warn',
+      'import/no-nodejs-modules': 'warn',
+      'import/no-unused-modules': ['warn', { unusedExports: true }],
+      'import/no-cycle': 'warn',
+    },
+  },
+];
diff --git a/examples/v9/package.json b/examples/v9/package.json
new file mode 100644
index 0000000000..4746d74005
--- /dev/null
+++ b/examples/v9/package.json
@@ -0,0 +1,14 @@
+{
+  "name": "v9",
+  "version": "1.0.0",
+  "main": "index.js",
+  "type": "module",
+  "scripts": {
+    "lint": "eslint src --report-unused-disable-directives"
+  },
+  "devDependencies": {
+    "@eslint/js": "^9.17.0",
+    "eslint": "^9.17.0",
+    "eslint-plugin-import": "file:../.."
+  }
+}
diff --git a/examples/v9/src/depth-zero.js b/examples/v9/src/depth-zero.js
new file mode 100644
index 0000000000..8cfde99795
--- /dev/null
+++ b/examples/v9/src/depth-zero.js
@@ -0,0 +1,3 @@
+import { foo } from "./es6/depth-one-dynamic";
+
+foo();
diff --git a/examples/v9/src/es6/depth-one-dynamic.js b/examples/v9/src/es6/depth-one-dynamic.js
new file mode 100644
index 0000000000..ca129fd622
--- /dev/null
+++ b/examples/v9/src/es6/depth-one-dynamic.js
@@ -0,0 +1,3 @@
+export function foo() {}
+
+export const bar = () => import("../depth-zero").then(({foo}) => foo);
diff --git a/examples/v9/src/exports-unused.js b/examples/v9/src/exports-unused.js
new file mode 100644
index 0000000000..3c44db68d0
--- /dev/null
+++ b/examples/v9/src/exports-unused.js
@@ -0,0 +1,6 @@
+export const a = 13;
+export const b = 18;
+
+const defaultExport = { a, b };
+
+export default defaultExport;
diff --git a/examples/v9/src/exports.js b/examples/v9/src/exports.js
new file mode 100644
index 0000000000..3c44db68d0
--- /dev/null
+++ b/examples/v9/src/exports.js
@@ -0,0 +1,6 @@
+export const a = 13;
+export const b = 18;
+
+const defaultExport = { a, b };
+
+export default defaultExport;
diff --git a/examples/v9/src/imports.js b/examples/v9/src/imports.js
new file mode 100644
index 0000000000..edf1336865
--- /dev/null
+++ b/examples/v9/src/imports.js
@@ -0,0 +1,6 @@
+//import c from './exports';
+import { a, b } from './exports';
+
+import path from 'path';
+import fs from 'node:fs';
+import console from 'console';
diff --git a/package.json b/package.json
index f3053e1c11..268b477ea4 100644
--- a/package.json
+++ b/package.json
@@ -33,9 +33,10 @@
     "test": "npm run tests-only",
     "test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
     "test-all": "node --require babel-register ./scripts/testAll",
-    "test-examples": "npm run build && npm run test-example:legacy && npm run test-example:flat",
+    "test-examples": "npm run build && npm run test-example:legacy && npm run test-example:flat && npm run test-example:v9",
     "test-example:legacy": "cd examples/legacy && npm install && npm run lint",
     "test-example:flat": "cd examples/flat && npm install && npm run lint",
+    "test-example:v9": "cd examples/v9 && npm install && npm run lint",
     "test-types": "npx --package typescript@latest tsc --noEmit index.d.ts",
     "prepublishOnly": "safe-publish-latest && npm run build",
     "prepublish": "not-in-publish || npm run prepublishOnly",
@@ -106,6 +107,7 @@
     "rimraf": "^2.7.1",
     "safe-publish-latest": "^2.0.0",
     "sinon": "^2.4.1",
+    "tmp": "^0.2.1",
     "typescript": "^2.8.1 || ~3.9.5 || ~4.5.2",
     "typescript-eslint-parser": "^15 || ^20 || ^22"
   },
diff --git a/src/core/fsWalk.js b/src/core/fsWalk.js
deleted file mode 100644
index fa112590f1..0000000000
--- a/src/core/fsWalk.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * This is intended to provide similar capability as the sync api from @nodelib/fs.walk, until `eslint-plugin-import`
- * is willing to modernize and update their minimum node version to at least v16.  I intentionally made the
- * shape of the API (for the part we're using) the same as @nodelib/fs.walk so that that can be swapped in
- * when the repo is ready for it.
- */
-
-import path from 'path';
-import { readdirSync } from 'fs';
-
-/** @typedef {{ name: string, path: string, dirent: import('fs').Dirent }} Entry */
-
-/**
- * Do a comprehensive walk of the provided src directory, and collect all entries.  Filter out
- * any directories or entries using the optional filter functions.
- * @param {string} root - path to the root of the folder we're walking
- * @param {{ deepFilter?: (entry: Entry) => boolean, entryFilter?: (entry: Entry) => boolean }} options
- * @param {Entry} currentEntry - entry for the current directory we're working in
- * @param {Entry[]} existingEntries - list of all entries so far
- * @returns {Entry[]} an array of directory entries
- */
-export function walkSync(root, options, currentEntry, existingEntries) {
-  // Extract the filter functions. Default to evaluating true, if no filter passed in.
-  const { deepFilter = () => true, entryFilter = () => true } = options;
-
-  let entryList = existingEntries || [];
-  const currentRelativePath = currentEntry ? currentEntry.path : '.';
-  const fullPath = currentEntry ? path.join(root, currentEntry.path) : root;
-
-  const dirents = readdirSync(fullPath, { withFileTypes: true });
-  dirents.forEach((dirent) => {
-    /** @type {Entry} */
-    const entry = {
-      name: dirent.name,
-      path: path.join(currentRelativePath, dirent.name),
-      dirent,
-    };
-
-    if (dirent.isDirectory() && deepFilter(entry)) {
-      entryList.push(entry);
-      entryList = walkSync(root, options, entry, entryList);
-    } else if (dirent.isFile() && entryFilter(entry)) {
-      entryList.push(entry);
-    }
-  });
-
-  return entryList;
-}
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index 358726299d..86302a0ea6 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -8,13 +8,12 @@ import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
 import { getFileExtensions } from 'eslint-module-utils/ignore';
 import resolve from 'eslint-module-utils/resolve';
 import visit from 'eslint-module-utils/visit';
-import { dirname, join, resolve as resolvePath } from 'path';
+import { dirname, join } from 'path';
 import readPkgUp from 'eslint-module-utils/readPkgUp';
 import values from 'object.values';
 import includes from 'array-includes';
 import flatMap from 'array.prototype.flatmap';
 
-import { walkSync } from '../core/fsWalk';
 import ExportMapBuilder from '../exportMap/builder';
 import recursivePatternCapture from '../exportMap/patternCapture';
 import docsUrl from '../docsUrl';
@@ -51,21 +50,62 @@ function requireFileEnumerator() {
 }
 
 /**
- *
+ * Given a FileEnumerator class, instantiate and load the list of files.
  * @param FileEnumerator the `FileEnumerator` class from `eslint`'s internal api
  * @param {string} src path to the src root
  * @param {string[]} extensions list of supported extensions
  * @returns {{ filename: string, ignored: boolean }[]} list of files to operate on
  */
 function listFilesUsingFileEnumerator(FileEnumerator, src, extensions) {
-  const e = new FileEnumerator({
+  // We need to know whether this is being run with flat config in order to
+  // determine how to report errors if FileEnumerator throws due to a lack of eslintrc.
+
+  const { ESLINT_USE_FLAT_CONFIG } = process.env;
+
+  // This condition is sufficient to test in v8, since the environment variable is necessary to turn on flat config
+  let isUsingFlatConfig = ESLINT_USE_FLAT_CONFIG && process.env.ESLINT_USE_FLAT_CONFIG !== 'false';
+
+  // In the case of using v9, we can check the `shouldUseFlatConfig` function
+  // If this function is present, then we assume it's v9
+  try {
+    const { shouldUseFlatConfig } = require('eslint/use-at-your-own-risk');
+    isUsingFlatConfig = shouldUseFlatConfig && ESLINT_USE_FLAT_CONFIG !== 'false';
+  } catch (_) {
+    // We don't want to throw here, since we only want to update the
+    // boolean if the function is available.
+  }
+
+  const enumerator = new FileEnumerator({
     extensions,
   });
 
-  return Array.from(
-    e.iterateFiles(src),
-    ({ filePath, ignored }) => ({ filename: filePath, ignored }),
-  );
+  try {
+    return Array.from(
+      enumerator.iterateFiles(src),
+      ({ filePath, ignored }) => ({ filename: filePath, ignored }),
+    );
+  } catch (e) {
+    // If we're using flat config, and FileEnumerator throws due to a lack of eslintrc,
+    // then we want to throw an error so that the user knows about this rule's reliance on
+    // the legacy config.
+    if (
+      isUsingFlatConfig
+      && e.message.includes('No ESLint configuration found')
+    ) {
+      throw new Error(`
+Due to the exclusion of certain internal ESLint APIs when using flat config,
+the import/no-unused-modules rule requires an .eslintrc file to know which
+files to ignore (even when using flat config).
+The .eslintrc file only needs to contain "ignorePatterns", or can be empty if
+you do not want to ignore any files.
+
+See https://github.com/import-js/eslint-plugin-import/issues/3079
+for additional context.
+`);
+    }
+    // If this isn't the case, then we'll just let the error bubble up
+    throw e;
+  }
 }
 
 /**
@@ -107,70 +147,14 @@ function listFilesWithLegacyFunctions(src, extensions) {
   }
 }
 
-/**
- * Given a source root and list of supported extensions, use fsWalk and the
- * new `eslint` `context.session` api to build the list of files we want to operate on
- * @param {string[]} srcPaths array of source paths (for flat config this should just be a singular root (e.g. cwd))
- * @param {string[]} extensions list of supported extensions
- * @param {{ isDirectoryIgnored: (path: string) => boolean, isFileIgnored: (path: string) => boolean }} session eslint context session object
- * @returns {string[]} list of files to operate on
- */
-function listFilesWithModernApi(srcPaths, extensions, session) {
-  /** @type {string[]} */
-  const files = [];
-
-  for (let i = 0; i < srcPaths.length; i++) {
-    const src = srcPaths[i];
-    // Use walkSync along with the new session api to gather the list of files
-    const entries = walkSync(src, {
-      deepFilter(entry) {
-        const fullEntryPath = resolvePath(src, entry.path);
-
-        // Include the directory if it's not marked as ignore by eslint
-        return !session.isDirectoryIgnored(fullEntryPath);
-      },
-      entryFilter(entry) {
-        const fullEntryPath = resolvePath(src, entry.path);
-
-        // Include the file if it's not marked as ignore by eslint and its extension is included in our list
-        return (
-          !session.isFileIgnored(fullEntryPath)
-          && extensions.find((extension) => entry.path.endsWith(extension))
-        );
-      },
-    });
-
-    // Filter out directories and map entries to their paths
-    files.push(
-      ...entries
-        .filter((entry) => !entry.dirent.isDirectory())
-        .map((entry) => entry.path),
-    );
-  }
-  return files;
-}
-
 /**
  * Given a src pattern and list of supported extensions, return a list of files to process
  * with this rule.
  * @param {string} src - file, directory, or glob pattern of files to act on
  * @param {string[]} extensions - list of supported file extensions
- * @param {import('eslint').Rule.RuleContext} context - the eslint context object
  * @returns {string[] | { filename: string, ignored: boolean }[]} the list of files that this rule will evaluate.
  */
-function listFilesToProcess(src, extensions, context) {
-  // If the context object has the new session functions, then prefer those
-  // Otherwise, fallback to using the deprecated `FileEnumerator` for legacy support.
-  // https://github.com/eslint/eslint/issues/18087
-  if (
-    context.session
-    && context.session.isFileIgnored
-    && context.session.isDirectoryIgnored
-  ) {
-    return listFilesWithModernApi(src, extensions, context.session);
-  }
-
-  // Fallback to og FileEnumerator
+function listFilesToProcess(src, extensions) {
   const FileEnumerator = requireFileEnumerator();
 
   // If we got the FileEnumerator, then let's go with that
@@ -295,10 +279,10 @@ const isNodeModule = (path) => (/\/(node_modules)\//).test(path);
 function resolveFiles(src, ignoreExports, context) {
   const extensions = Array.from(getFileExtensions(context.settings));
 
-  const srcFileList = listFilesToProcess(src, extensions, context);
+  const srcFileList = listFilesToProcess(src, extensions);
 
   // prepare list of ignored files
-  const ignoredFilesList = listFilesToProcess(ignoreExports, extensions, context);
+  const ignoredFilesList = listFilesToProcess(ignoreExports, extensions);
 
   // The modern api will return a list of file paths, rather than an object
   if (ignoredFilesList.length && typeof ignoredFilesList[0] === 'string') {
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index d86f406220..a15d2c2376 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -3,8 +3,12 @@ import jsxConfig from '../../../config/react';
 import typescriptConfig from '../../../config/typescript';
 
 import { RuleTester } from '../rule-tester';
+import { expect } from 'chai';
+import { execSync } from 'child_process';
 import fs from 'fs';
 import eslintPkg from 'eslint/package.json';
+import path from 'path';
+import process from 'process';
 import semver from 'semver';
 
 let FlatRuleTester;
@@ -14,6 +18,7 @@ try {
 
 // TODO: figure out why these tests fail in eslint 4 and 5
 const isESLint4TODO = semver.satisfies(eslintPkg.version, '^4 || ^5');
+const isESLint9 = semver.satisfies(eslintPkg.version, '>=9');
 
 const ruleTester = new RuleTester();
 const typescriptRuleTester = new RuleTester(typescriptConfig);
@@ -1482,3 +1487,37 @@ describe('parser ignores prefixes like BOM and hashbang', () => {
     });
   });
 });
+
+(isESLint9 ? describe : describe.skip)('with eslint 9+', () => {
+  it('provides meaningful error when eslintrc is not present', () => {
+    const tmp = require('tmp');
+
+    // Create temp directory outside of project root
+    const tempDir = tmp.dirSync({ unsafeCleanup: true });
+
+    // Copy example project to temp directory
+    fs.cpSync(path.join(process.cwd(), 'examples/v9'), tempDir.name, { recursive: true });
+
+    let errorMessage = '';
+
+    // Build the plugin
+    try {
+      execSync('npm run build');
+    } catch (_) {
+      /* ignore */
+    }
+
+    // Install the plugin and run the lint command in the temp directory
+    try {
+      execSync(`npm install -D ${process.cwd()} && npm run lint`, { cwd: tempDir.name });
+    } catch (error) {
+      errorMessage = error.stderr.toString();
+    }
+
+    // Verify that the error message is as expected
+    expect(errorMessage).to.contain('the import/no-unused-modules rule requires an .eslintrc file');
+
+    // Cleanup
+    tempDir.removeCallback();
+  }).timeout(100000);
+});

From 78731f149b5a64c3418f1b69f37392ebeac0a762 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 30 Dec 2024 16:26:47 -0800
Subject: [PATCH 755/767] [Deps] update `array.prototype.flat`,
 `array.prototype.flatmap`, `is-core-module`, `object.values`

---
 package.json | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 268b477ea4..125fc426e8 100644
--- a/package.json
+++ b/package.json
@@ -118,19 +118,19 @@
     "@rtsao/scc": "^1.1.0",
     "array-includes": "^3.1.8",
     "array.prototype.findlastindex": "^1.2.5",
-    "array.prototype.flat": "^1.3.2",
-    "array.prototype.flatmap": "^1.3.2",
+    "array.prototype.flat": "^1.3.3",
+    "array.prototype.flatmap": "^1.3.3",
     "debug": "^3.2.7",
     "doctrine": "^2.1.0",
     "eslint-import-resolver-node": "^0.3.9",
     "eslint-module-utils": "^2.12.0",
     "hasown": "^2.0.2",
-    "is-core-module": "^2.15.1",
+    "is-core-module": "^2.16.1",
     "is-glob": "^4.0.3",
     "minimatch": "^3.1.2",
     "object.fromentries": "^2.0.8",
     "object.groupby": "^1.0.3",
-    "object.values": "^1.2.0",
+    "object.values": "^1.2.1",
     "semver": "^6.3.1",
     "string.prototype.trimend": "^1.0.9",
     "tsconfig-paths": "^3.15.0"

From 74c976339a5cf603e757d596f221473023f6b113 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Mon, 30 Dec 2024 16:25:35 -0800
Subject: [PATCH 756/767] [Docs] `order`: remove mistakenly included sections
 in #3106

---
 docs/rules/order.md | 492 ++------------------------------------------
 1 file changed, 13 insertions(+), 479 deletions(-)

diff --git a/docs/rules/order.md b/docs/rules/order.md
index fcdd4fda7e..02a2b4bed7 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -106,9 +106,6 @@ This rule supports the following options (none of which are required):
  - [`alphabetize`][30]
  - [`named`][33]
  - [`warnOnUnassignedImports`][5]
- - [`sortTypesAmongThemselves`][7]
- - [`newlines-between-types`][27]
- - [`consolidateIslands`][25]
 
 ---
 
@@ -159,7 +156,7 @@ Roughly speaking, the grouping algorithm is as follows:
 
 1. If the import has no corresponding identifiers (e.g. `import './my/thing.js'`), is otherwise "unassigned," or is an unsupported use of `require()`, and [`warnOnUnassignedImports`][5] is disabled, it will be ignored entirely since the order of these imports may be important for their [side-effects][31]
 2. If the import is part of an arcane TypeScript declaration (e.g. `import log = console.log`), it will be considered **object**. However, note that external module references (e.g. `import x = require('z')`) are treated as normal `require()`s and import-exports (e.g. `export import w = y;`) are ignored entirely
-3. If the import is [type-only][6], `"type"` is in `groups`, and [`sortTypesAmongThemselves`][7] is disabled, it will be considered **type** (with additional implications if using [`pathGroups`][8] and `"type"` is in [`pathGroupsExcludedImportTypes`][9])
+3. If the import is [type-only][6], and `"type"` is in `groups`, it will be considered **type** (with additional implications if using [`pathGroups`][8] and `"type"` is in [`pathGroupsExcludedImportTypes`][9])
 4. If the import's specifier matches [`import/internal-regex`][28], it will be considered **internal**
 5. If the import's specifier is an absolute path, it will be considered **unknown**
 6. If the import's specifier has the name of a Node.js core module (using [is-core-module][10]), it will be considered **builtin**
@@ -174,18 +171,16 @@ Roughly speaking, the grouping algorithm is as follows:
 15. If the import's specifier has a name that starts with a word character, it will be considered **external**
 16. If this point is reached, the import will be ignored entirely
 
-At the end of the process, if they co-exist in the same file, all top-level `require()` statements that haven't been ignored are shifted (with respect to their order) below any ES6 `import` or similar declarations. Finally, any type-only declarations are potentially reorganized according to [`sortTypesAmongThemselves`][7].
+At the end of the process, if they co-exist in the same file, all top-level `require()` statements that haven't been ignored are shifted (with respect to their order) below any ES6 `import` or similar declarations.
 
 ### `pathGroups`
 
 Valid values: `PathGroup[]` \
 Default: `[]`
 
-Sometimes [the predefined groups][18] are not fine-grained
-enough, especially when using import aliases. `pathGroups` defines one or more
-[`PathGroup`][13]s relative to a predefined group. Imports are associated with a
-[`PathGroup`][13] based on path matching against the import specifier (using
-[minimatch][14]).
+Sometimes [the predefined groups][18] are not fine-grained enough, especially when using import aliases.
+`pathGroups` defines one or more [`PathGroup`][13]s relative to a predefined group.
+Imports are associated with a [`PathGroup`][13] based on path matching against the import specifier (using [minimatch][14]).
 
 > \[!IMPORTANT]
 >
@@ -224,9 +219,8 @@ enough, especially when using import aliases. `pathGroups` defines one or more
 Valid values: `("builtin" | "external" | "internal" | "unknown" | "parent" | "sibling" | "index" | "object" | "type")[]` \
 Default: `["builtin", "external", "object"]`
 
-By default, imports in certain [groups][18] are excluded
-from being matched against [`pathGroups`][8] to prevent overeager sorting. Use
-`pathGroupsExcludedImportTypes` to modify which groups are excluded.
+By default, imports in certain [groups][18] are excluded from being matched against [`pathGroups`][8] to prevent overeager sorting.
+Use `pathGroupsExcludedImportTypes` to modify which groups are excluded.
 
 > \[!TIP]
 >
@@ -430,13 +424,10 @@ Default: `false`
 
 Enforce ordering of names within imports and exports.
 
-If set to `true` or `{ enabled: true }`, _all_ named imports must be ordered
-according to [`alphabetize`][30]. If set to `false` or `{ enabled:
-false }`, named imports can occur in any order.
+If set to `true` or `{ enabled: true }`, _all_ named imports must be ordered according to [`alphabetize`][30].
+If set to `false` or `{ enabled: false }`, named imports can occur in any order.
 
-If set to `{ enabled: true, ... }`, and any of the properties `import`,
-`export`, `require`, or `cjsExports` are set to `false`, named ordering is
-disabled with respect to the following kind of expressions:
+If set to `{ enabled: true, ... }`, and any of the properties `import`, `export`, `require`, or `cjsExports` are set to `false`, named ordering is disabled with respect to the following kind of expressions:
 
  - `import`:
 
@@ -506,15 +497,12 @@ import { apply, compose } from 'xcompose';
 Valid values: `boolean` \
 Default: `false`
 
-Warn when "unassigned" imports are out of order. Unassigned imports are imports
-with no corresponding identifiers (e.g. `import './my/thing.js'` or
-`require('./side-effects.js')`).
+Warn when "unassigned" imports are out of order.
+Unassigned imports are imports with no corresponding identifiers (e.g. `import './my/thing.js'` or `require('./side-effects.js')`).
 
 > \[!NOTE]
 >
-> These warnings are not fixable with `--fix` since unassigned imports might be
-> used for their
-> [side-effects][31],
+> These warnings are not fixable with `--fix` since unassigned imports might be used for their [side-effects][31],
 > and changing the order of such imports cannot be done safely.
 
 #### Example
@@ -545,457 +533,6 @@ import path from 'path';
 import './styles.css';
 ```
 
-### `sortTypesAmongThemselves`
-
-Valid values: `boolean` \
-Default: `false`
-
-> \[!NOTE]
->
-> This setting is only meaningful when `"type"` is included in [`groups`][18].
-
-Sort [type-only imports][6] separately from normal non-type imports.
-
-When enabled, the intragroup sort order of [type-only imports][6] will mirror the intergroup ordering of normal imports as defined by [`groups`][18], [`pathGroups`][8], etc.
-
-#### Example
-
-Given the following settings:
-
-```jsonc
-{
-  "import/order": ["error", {
-    "groups": ["type", "builtin", "parent", "sibling", "index"],
-    "alphabetize": { "order": "asc" }
-  }]
-}
-```
-
-This will fail the rule check even though it's logically ordered as we expect (builtins come before parents, parents come before siblings, siblings come before indices), the only difference is we separated type-only imports from normal imports:
-
-```ts
-import type A from "fs";
-import type B from "path";
-import type C from "../foo.js";
-import type D from "./bar.js";
-import type E from './';
-
-import a from "fs";
-import b from "path";
-import c from "../foo.js";
-import d from "./bar.js";
-import e from "./";
-```
-
-This happens because [type-only imports][6] are considered part of one global
-[`"type"` group](#how-imports-are-grouped) by default. However, if we set
-`sortTypesAmongThemselves` to `true`:
-
-```jsonc
-{
-  "import/order": ["error", {
-    "groups": ["type", "builtin", "parent", "sibling", "index"],
-    "alphabetize": { "order": "asc" },
-    "sortTypesAmongThemselves": true
-  }]
-}
-```
-
-The same example will pass.
-
-### `newlines-between-types`
-
-Valid values: `"ignore" | "always" | "always-and-inside-groups" | "never"` \
-Default: the value of [`newlines-between`][20]
-
-> \[!NOTE]
->
-> This setting is only meaningful when [`sortTypesAmongThemselves`][7] is enabled.
-
-`newlines-between-types` is functionally identical to [`newlines-between`][20] except it only enforces or forbids new lines between _[type-only][6] import groups_, which exist only when [`sortTypesAmongThemselves`][7] is enabled.
-
-In addition, when determining if a new line is enforceable or forbidden between the type-only imports and the normal imports, `newlines-between-types` takes precedence over [`newlines-between`][20].
-
-#### Example
-
-Given the following settings:
-
-```jsonc
-{
-  "import/order": ["error", {
-    "groups": ["type", "builtin", "parent", "sibling", "index"],
-    "sortTypesAmongThemselves": true,
-    "newlines-between": "always"
-  }]
-}
-```
-
-This will fail the rule check:
-
-```ts
-import type A from "fs";
-import type B from "path";
-import type C from "../foo.js";
-import type D from "./bar.js";
-import type E from './';
-
-import a from "fs";
-import b from "path";
-
-import c from "../foo.js";
-
-import d from "./bar.js";
-
-import e from "./";
-```
-
-However, if we set `newlines-between-types` to `"ignore"`:
-
-```jsonc
-{
-  "import/order": ["error", {
-    "groups": ["type", "builtin", "parent", "sibling", "index"],
-    "sortTypesAmongThemselves": true,
-    "newlines-between": "always",
-    "newlines-between-types": "ignore"
-  }]
-}
-```
-
-The same example will pass.
-
-Note the new line after `import type E from './';` but before `import a from "fs";`. This new line separates the type-only imports from the normal imports. Its existence is governed by [`newlines-between-types`][27] and _not `newlines-between`_.
-
-> \[!IMPORTANT]
->
-> In certain situations, [`consolidateIslands: true`][25] will take precedence over `newlines-between-types: "never"`, if used, when it comes to the new line separating type-only imports from normal imports.
-
-The next example will pass even though there's a new line preceding the normal import and [`newlines-between`][20] is set to `"never"`:
-
-```jsonc
-{
-  "import/order": ["error", {
-    "groups": ["type", "builtin", "parent", "sibling", "index"],
-    "sortTypesAmongThemselves": true,
-    "newlines-between": "never",
-    "newlines-between-types": "always"
-  }]
-}
-```
-
-```ts
-import type A from "fs";
-
-import type B from "path";
-
-import type C from "../foo.js";
-
-import type D from "./bar.js";
-
-import type E from './';
-
-import a from "fs";
-import b from "path";
-import c from "../foo.js";
-import d from "./bar.js";
-import e from "./";
-```
-
-While the following fails due to the new line between the last type import and the first normal import:
-
-```jsonc
-{
-  "import/order": ["error", {
-    "groups": ["type", "builtin", "parent", "sibling", "index"],
-    "sortTypesAmongThemselves": true,
-    "newlines-between": "always",
-    "newlines-between-types": "never"
-  }]
-}
-```
-
-```ts
-import type A from "fs";
-import type B from "path";
-import type C from "../foo.js";
-import type D from "./bar.js";
-import type E from './';
-
-import a from "fs";
-
-import b from "path";
-
-import c from "../foo.js";
-
-import d from "./bar.js";
-
-import e from "./";
-```
-
-### `consolidateIslands`
-
-Valid values: `"inside-groups" | "never"` \
-Default: `"never"`
-
-> \[!NOTE]
->
-> This setting is only meaningful when [`newlines-between`][20] and/or [`newlines-between-types`][27] is set to `"always-and-inside-groups"`.
-
-When set to `"inside-groups"`, this ensures imports spanning multiple lines are separated from other imports with a new line while single-line imports are grouped together (and the space between them consolidated) if they belong to the same [group][18] or [`pathGroups`][8].
-
-> \[!IMPORTANT]
->
-> When all of the following are true:
->
->  - `consolidateIslands` is set to `"inside-groups"`
->  - [`newlines-between`][20] is set to `"always-and-inside-groups"`
->  - [`newlines-between-types`][27] is set to `"never"`
->  - [`sortTypesAmongThemselves`][7] is set to `true`
->
-> Then [`newlines-between-types`][27] will yield to `consolidateIslands` and allow new lines to separate multi-line imports and a single new line to separate all [type-only imports][6] from all normal imports. Other than that, [`newlines-between-types: "never"`][27] functions as described.
->
-> This configuration is useful to keep type-only imports stacked tightly
-> together at the bottom of your import block to preserve space while still
-> logically organizing normal imports for quick and pleasant reference.
-
-#### Example
-
-Given the following settings:
-
-```jsonc
-{
-  "import/order": ["error", {
-    "newlines-between": "always-and-inside-groups",
-    "consolidateIslands": "inside-groups"
-  }]
-}
-```
-
-This will fail the rule check:
-
-```ts
-var fs = require('fs');
-var path = require('path');
-var { util1, util2, util3 } = require('util');
-var async = require('async');
-var relParent1 = require('../foo');
-var {
-  relParent21,
-  relParent22,
-  relParent23,
-  relParent24,
-} = require('../');
-var relParent3 = require('../bar');
-var { sibling1,
-  sibling2, sibling3 } = require('./foo');
-var sibling2 = require('./bar');
-var sibling3 = require('./foobar');
-```
-
-While this will succeed (and is what `--fix` would yield):
-
-```ts
-var fs = require('fs');
-var path = require('path');
-var { util1, util2, util3 } = require('util');
-
-var async = require('async');
-
-var relParent1 = require('../foo');
-
-var {
-  relParent21,
-  relParent22,
-  relParent23,
-  relParent24,
-} = require('../');
-
-var relParent3 = require('../bar');
-
-var { sibling1,
-  sibling2, sibling3 } = require('./foo');
-
-var sibling2 = require('./bar');
-var sibling3 = require('./foobar');
-```
-
-Note the intragroup "islands" of grouped single-line imports, as well as multi-line imports, are surrounded by new lines. At the same time, note the typical new lines separating different groups are still maintained thanks to [`newlines-between`][20].
-
-The same holds true for the next example; when given the following settings:
-
-```jsonc
-{
-  "import/order": ["error", {
-    "alphabetize": { "order": "asc" },
-    "groups": ["external", "internal", "index", "type"],
-    "pathGroups": [
-      {
-        "pattern": "dirA/**",
-        "group": "internal",
-        "position": "after"
-      },
-      {
-        "pattern": "dirB/**",
-        "group": "internal",
-        "position": "before"
-      },
-      {
-        "pattern": "dirC/**",
-        "group": "internal"
-      }
-    ],
-    "newlines-between": "always-and-inside-groups",
-    "newlines-between-types": "never",
-    "pathGroupsExcludedImportTypes": [],
-    "sortTypesAmongThemselves": true,
-    "consolidateIslands": "inside-groups"
-  }]
-}
-```
-
-> [!IMPORTANT]
->
-> **Pay special attention to the value of [`pathGroupsExcludedImportTypes`][9]** in this example's settings.
-> Without it, the successful example below would fail.
-> This is because the imports with specifiers starting with "dirA/", "dirB/", and "dirC/" are all [considered part of the `"external"` group](#how-imports-are-grouped), and imports in that group are excluded from [`pathGroups`][8] matching by default.
->
-> The fix is to remove `"external"` (and, in this example, the others) from [`pathGroupsExcludedImportTypes`][9].
-
-This will fail the rule check:
-
-```ts
-import c from 'Bar';
-import d from 'bar';
-import {
-  aa,
-  bb,
-  cc,
-  dd,
-  ee,
-  ff,
-  gg
-} from 'baz';
-import {
-  hh,
-  ii,
-  jj,
-  kk,
-  ll,
-  mm,
-  nn
-} from 'fizz';
-import a from 'foo';
-import b from 'dirA/bar';
-import index from './';
-import type { AA,
-  BB, CC } from 'abc';
-import type { Z } from 'fizz';
-import type {
-  A,
-  B
-} from 'foo';
-import type { C2 } from 'dirB/Bar';
-import type {
-  D2,
-  X2,
-  Y2
-} from 'dirB/bar';
-import type { E2 } from 'dirB/baz';
-import type { C3 } from 'dirC/Bar';
-import type {
-  D3,
-  X3,
-  Y3
-} from 'dirC/bar';
-import type { E3 } from 'dirC/baz';
-import type { F3 } from 'dirC/caz';
-import type { C1 } from 'dirA/Bar';
-import type {
-  D1,
-  X1,
-  Y1
-} from 'dirA/bar';
-import type { E1 } from 'dirA/baz';
-import type { F } from './index.js';
-import type { G } from './aaa.js';
-import type { H } from './bbb';
-```
-
-While this will succeed (and is what `--fix` would yield):
-
-```ts
-import c from 'Bar';
-import d from 'bar';
-
-import {
-  aa,
-  bb,
-  cc,
-  dd,
-  ee,
-  ff,
-  gg
-} from 'baz';
-
-import {
-  hh,
-  ii,
-  jj,
-  kk,
-  ll,
-  mm,
-  nn
-} from 'fizz';
-
-import a from 'foo';
-
-import b from 'dirA/bar';
-
-import index from './';
-
-import type { AA,
-  BB, CC } from 'abc';
-
-import type { Z } from 'fizz';
-
-import type {
-  A,
-  B
-} from 'foo';
-
-import type { C2 } from 'dirB/Bar';
-
-import type {
-  D2,
-  X2,
-  Y2
-} from 'dirB/bar';
-
-import type { E2 } from 'dirB/baz';
-import type { C3 } from 'dirC/Bar';
-
-import type {
-  D3,
-  X3,
-  Y3
-} from 'dirC/bar';
-
-import type { E3 } from 'dirC/baz';
-import type { F3 } from 'dirC/caz';
-import type { C1 } from 'dirA/Bar';
-
-import type {
-  D1,
-  X1,
-  Y1
-} from 'dirA/bar';
-
-import type { E1 } from 'dirA/baz';
-import type { F } from './index.js';
-import type { G } from './aaa.js';
-import type { H } from './bbb';
-```
-
 ## Related
 
  - [`import/external-module-folders`][29]
@@ -1006,7 +543,6 @@ import type { H } from './bbb';
 [4]: https://nodejs.org/api/esm.html#terminology
 [5]: #warnonunassignedimports
 [6]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export
-[7]: #sorttypesamongthemselves
 [8]: #pathgroups
 [9]: #pathgroupsexcludedimporttypes
 [10]: https://www.npmjs.com/package/is-core-module
@@ -1021,8 +557,6 @@ import type { H } from './bbb';
 [21]: https://eslint.org/docs/latest/rules/no-multiple-empty-lines
 [22]: https://prettier.io
 [23]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#type-modifiers-on-import-names
-[25]: #consolidateislands
-[27]: #newlines-between-types
 [28]: ../../README.md#importinternal-regex
 [29]: ../../README.md#importexternal-module-folders
 [30]: #alphabetize

From fa36d4983c03f1e3a63c3cd555ea2fb34adc0a86 Mon Sep 17 00:00:00 2001
From: "Xunnamius (Romulus)" <Xunnamius@users.noreply.github.com>
Date: Mon, 18 Nov 2024 03:17:01 -0800
Subject: [PATCH 757/767] [New] `extensions`: add `pathGroupOverrides to allow
 enforcement decision overrides based on specifier

---
 CHANGELOG.md                  |   2 +
 src/rules/extensions.js       |  50 +++++++++++++-
 tests/src/rules/extensions.js | 120 ++++++++++++++++++++++++++++++++++
 3 files changed, 169 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5bcd7163ff..6aff8cda1a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Added
 - add [`enforce-node-protocol-usage`] rule and `import/node-version` setting ([#3024], thanks [@GoldStrikeArch] and [@sevenc-nanashi])
 - add TypeScript types ([#3097], thanks [@G-Rath])
+- [`extensions`]: add `pathGroupOverrides to allow enforcement decision overrides based on specifier ([#3105], thanks [@Xunnamius])
 
 ### Fixed
 - [`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks [@michaelfaith])
@@ -1170,6 +1171,7 @@ for info on changes for earlier releases.
 [#3122]: https://github.com/import-js/eslint-plugin-import/pull/3122
 [#3116]: https://github.com/import-js/eslint-plugin-import/pull/3116
 [#3106]: https://github.com/import-js/eslint-plugin-import/pull/3106
+[#3105]: https://github.com/import-js/eslint-plugin-import/pull/3105
 [#3097]: https://github.com/import-js/eslint-plugin-import/pull/3097
 [#3073]: https://github.com/import-js/eslint-plugin-import/pull/3073
 [#3072]: https://github.com/import-js/eslint-plugin-import/pull/3072
diff --git a/src/rules/extensions.js b/src/rules/extensions.js
index c2c03a2b17..2aeef64758 100644
--- a/src/rules/extensions.js
+++ b/src/rules/extensions.js
@@ -1,5 +1,6 @@
 import path from 'path';
 
+import minimatch from 'minimatch';
 import resolve from 'eslint-module-utils/resolve';
 import { isBuiltIn, isExternalModule, isScoped } from '../core/importType';
 import moduleVisitor from 'eslint-module-utils/moduleVisitor';
@@ -16,6 +17,26 @@ const properties = {
     pattern: patternProperties,
     checkTypeImports: { type: 'boolean' },
     ignorePackages: { type: 'boolean' },
+    pathGroupOverrides: {
+      type: 'array',
+      items: {
+        type: 'object',
+        properties: {
+          pattern: {
+            type: 'string',
+          },
+          patternOptions: {
+            type: 'object',
+          },
+          action: {
+            type: 'string',
+            enum: ['enforce', 'ignore'],
+          },
+        },
+        additionalProperties: false,
+        required: ['pattern', 'action'],
+      },
+    },
   },
 };
 
@@ -54,6 +75,10 @@ function buildProperties(context) {
     if (obj.checkTypeImports !== undefined) {
       result.checkTypeImports = obj.checkTypeImports;
     }
+
+    if (obj.pathGroupOverrides !== undefined) {
+      result.pathGroupOverrides = obj.pathGroupOverrides;
+    }
   });
 
   if (result.defaultConfig === 'ignorePackages') {
@@ -143,20 +168,39 @@ module.exports = {
       return false;
     }
 
+    function computeOverrideAction(pathGroupOverrides, path) {
+      for (let i = 0, l = pathGroupOverrides.length; i < l; i++) {
+        const { pattern, patternOptions, action } = pathGroupOverrides[i];
+        if (minimatch(path, pattern, patternOptions || { nocomment: true })) {
+          return action;
+        }
+      }
+    }
+
     function checkFileExtension(source, node) {
       // bail if the declaration doesn't have a source, e.g. "export { foo };", or if it's only partially typed like in an editor
       if (!source || !source.value) { return; }
 
       const importPathWithQueryString = source.value;
 
+      // If not undefined, the user decided if rules are enforced on this import
+      const overrideAction = computeOverrideAction(
+        props.pathGroupOverrides || [],
+        importPathWithQueryString,
+      );
+
+      if (overrideAction === 'ignore') {
+        return;
+      }
+
       // don't enforce anything on builtins
-      if (isBuiltIn(importPathWithQueryString, context.settings)) { return; }
+      if (!overrideAction && isBuiltIn(importPathWithQueryString, context.settings)) { return; }
 
       const importPath = importPathWithQueryString.replace(/\?(.*)$/, '');
 
       // don't enforce in root external packages as they may have names with `.js`.
       // Like `import Decimal from decimal.js`)
-      if (isExternalRootModule(importPath)) { return; }
+      if (!overrideAction && isExternalRootModule(importPath)) { return; }
 
       const resolvedPath = resolve(importPath, context);
 
@@ -174,7 +218,7 @@ module.exports = {
       if (!extension || !importPath.endsWith(`.${extension}`)) {
         // ignore type-only imports and exports
         if (!props.checkTypeImports && (node.importKind === 'type' || node.exportKind === 'type')) { return; }
-        const extensionRequired = isUseOfExtensionRequired(extension, isPackage);
+        const extensionRequired = isUseOfExtensionRequired(extension, !overrideAction && isPackage);
         const extensionForbidden = isUseOfExtensionForbidden(extension);
         if (extensionRequired && !extensionForbidden) {
           context.report({
diff --git a/tests/src/rules/extensions.js b/tests/src/rules/extensions.js
index 883dfab657..8843713e34 100644
--- a/tests/src/rules/extensions.js
+++ b/tests/src/rules/extensions.js
@@ -736,6 +736,86 @@ describe('TypeScript', () => {
             ],
             parser,
           }),
+
+          // pathGroupOverrides: no patterns match good bespoke specifiers
+          test({
+            code: `
+              import { ErrorMessage as UpstreamErrorMessage } from '@black-flag/core/util';
+
+              import { $instances } from 'rootverse+debug:src.ts';
+              import { $exists } from 'rootverse+bfe:src/symbols.ts';
+
+              import type { Entries } from 'type-fest';
+            `,
+            parser,
+            options: [
+              'always',
+              {
+                ignorePackages: true,
+                checkTypeImports: true,
+                pathGroupOverrides: [
+                  {
+                    pattern: 'multiverse{*,*/**}',
+                    action: 'enforce',
+                  },
+                ],
+              },
+            ],
+          }),
+          // pathGroupOverrides: an enforce pattern matches good bespoke specifiers
+          test({
+            code: `
+              import { ErrorMessage as UpstreamErrorMessage } from '@black-flag/core/util';
+
+              import { $instances } from 'rootverse+debug:src.ts';
+              import { $exists } from 'rootverse+bfe:src/symbols.ts';
+
+              import type { Entries } from 'type-fest';
+            `,
+            parser,
+            options: [
+              'always',
+              {
+                ignorePackages: true,
+                checkTypeImports: true,
+                pathGroupOverrides: [
+                  {
+                    pattern: 'rootverse{*,*/**}',
+                    action: 'enforce',
+                  },
+                ],
+              },
+            ],
+          }),
+          // pathGroupOverrides: an ignore pattern matches bad bespoke specifiers
+          test({
+            code: `
+              import { ErrorMessage as UpstreamErrorMessage } from '@black-flag/core/util';
+
+              import { $instances } from 'rootverse+debug:src';
+              import { $exists } from 'rootverse+bfe:src/symbols';
+
+              import type { Entries } from 'type-fest';
+            `,
+            parser,
+            options: [
+              'always',
+              {
+                ignorePackages: true,
+                checkTypeImports: true,
+                pathGroupOverrides: [
+                  {
+                    pattern: 'multiverse{*,*/**}',
+                    action: 'enforce',
+                  },
+                  {
+                    pattern: 'rootverse{*,*/**}',
+                    action: 'ignore',
+                  },
+                ],
+              },
+            ],
+          }),
         ],
         invalid: [
           test({
@@ -756,6 +836,46 @@ describe('TypeScript', () => {
             ],
             parser,
           }),
+
+          // pathGroupOverrides: an enforce pattern matches bad bespoke specifiers
+          test({
+            code: `
+              import { ErrorMessage as UpstreamErrorMessage } from '@black-flag/core/util';
+
+              import { $instances } from 'rootverse+debug:src';
+              import { $exists } from 'rootverse+bfe:src/symbols';
+
+              import type { Entries } from 'type-fest';
+            `,
+            parser,
+            options: [
+              'always',
+              {
+                ignorePackages: true,
+                checkTypeImports: true,
+                pathGroupOverrides: [
+                  {
+                    pattern: 'rootverse{*,*/**}',
+                    action: 'enforce',
+                  },
+                  {
+                    pattern: 'universe{*,*/**}',
+                    action: 'ignore',
+                  },
+                ],
+              },
+            ],
+            errors: [
+              {
+                message: 'Missing file extension for "rootverse+debug:src"',
+                line: 4,
+              },
+              {
+                message: 'Missing file extension for "rootverse+bfe:src/symbols"',
+                line: 5,
+              },
+            ],
+          }),
         ],
       });
     });

From 341178de7d0ca76e6fc35550737509b8da95d44e Mon Sep 17 00:00:00 2001
From: D <intellix@users.noreply.github.com>
Date: Wed, 8 Jan 2025 18:41:53 +0000
Subject: [PATCH 758/767] [readme] Update flatConfig example to include
 typescript config

---
 CHANGELOG.md | 3 +++
 README.md    | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6aff8cda1a..80b1f632a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
 - [Docs] add flat config guide for using `tseslint.config()` ([#3125], thanks [@lnuvy])
 - [Docs] add missing comma ([#3122], thanks [@RyanGst])
+- [readme] Update flatConfig example to include typescript config ([#3138], thanks [@intellix])
 
 ## [2.31.0] - 2024-10-03
 
@@ -1167,6 +1168,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3138]: https://github.com/import-js/eslint-plugin-import/pull/3138
 [#3125]: https://github.com/import-js/eslint-plugin-import/pull/3125
 [#3122]: https://github.com/import-js/eslint-plugin-import/pull/3122
 [#3116]: https://github.com/import-js/eslint-plugin-import/pull/3116
@@ -1873,6 +1875,7 @@ for info on changes for earlier releases.
 [@hulkish]: https://github.com/hulkish
 [@hyperupcall]: https://github.com/hyperupcall
 [@Hypnosphi]: https://github.com/Hypnosphi
+[@intellix]: https://github.com/intellix
 [@isiahmeadows]: https://github.com/isiahmeadows
 [@IvanGoncharov]: https://github.com/IvanGoncharov
 [@ivo-stefchev]: https://github.com/ivo-stefchev
diff --git a/README.md b/README.md
index 993d31399a..885f34873c 100644
--- a/README.md
+++ b/README.md
@@ -205,7 +205,7 @@ export default tseslint.config(
   // other configs...
   {
     files: ['**/*.{ts,tsx}'],
-    extends: [importPlugin.flatConfigs.recommended],
+    extends: [importPlugin.flatConfigs.recommended, importPlugin.flatConfigs.typescript],
     // other configs...
   }
 );

From fd1ae63492a554ded6c5cc7fc262034804819e5e Mon Sep 17 00:00:00 2001
From: "Xunnamius (Romulus)" <Xunnamius@users.noreply.github.com>
Date: Sun, 22 Dec 2024 17:56:27 -0800
Subject: [PATCH 759/767] [New] `order`: add `sortTypesGroup` option to allow
 intragroup sorting of type-only imports

Closes #2912
Closes #2347
Closes #2441
Subsumes #2615
---
 CHANGELOG.md             |   2 +
 docs/rules/order.md      |  64 +++++++++++++-
 src/rules/order.js       |  33 +++++--
 tests/src/rules/order.js | 182 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 274 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 80b1f632a1..9d60bc3110 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - add [`enforce-node-protocol-usage`] rule and `import/node-version` setting ([#3024], thanks [@GoldStrikeArch] and [@sevenc-nanashi])
 - add TypeScript types ([#3097], thanks [@G-Rath])
 - [`extensions`]: add `pathGroupOverrides to allow enforcement decision overrides based on specifier ([#3105], thanks [@Xunnamius])
+- [`order`]: add `sortTypesGroup` option to allow intragroup sorting of type-only imports ([#3104], thanks [@Xunnamius])
 
 ### Fixed
 - [`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks [@michaelfaith])
@@ -1174,6 +1175,7 @@ for info on changes for earlier releases.
 [#3116]: https://github.com/import-js/eslint-plugin-import/pull/3116
 [#3106]: https://github.com/import-js/eslint-plugin-import/pull/3106
 [#3105]: https://github.com/import-js/eslint-plugin-import/pull/3105
+[#3104]: https://github.com/import-js/eslint-plugin-import/pull/3104
 [#3097]: https://github.com/import-js/eslint-plugin-import/pull/3097
 [#3073]: https://github.com/import-js/eslint-plugin-import/pull/3073
 [#3072]: https://github.com/import-js/eslint-plugin-import/pull/3072
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 02a2b4bed7..996df915c2 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -106,6 +106,7 @@ This rule supports the following options (none of which are required):
  - [`alphabetize`][30]
  - [`named`][33]
  - [`warnOnUnassignedImports`][5]
+ - [`sortTypesGroup`][7]
 
 ---
 
@@ -156,7 +157,7 @@ Roughly speaking, the grouping algorithm is as follows:
 
 1. If the import has no corresponding identifiers (e.g. `import './my/thing.js'`), is otherwise "unassigned," or is an unsupported use of `require()`, and [`warnOnUnassignedImports`][5] is disabled, it will be ignored entirely since the order of these imports may be important for their [side-effects][31]
 2. If the import is part of an arcane TypeScript declaration (e.g. `import log = console.log`), it will be considered **object**. However, note that external module references (e.g. `import x = require('z')`) are treated as normal `require()`s and import-exports (e.g. `export import w = y;`) are ignored entirely
-3. If the import is [type-only][6], and `"type"` is in `groups`, it will be considered **type** (with additional implications if using [`pathGroups`][8] and `"type"` is in [`pathGroupsExcludedImportTypes`][9])
+3. If the import is [type-only][6], `"type"` is in `groups`, and [`sortTypesGroup`][7] is disabled, it will be considered **type** (with additional implications if using [`pathGroups`][8] and `"type"` is in [`pathGroupsExcludedImportTypes`][9])
 4. If the import's specifier matches [`import/internal-regex`][28], it will be considered **internal**
 5. If the import's specifier is an absolute path, it will be considered **unknown**
 6. If the import's specifier has the name of a Node.js core module (using [is-core-module][10]), it will be considered **builtin**
@@ -171,7 +172,7 @@ Roughly speaking, the grouping algorithm is as follows:
 15. If the import's specifier has a name that starts with a word character, it will be considered **external**
 16. If this point is reached, the import will be ignored entirely
 
-At the end of the process, if they co-exist in the same file, all top-level `require()` statements that haven't been ignored are shifted (with respect to their order) below any ES6 `import` or similar declarations.
+At the end of the process, if they co-exist in the same file, all top-level `require()` statements that haven't been ignored are shifted (with respect to their order) below any ES6 `import` or similar declarations. Finally, any type-only declarations are potentially reorganized according to [`sortTypesGroup`][7].
 
 ### `pathGroups`
 
@@ -533,6 +534,64 @@ import path from 'path';
 import './styles.css';
 ```
 
+### `sortTypesGroup`
+
+Valid values: `boolean` \
+Default: `false`
+
+> \[!NOTE]
+>
+> This setting is only meaningful when `"type"` is included in [`groups`][18].
+
+Sort [type-only imports][6] separately from normal non-type imports.
+
+When enabled, the intragroup sort order of [type-only imports][6] will mirror the intergroup ordering of normal imports as defined by [`groups`][18], [`pathGroups`][8], etc.
+
+#### Example
+
+Given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "alphabetize": { "order": "asc" }
+  }]
+}
+```
+
+This will fail the rule check even though it's logically ordered as we expect (builtins come before parents, parents come before siblings, siblings come before indices), the only difference is we separated type-only imports from normal imports:
+
+```ts
+import type A from "fs";
+import type B from "path";
+import type C from "../foo.js";
+import type D from "./bar.js";
+import type E from './';
+
+import a from "fs";
+import b from "path";
+import c from "../foo.js";
+import d from "./bar.js";
+import e from "./";
+```
+
+This happens because [type-only imports][6] are considered part of one global
+[`"type"` group](#how-imports-are-grouped) by default. However, if we set
+`sortTypesGroup` to `true`:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "alphabetize": { "order": "asc" },
+    "sortTypesGroup": true
+  }]
+}
+```
+
+The same example will pass.
+
 ## Related
 
  - [`import/external-module-folders`][29]
@@ -543,6 +602,7 @@ import './styles.css';
 [4]: https://nodejs.org/api/esm.html#terminology
 [5]: #warnonunassignedimports
 [6]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export
+[7]: #sorttypesgroup
 [8]: #pathgroups
 [9]: #pathgroupsexcludedimporttypes
 [10]: https://www.npmjs.com/package/is-core-module
diff --git a/src/rules/order.js b/src/rules/order.js
index d6f25ddd33..ead2fdff97 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -513,22 +513,34 @@ function computePathRank(ranks, pathGroups, path, maxPosition) {
   }
 }
 
-function computeRank(context, ranks, importEntry, excludedImportTypes) {
+function computeRank(context, ranks, importEntry, excludedImportTypes, isSortingTypesGroup) {
   let impType;
   let rank;
+
+  const isTypeGroupInGroups = ranks.omittedTypes.indexOf('type') === -1;
+  const isTypeOnlyImport = importEntry.node.importKind === 'type';
+  const isExcludedFromPathRank = isTypeOnlyImport && isTypeGroupInGroups && excludedImportTypes.has('type');
+
   if (importEntry.type === 'import:object') {
     impType = 'object';
-  } else if (importEntry.node.importKind === 'type' && ranks.omittedTypes.indexOf('type') === -1) {
+  } else if (isTypeOnlyImport && isTypeGroupInGroups && !isSortingTypesGroup) {
     impType = 'type';
   } else {
     impType = importType(importEntry.value, context);
   }
-  if (!excludedImportTypes.has(impType)) {
+
+  if (!excludedImportTypes.has(impType) && !isExcludedFromPathRank) {
     rank = computePathRank(ranks.groups, ranks.pathGroups, importEntry.value, ranks.maxPosition);
   }
+
   if (typeof rank === 'undefined') {
     rank = ranks.groups[impType];
   }
+
+  if (isTypeOnlyImport && isSortingTypesGroup) {
+    rank = ranks.groups.type + rank / 10;
+  }
+
   if (importEntry.type !== 'import' && !importEntry.type.startsWith('import:')) {
     rank += 100;
   }
@@ -536,8 +548,8 @@ function computeRank(context, ranks, importEntry, excludedImportTypes) {
   return rank;
 }
 
-function registerNode(context, importEntry, ranks, imported, excludedImportTypes) {
-  const rank = computeRank(context, ranks, importEntry, excludedImportTypes);
+function registerNode(context, importEntry, ranks, imported, excludedImportTypes, isSortingTypesGroup) {
+  const rank = computeRank(context, ranks, importEntry, excludedImportTypes, isSortingTypesGroup);
   if (rank !== -1) {
     imported.push({ ...importEntry, rank });
   }
@@ -781,6 +793,10 @@ module.exports = {
               'never',
             ],
           },
+          sortTypesGroup: {
+            type: 'boolean',
+            default: false,
+          },
           named: {
             default: false,
             oneOf: [{
@@ -837,6 +853,7 @@ module.exports = {
     const options = context.options[0] || {};
     const newlinesBetweenImports = options['newlines-between'] || 'ignore';
     const pathGroupsExcludedImportTypes = new Set(options.pathGroupsExcludedImportTypes || ['builtin', 'external', 'object']);
+    const sortTypesGroup = options.sortTypesGroup;
 
     const named = {
       types: 'mixed',
@@ -879,6 +896,9 @@ module.exports = {
     const importMap = new Map();
     const exportMap = new Map();
 
+    const isTypeGroupInGroups = ranks.omittedTypes.indexOf('type') === -1;
+    const isSortingTypesGroup = isTypeGroupInGroups && sortTypesGroup;
+
     function getBlockImports(node) {
       if (!importMap.has(node)) {
         importMap.set(node, []);
@@ -932,6 +952,7 @@ module.exports = {
             ranks,
             getBlockImports(node.parent),
             pathGroupsExcludedImportTypes,
+            isSortingTypesGroup,
           );
 
           if (named.import) {
@@ -983,6 +1004,7 @@ module.exports = {
           ranks,
           getBlockImports(node.parent),
           pathGroupsExcludedImportTypes,
+          isSortingTypesGroup,
         );
       },
       CallExpression(node) {
@@ -1005,6 +1027,7 @@ module.exports = {
           ranks,
           getBlockImports(block),
           pathGroupsExcludedImportTypes,
+          isSortingTypesGroup,
         );
       },
       ...named.require && {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index ea62cec71d..6da42474c3 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -3285,6 +3285,188 @@ context('TypeScript', function () {
               }],
             }),
           ] : [],
+          // Option sortTypesGroup: false (default)
+          test({
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+
+              import type { C } from 'dirA/Bar';
+              import b from 'dirA/bar';
+              import type { D } from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA } from 'abc';
+              import type { A } from 'foo';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                pathGroupsExcludedImportTypes: [],
+              },
+            ],
+          }),
+          test({
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+
+              import type { C } from 'dirA/Bar';
+              import b from 'dirA/bar';
+              import type { D } from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA } from 'abc';
+              import type { A } from 'foo';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: false,
+              },
+            ],
+          }),
+          // Option sortTypesGroup: true and 'type' in pathGroupsExcludedImportTypes
+          test({
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA } from 'abc';
+              import type { C } from 'dirA/Bar';
+              import type { D } from 'dirA/bar';
+              import type { A } from 'foo';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                pathGroupsExcludedImportTypes: ['type'],
+                sortTypesGroup: true,
+              },
+            ],
+          }),
+          // Option sortTypesGroup: true and 'type' omitted from groups
+          test({
+            code: `
+              import c from 'Bar';
+              import type { AA } from 'abc';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import type { C } from 'dirA/Bar';
+              import b from 'dirA/bar';
+              import type { D } from 'dirA/bar';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                pathGroupsExcludedImportTypes: [],
+                // Becomes a no-op without "type" in groups
+                sortTypesGroup: true,
+              },
+            ],
+          }),
+          test({
+            code: `
+              import c from 'Bar';
+              import type { AA } from 'abc';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import type { C } from 'dirA/Bar';
+              import b from 'dirA/bar';
+              import type { D } from 'dirA/bar';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                pathGroupsExcludedImportTypes: [],
+              },
+            ],
+          }),
+          // Option: sortTypesGroup: true puts type imports in the same order as regular imports (from issue #2441, PR #2615)
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                alphabetize: {
+                  order: 'asc',
+                  caseInsensitive: true,
+                },
+                sortTypesGroup: true,
+              },
+            ],
+          }),
         ),
         invalid: [].concat(
           // Option alphabetize: {order: 'asc'}

From 668d493dbb456415c3aa12bcbde7917d475393c5 Mon Sep 17 00:00:00 2001
From: Nisharg Shah <nishargshah3101@gmail.com>
Date: Fri, 24 Jan 2025 18:43:21 +0530
Subject: [PATCH 760/767] [Fix] configs: added missing name attribute for
 eslint config inspector

---
 CHANGELOG.md | 3 +++
 src/index.js | 8 ++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d60bc3110..1cb9b56276 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 
 ### Fixed
 - [`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks [@michaelfaith])
+- configs: added missing name attribute for eslint config inspector ([#3151], thanks [@NishargShah])
 
 ### Changed
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
@@ -1169,6 +1170,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3151]: https://github.com/import-js/eslint-plugin-import/pull/3151
 [#3138]: https://github.com/import-js/eslint-plugin-import/pull/3138
 [#3125]: https://github.com/import-js/eslint-plugin-import/pull/3125
 [#3122]: https://github.com/import-js/eslint-plugin-import/pull/3122
@@ -1965,6 +1967,7 @@ for info on changes for earlier releases.
 [@Nfinished]: https://github.com/Nfinished
 [@nickofthyme]: https://github.com/nickofthyme
 [@nicolashenry]: https://github.com/nicolashenry
+[@NishargShah]: https://github.com/NishargShah
 [@noelebrun]: https://github.com/noelebrun
 [@ntdb]: https://github.com/ntdb
 [@nwalters512]: https://github.com/nwalters512
diff --git a/src/index.js b/src/index.js
index 6252620605..6cd7bffe2f 100644
--- a/src/index.js
+++ b/src/index.js
@@ -96,8 +96,8 @@ export const flatConfigs = {
   warnings: createFlatConfig(require('../config/flat/warnings'), 'warnings'),
 
   // useful stuff for folks using various environments
-  react: require('../config/flat/react'),
-  'react-native': configs['react-native'],
-  electron: configs.electron,
-  typescript: configs.typescript,
+  react: createFlatConfig(require('../config/flat/react'), 'react'),
+  'react-native': createFlatConfig(configs['react-native'], 'react-native'),
+  electron: createFlatConfig(configs.electron, 'electron'),
+  typescript: createFlatConfig(configs.typescript, 'typescript'),
 };

From e1e55384e53702b670cf9eea4adfaf004244b72b Mon Sep 17 00:00:00 2001
From: "Xunnamius (Romulus)" <Xunnamius@users.noreply.github.com>
Date: Sun, 22 Dec 2024 17:56:27 -0800
Subject: [PATCH 761/767] [New] `order`: add `newlines-between-types` option to
 control intragroup sorting of type-only imports

Closes #2912
Closes #2347
Closes #2441
Subsumes #2615
---
 CHANGELOG.md             |   2 +
 docs/rules/order.md      | 131 +++++++++++++
 src/rules/order.js       | 120 ++++++++----
 tests/src/rules/order.js | 383 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 603 insertions(+), 33 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1cb9b56276..a2a436a38a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - add TypeScript types ([#3097], thanks [@G-Rath])
 - [`extensions`]: add `pathGroupOverrides to allow enforcement decision overrides based on specifier ([#3105], thanks [@Xunnamius])
 - [`order`]: add `sortTypesGroup` option to allow intragroup sorting of type-only imports ([#3104], thanks [@Xunnamius])
+- [`order`]: add `newlines-between-types` option to control intragroup sorting of type-only imports ([#3127], thanks [@Xunnamius])
 
 ### Fixed
 - [`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks [@michaelfaith])
@@ -1172,6 +1173,7 @@ for info on changes for earlier releases.
 
 [#3151]: https://github.com/import-js/eslint-plugin-import/pull/3151
 [#3138]: https://github.com/import-js/eslint-plugin-import/pull/3138
+[#3127]: https://github.com/import-js/eslint-plugin-import/pull/3127
 [#3125]: https://github.com/import-js/eslint-plugin-import/pull/3125
 [#3122]: https://github.com/import-js/eslint-plugin-import/pull/3122
 [#3116]: https://github.com/import-js/eslint-plugin-import/pull/3116
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 996df915c2..3dee4b6de1 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -107,6 +107,7 @@ This rule supports the following options (none of which are required):
  - [`named`][33]
  - [`warnOnUnassignedImports`][5]
  - [`sortTypesGroup`][7]
+ - [`newlines-between-types`][27]
 
 ---
 
@@ -592,6 +593,135 @@ This happens because [type-only imports][6] are considered part of one global
 
 The same example will pass.
 
+### `newlines-between-types`
+
+Valid values: `"ignore" | "always" | "always-and-inside-groups" | "never"` \
+Default: the value of [`newlines-between`][20]
+
+> \[!NOTE]
+>
+> This setting is only meaningful when [`sortTypesGroup`][7] is enabled.
+
+`newlines-between-types` is functionally identical to [`newlines-between`][20] except it only enforces or forbids new lines between _[type-only][6] import groups_, which exist only when [`sortTypesGroup`][7] is enabled.
+
+In addition, when determining if a new line is enforceable or forbidden between the type-only imports and the normal imports, `newlines-between-types` takes precedence over [`newlines-between`][20].
+
+#### Example
+
+Given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "sortTypesGroup": true,
+    "newlines-between": "always"
+  }]
+}
+```
+
+This will fail the rule check:
+
+```ts
+import type A from "fs";
+import type B from "path";
+import type C from "../foo.js";
+import type D from "./bar.js";
+import type E from './';
+
+import a from "fs";
+import b from "path";
+
+import c from "../foo.js";
+
+import d from "./bar.js";
+
+import e from "./";
+```
+
+However, if we set `newlines-between-types` to `"ignore"`:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "sortTypesGroup": true,
+    "newlines-between": "always",
+    "newlines-between-types": "ignore"
+  }]
+}
+```
+
+The same example will pass.
+
+Note the new line after `import type E from './';` but before `import a from "fs";`. This new line separates the type-only imports from the normal imports. Its existence is governed by [`newlines-between-types`][27] and _not `newlines-between`_.
+
+> \[!IMPORTANT]
+>
+> In certain situations, `consolidateIslands: true` will take precedence over `newlines-between-types: "never"`, if used, when it comes to the new line separating type-only imports from normal imports.
+
+The next example will pass even though there's a new line preceding the normal import and [`newlines-between`][20] is set to `"never"`:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "sortTypesGroup": true,
+    "newlines-between": "never",
+    "newlines-between-types": "always"
+  }]
+}
+```
+
+```ts
+import type A from "fs";
+
+import type B from "path";
+
+import type C from "../foo.js";
+
+import type D from "./bar.js";
+
+import type E from './';
+
+import a from "fs";
+import b from "path";
+import c from "../foo.js";
+import d from "./bar.js";
+import e from "./";
+```
+
+While the following fails due to the new line between the last type import and the first normal import:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "groups": ["type", "builtin", "parent", "sibling", "index"],
+    "sortTypesGroup": true,
+    "newlines-between": "always",
+    "newlines-between-types": "never"
+  }]
+}
+```
+
+```ts
+import type A from "fs";
+import type B from "path";
+import type C from "../foo.js";
+import type D from "./bar.js";
+import type E from './';
+
+import a from "fs";
+
+import b from "path";
+
+import c from "../foo.js";
+
+import d from "./bar.js";
+
+import e from "./";
+```
+
 ## Related
 
  - [`import/external-module-folders`][29]
@@ -617,6 +747,7 @@ The same example will pass.
 [21]: https://eslint.org/docs/latest/rules/no-multiple-empty-lines
 [22]: https://prettier.io
 [23]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#type-modifiers-on-import-names
+[27]: #newlines-between-types
 [28]: ../../README.md#importinternal-regex
 [29]: ../../README.md#importexternal-module-folders
 [30]: #alphabetize
diff --git a/src/rules/order.js b/src/rules/order.js
index ead2fdff97..cb77c15809 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -416,7 +416,7 @@ const compareString = (a, b) => {
 };
 
 /** Some parsers (languages without types) don't provide ImportKind */
-const DEAFULT_IMPORT_KIND = 'value';
+const DEFAULT_IMPORT_KIND = 'value';
 const getNormalizedValue = (node, toLowerCase) => {
   const value = node.value;
   return toLowerCase ? String(value).toLowerCase() : value;
@@ -462,8 +462,8 @@ function getSorter(alphabetizeOptions) {
     // In case the paths are equal (result === 0), sort them by importKind
     if (!result && multiplierImportKind) {
       result = multiplierImportKind * compareString(
-        nodeA.node.importKind || DEAFULT_IMPORT_KIND,
-        nodeB.node.importKind || DEAFULT_IMPORT_KIND,
+        nodeA.node.importKind || DEFAULT_IMPORT_KIND,
+        nodeB.node.importKind || DEFAULT_IMPORT_KIND,
       );
     }
 
@@ -677,7 +677,7 @@ function removeNewLineAfterImport(context, currentImport, previousImport) {
   return undefined;
 }
 
-function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, distinctGroup) {
+function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, newlinesBetweenTypeOnlyImports, distinctGroup, isSortingTypesGroup) {
   const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
     const linesBetweenImports = getSourceCode(context).lines.slice(
       previousImport.node.loc.end.line,
@@ -690,35 +690,72 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, di
   let previousImport = imported[0];
 
   imported.slice(1).forEach(function (currentImport) {
-    const emptyLinesBetween = getNumberOfEmptyLinesBetween(currentImport, previousImport);
-    const isStartOfDistinctGroup = getIsStartOfDistinctGroup(currentImport, previousImport);
-
-    if (newlinesBetweenImports === 'always'
-        || newlinesBetweenImports === 'always-and-inside-groups') {
-      if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
-        if (distinctGroup || !distinctGroup && isStartOfDistinctGroup) {
-          context.report({
-            node: previousImport.node,
-            message: 'There should be at least one empty line between import groups',
-            fix: fixNewLineAfterImport(context, previousImport),
-          });
-        }
-      } else if (emptyLinesBetween > 0
-        && newlinesBetweenImports !== 'always-and-inside-groups') {
-        if (distinctGroup && currentImport.rank === previousImport.rank || !distinctGroup && !isStartOfDistinctGroup) {
-          context.report({
-            node: previousImport.node,
-            message: 'There should be no empty line within import group',
-            fix: removeNewLineAfterImport(context, currentImport, previousImport),
-          });
+    const emptyLinesBetween = getNumberOfEmptyLinesBetween(
+      currentImport,
+      previousImport,
+    );
+
+    const isStartOfDistinctGroup = getIsStartOfDistinctGroup(
+      currentImport,
+      previousImport,
+    );
+
+    const isTypeOnlyImport = currentImport.node.importKind === 'type';
+    const isPreviousImportTypeOnlyImport = previousImport.node.importKind === 'type';
+
+    const isNormalImportFollowingTypeOnlyImportAndRelevant = !isTypeOnlyImport && isPreviousImportTypeOnlyImport && isSortingTypesGroup;
+
+    const isTypeOnlyImportAndRelevant = isTypeOnlyImport && isSortingTypesGroup;
+
+    const isNotIgnored = isTypeOnlyImportAndRelevant
+        && newlinesBetweenTypeOnlyImports !== 'ignore'
+      || !isTypeOnlyImportAndRelevant && newlinesBetweenImports !== 'ignore';
+
+    if (isNotIgnored) {
+      const shouldAssertNewlineBetweenGroups = (isTypeOnlyImportAndRelevant || isNormalImportFollowingTypeOnlyImportAndRelevant)
+          && (newlinesBetweenTypeOnlyImports === 'always'
+            || newlinesBetweenTypeOnlyImports === 'always-and-inside-groups')
+        || !isTypeOnlyImportAndRelevant && !isNormalImportFollowingTypeOnlyImportAndRelevant
+          && (newlinesBetweenImports === 'always'
+            || newlinesBetweenImports === 'always-and-inside-groups');
+
+      const shouldAssertNoNewlineWithinGroup = (isTypeOnlyImportAndRelevant || isNormalImportFollowingTypeOnlyImportAndRelevant)
+          && newlinesBetweenTypeOnlyImports !== 'always-and-inside-groups'
+        || !isTypeOnlyImportAndRelevant && !isNormalImportFollowingTypeOnlyImportAndRelevant
+          && newlinesBetweenImports !== 'always-and-inside-groups';
+
+      const shouldAssertNoNewlineBetweenGroup = !isSortingTypesGroup
+        || !isNormalImportFollowingTypeOnlyImportAndRelevant
+        || newlinesBetweenTypeOnlyImports === 'never';
+
+      if (shouldAssertNewlineBetweenGroups) {
+        if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
+          if (distinctGroup || !distinctGroup && isStartOfDistinctGroup) {
+            context.report({
+              node: previousImport.node,
+              message: 'There should be at least one empty line between import groups',
+              fix: fixNewLineAfterImport(context, previousImport),
+            });
+          }
+        } else if (emptyLinesBetween > 0 && shouldAssertNoNewlineWithinGroup) {
+          if (
+            distinctGroup && currentImport.rank === previousImport.rank
+            || !distinctGroup && !isStartOfDistinctGroup
+          ) {
+            context.report({
+              node: previousImport.node,
+              message: 'There should be no empty line within import group',
+              fix: removeNewLineAfterImport(context, currentImport, previousImport),
+            });
+          }
         }
+      } else if (emptyLinesBetween > 0 && shouldAssertNoNewlineBetweenGroup) {
+        context.report({
+          node: previousImport.node,
+          message: 'There should be no empty line between import groups',
+          fix: removeNewLineAfterImport(context, currentImport, previousImport),
+        });
       }
-    } else if (emptyLinesBetween > 0) {
-      context.report({
-        node: previousImport.node,
-        message: 'There should be no empty line between import groups',
-        fix: removeNewLineAfterImport(context, currentImport, previousImport),
-      });
     }
 
     previousImport = currentImport;
@@ -793,6 +830,14 @@ module.exports = {
               'never',
             ],
           },
+          'newlines-between-types': {
+            enum: [
+              'ignore',
+              'always',
+              'always-and-inside-groups',
+              'never',
+            ],
+          },
           sortTypesGroup: {
             type: 'boolean',
             default: false,
@@ -845,6 +890,14 @@ module.exports = {
           },
         },
         additionalProperties: false,
+        dependencies: {
+          'newlines-between-types': {
+            properties: {
+              sortTypesGroup: { enum: [true] },
+            },
+            required: ['sortTypesGroup'],
+          },
+        },
       },
     ],
   },
@@ -852,6 +905,7 @@ module.exports = {
   create(context) {
     const options = context.options[0] || {};
     const newlinesBetweenImports = options['newlines-between'] || 'ignore';
+    const newlinesBetweenTypeOnlyImports = options['newlines-between-types'] || newlinesBetweenImports;
     const pathGroupsExcludedImportTypes = new Set(options.pathGroupsExcludedImportTypes || ['builtin', 'external', 'object']);
     const sortTypesGroup = options.sortTypesGroup;
 
@@ -1115,8 +1169,8 @@ module.exports = {
       },
       'Program:exit'() {
         importMap.forEach((imported) => {
-          if (newlinesBetweenImports !== 'ignore') {
-            makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, distinctGroup);
+          if (newlinesBetweenImports !== 'ignore' || newlinesBetweenTypeOnlyImports !== 'ignore') {
+            makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, newlinesBetweenTypeOnlyImports, distinctGroup, isSortingTypesGroup);
           }
 
           if (alphabetize.order !== 'ignore') {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 6da42474c3..13f96ca272 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -3440,6 +3440,168 @@ context('TypeScript', function () {
               },
             ],
           }),
+          // Option sortTypesGroup: true and newlines-between-types defaults to the value of newlines-between
+          test({
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA } from 'abc';
+              import type { A } from 'foo';
+
+              import type { C } from 'dirA/Bar';
+              import type { D } from 'dirA/bar';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+              },
+            ],
+          }),
+          // Option: sortTypesGroup: true and newlines-between-types: 'always' (takes precedence over newlines-between between type-only and normal imports)
+          test({
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+              import b from 'dirA/bar';
+              import index from './';
+
+              import type { AA } from 'abc';
+              import type { A } from 'foo';
+
+              import type { C } from 'dirA/Bar';
+              import type { D } from 'dirA/bar';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'never',
+                'newlines-between-types': 'always',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+              },
+            ],
+          }),
+          // Option: sortTypesGroup: true and newlines-between-types: 'never' (takes precedence over newlines-between between type-only and normal imports)
+          test({
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+              import type { AA } from 'abc';
+              import type { A } from 'foo';
+              import type { C } from 'dirA/Bar';
+              import type { D } from 'dirA/bar';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always',
+                'newlines-between-types': 'never',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+              },
+            ],
+          }),
+          // Option: sortTypesGroup: true and newlines-between-types: 'ignore'
+          test({
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+              import b from 'dirA/bar';
+              import index from './';
+              import type { AA } from 'abc';
+
+              import type { A } from 'foo';
+              import type { C } from 'dirA/Bar';
+              import type { D } from 'dirA/bar';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'never',
+                'newlines-between-types': 'ignore',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+              },
+            ],
+          }),
+          // Option: sortTypesGroup: true and newlines-between-types: 'always-and-inside-groups'
+          test({
+            code: `
+              import c from 'Bar';
+              import a from 'foo';
+              import b from 'dirA/bar';
+              import index from './';
+
+              import type { AA } from 'abc';
+
+              import type { A } from 'foo';
+
+              import type { C } from 'dirA/Bar';
+
+              import type { D } from 'dirA/bar';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'never',
+                'newlines-between-types': 'always-and-inside-groups',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+              },
+            ],
+          }),
           // Option: sortTypesGroup: true puts type imports in the same order as regular imports (from issue #2441, PR #2615)
           test({
             code: `
@@ -3467,6 +3629,116 @@ context('TypeScript', function () {
               },
             ],
           }),
+          // Options: sortTypesGroup + newlines-between-types example #1 from the documentation (pass)
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+                'newlines-between-types': 'ignore',
+              },
+            ],
+          }),
+          test({
+            code: `
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['builtin', 'parent', 'sibling', 'index', 'type'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+                'newlines-between-types': 'ignore',
+              },
+            ],
+          }),
+          // Options: sortTypesGroup + newlines-between-types example #2 from the documentation (pass)
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+
+              import type C from "../foo.js";
+
+              import type D from "./bar.js";
+
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                sortTypesGroup: true,
+                'newlines-between': 'never',
+                'newlines-between-types': 'always',
+              },
+            ],
+          }),
+          test({
+            code: `
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
+
+              import type A from "fs";
+              import type B from "path";
+
+              import type C from "../foo.js";
+
+              import type D from "./bar.js";
+
+              import type E from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['builtin', 'parent', 'sibling', 'index', 'type'],
+                sortTypesGroup: true,
+                'newlines-between': 'never',
+                'newlines-between-types': 'always',
+              },
+            ],
+          }),
         ),
         invalid: [].concat(
           // Option alphabetize: {order: 'asc'}
@@ -3721,6 +3993,117 @@ context('TypeScript', function () {
             }],
           }),
 
+          // Options: sortTypesGroup + newlines-between-types example #1 from the documentation (fail)
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            output: `
+              import type A from "fs";
+              import type B from "path";
+
+              import type C from "../foo.js";
+
+              import type D from "./bar.js";
+
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+              },
+            ],
+            errors: [
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 3,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 4,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 5,
+              },
+            ],
+          }),
+
+          // Options: sortTypesGroup + newlines-between-types example #2 from the documentation (fail)
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            output: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+                'newlines-between-types': 'never',
+              },
+            ],
+            errors: [
+              {
+                message: 'There should be no empty line between import groups',
+                line: 6,
+              },
+            ],
+          }),
+
           supportsExportTypeSpecifiers ? [
             test({
               code: `

From 42ce8569b2aab2e1dd70b0229493b370bfbfc09b Mon Sep 17 00:00:00 2001
From: Climax708 <soryy708@gmail.com>
Date: Sat, 14 Dec 2024 23:19:07 +0200
Subject: [PATCH 762/767] [meta] issue template with guidance for bug reports

---
 .github/issue_template.md | 10 ++++++++++
 1 file changed, 10 insertions(+)
 create mode 100644 .github/issue_template.md

diff --git a/.github/issue_template.md b/.github/issue_template.md
new file mode 100644
index 0000000000..673d652375
--- /dev/null
+++ b/.github/issue_template.md
@@ -0,0 +1,10 @@
+<!-- Reporting a bug? -->
+<!--
+  Please provide the output of running ESLint with this environment variable: `DEBUG=eslint-plugin-import:*`
+  Windows:      `set DEBUG=eslint-plugin-import:* & eslint .`
+  Linux/Mac: `export DEBUG=eslint-plugin-import:* & eslint .`
+
+  It will also be helpful if you can provide a minimal reproducible example
+  Preferably a GitHub repository containing all the code & ESLint config required
+  https://stackoverflow.com/help/minimal-reproducible-example
+-->

From 5e7ea1d3f00896acbc42ba8d354a4bee70a7d1b0 Mon Sep 17 00:00:00 2001
From: "Xunnamius (Romulus)" <Xunnamius@users.noreply.github.com>
Date: Sat, 16 Nov 2024 17:15:44 -0800
Subject: [PATCH 763/767] [Fix] `order`: ensure arcane imports do not cause
 undefined behavior

---
 CHANGELOG.md             |  2 ++
 src/rules/order.js       |  4 ++++
 tests/src/rules/order.js | 32 ++++++++++++++++++++++++++++++--
 3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a2a436a38a..7a092c2a46 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 ### Fixed
 - [`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks [@michaelfaith])
 - configs: added missing name attribute for eslint config inspector ([#3151], thanks [@NishargShah])
+- [`order`]: ensure arcane imports do not cause undefined behavior ([#3128], thanks [@Xunnamius])
 
 ### Changed
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
@@ -1173,6 +1174,7 @@ for info on changes for earlier releases.
 
 [#3151]: https://github.com/import-js/eslint-plugin-import/pull/3151
 [#3138]: https://github.com/import-js/eslint-plugin-import/pull/3138
+[#3128]: https://github.com/import-js/eslint-plugin-import/pull/3128
 [#3127]: https://github.com/import-js/eslint-plugin-import/pull/3127
 [#3125]: https://github.com/import-js/eslint-plugin-import/pull/3125
 [#3122]: https://github.com/import-js/eslint-plugin-import/pull/3122
diff --git a/src/rules/order.js b/src/rules/order.js
index cb77c15809..17e8735e19 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -535,6 +535,10 @@ function computeRank(context, ranks, importEntry, excludedImportTypes, isSorting
 
   if (typeof rank === 'undefined') {
     rank = ranks.groups[impType];
+
+    if (typeof rank === 'undefined') {
+      return -1;
+    }
   }
 
   if (isTypeOnlyImport && isSortingTypesGroup) {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index 13f96ca272..bde928f425 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -3115,7 +3115,6 @@ context('TypeScript', function () {
           }),
           // Option alphabetize: {order: 'asc'} with type group & path group
           test({
-            // only: true,
             code: `
               import c from 'Bar';
               import a from 'foo';
@@ -3145,7 +3144,6 @@ context('TypeScript', function () {
           }),
           // Option alphabetize: {order: 'asc'} with path group
           test({
-            // only: true,
             code: `
               import c from 'Bar';
               import type { A } from 'foo';
@@ -3739,6 +3737,36 @@ context('TypeScript', function () {
               },
             ],
           }),
+          // Ensure the rule doesn't choke and die on absolute paths trying to pass NaN around
+          test({
+            code: `
+              import fs from 'fs';
+
+              import '@scoped/package';
+              import type { B } from 'fs';
+
+              import type { A1 } from '/bad/bad/bad/bad';
+              import './a/b/c';
+              import type { A2 } from '/bad/bad/bad/bad';
+              import type { A3 } from '/bad/bad/bad/bad';
+              import type { D1 } from '/bad/bad/not/good';
+              import type { D2 } from '/bad/bad/not/good';
+              import type { D3 } from '/bad/bad/not/good';
+
+              import type { C } from '@something/else';
+
+              import type { E } from './index.js';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['builtin', 'type', 'unknown', 'external'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+              },
+            ],
+          }),
         ),
         invalid: [].concat(
           // Option alphabetize: {order: 'asc'}

From 4f145a2c64af4931f4bf3ae951c8b719b544718f Mon Sep 17 00:00:00 2001
From: "Xunnamius (Romulus)" <Xunnamius@users.noreply.github.com>
Date: Mon, 30 Dec 2024 17:12:49 -0800
Subject: [PATCH 764/767] [New] `order`: add `consolidateIslands` option to
 collapse excess spacing for aesthetically pleasing imports

---
 CHANGELOG.md             |    2 +
 docs/rules/order.md      |  286 +++-
 src/rules/order.js       |  123 +-
 tests/src/rules/order.js | 2874 +++++++++++++++++++++++++++++++++++---
 4 files changed, 3083 insertions(+), 202 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7a092c2a46..e72b3ca39e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`extensions`]: add `pathGroupOverrides to allow enforcement decision overrides based on specifier ([#3105], thanks [@Xunnamius])
 - [`order`]: add `sortTypesGroup` option to allow intragroup sorting of type-only imports ([#3104], thanks [@Xunnamius])
 - [`order`]: add `newlines-between-types` option to control intragroup sorting of type-only imports ([#3127], thanks [@Xunnamius])
+- [`order`]: add `consolidateIslands` option to collapse excess spacing for aesthetically pleasing imports ([#3129], thanks [@Xunnamius])
 
 ### Fixed
 - [`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks [@michaelfaith])
@@ -1174,6 +1175,7 @@ for info on changes for earlier releases.
 
 [#3151]: https://github.com/import-js/eslint-plugin-import/pull/3151
 [#3138]: https://github.com/import-js/eslint-plugin-import/pull/3138
+[#3129]: https://github.com/import-js/eslint-plugin-import/pull/3129
 [#3128]: https://github.com/import-js/eslint-plugin-import/pull/3128
 [#3127]: https://github.com/import-js/eslint-plugin-import/pull/3127
 [#3125]: https://github.com/import-js/eslint-plugin-import/pull/3125
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 3dee4b6de1..4a52b823e1 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -108,6 +108,7 @@ This rule supports the following options (none of which are required):
  - [`warnOnUnassignedImports`][5]
  - [`sortTypesGroup`][7]
  - [`newlines-between-types`][27]
+ - [`consolidateIslands`][25]
 
 ---
 
@@ -184,7 +185,7 @@ Sometimes [the predefined groups][18] are not fine-grained enough, especially wh
 `pathGroups` defines one or more [`PathGroup`][13]s relative to a predefined group.
 Imports are associated with a [`PathGroup`][13] based on path matching against the import specifier (using [minimatch][14]).
 
-> \[!IMPORTANT]
+> [!IMPORTANT]
 >
 > Note that, by default, imports grouped as `"builtin"`, `"external"`, or `"object"` will not be considered for further `pathGroups` matching unless they are removed from [`pathGroupsExcludedImportTypes`][9].
 
@@ -224,7 +225,7 @@ Default: `["builtin", "external", "object"]`
 By default, imports in certain [groups][18] are excluded from being matched against [`pathGroups`][8] to prevent overeager sorting.
 Use `pathGroupsExcludedImportTypes` to modify which groups are excluded.
 
-> \[!TIP]
+> [!TIP]
 >
 > If using imports with custom specifier aliases (e.g.
 > you're using `eslint-import-resolver-alias`, `paths` in `tsconfig.json`, etc) that [end up
@@ -254,7 +255,7 @@ Use `pathGroupsExcludedImportTypes` to modify which groups are excluded.
 Valid values: `boolean` \
 Default: `true`
 
-> \[!CAUTION]
+> [!CAUTION]
 >
 > Currently, `distinctGroup` defaults to `true`. However, in a later update, the
 > default will change to `false`.
@@ -371,7 +372,7 @@ Default: `{ order: "ignore", orderImportKind: "ignore", caseInsensitive: false }
 
 Determine the sort order of imports within each [predefined group][18] or [`PathGroup`][8] alphabetically based on specifier.
 
-> \[!NOTE]
+> [!NOTE]
 >
 > Imports will be alphabetized based on their _specifiers_, not by their
 > identifiers. For example, `const a = require('z');` will come _after_ `const z = require('a');` when `alphabetize` is set to `{ order: "asc" }`.
@@ -502,7 +503,7 @@ Default: `false`
 Warn when "unassigned" imports are out of order.
 Unassigned imports are imports with no corresponding identifiers (e.g. `import './my/thing.js'` or `require('./side-effects.js')`).
 
-> \[!NOTE]
+> [!NOTE]
 >
 > These warnings are not fixable with `--fix` since unassigned imports might be used for their [side-effects][31],
 > and changing the order of such imports cannot be done safely.
@@ -540,7 +541,7 @@ import './styles.css';
 Valid values: `boolean` \
 Default: `false`
 
-> \[!NOTE]
+> [!NOTE]
 >
 > This setting is only meaningful when `"type"` is included in [`groups`][18].
 
@@ -598,7 +599,7 @@ The same example will pass.
 Valid values: `"ignore" | "always" | "always-and-inside-groups" | "never"` \
 Default: the value of [`newlines-between`][20]
 
-> \[!NOTE]
+> [!NOTE]
 >
 > This setting is only meaningful when [`sortTypesGroup`][7] is enabled.
 
@@ -656,9 +657,9 @@ The same example will pass.
 
 Note the new line after `import type E from './';` but before `import a from "fs";`. This new line separates the type-only imports from the normal imports. Its existence is governed by [`newlines-between-types`][27] and _not `newlines-between`_.
 
-> \[!IMPORTANT]
+> [!IMPORTANT]
 >
-> In certain situations, `consolidateIslands: true` will take precedence over `newlines-between-types: "never"`, if used, when it comes to the new line separating type-only imports from normal imports.
+> In certain situations, [`consolidateIslands: true`][25] will take precedence over `newlines-between-types: "never"`, if used, when it comes to the new line separating type-only imports from normal imports.
 
 The next example will pass even though there's a new line preceding the normal import and [`newlines-between`][20] is set to `"never"`:
 
@@ -722,6 +723,272 @@ import d from "./bar.js";
 import e from "./";
 ```
 
+### `consolidateIslands`
+
+Valid values: `"inside-groups" | "never"` \
+Default: `"never"`
+
+> [!NOTE]
+>
+> This setting is only meaningful when [`newlines-between`][20] and/or [`newlines-between-types`][27] is set to `"always-and-inside-groups"`.
+
+When set to `"inside-groups"`, this ensures imports spanning multiple lines are separated from other imports with a new line while single-line imports are grouped together (and the space between them consolidated) if they belong to the same [group][18] or [`pathGroups`][8].
+
+> [!IMPORTANT]
+>
+> When all of the following are true:
+>
+>  - [`sortTypesGroup`][7] is set to `true`
+>  - `consolidateIslands` is set to `"inside-groups"`
+>  - [`newlines-between`][20] is set to `"always-and-inside-groups"` when [`newlines-between-types`][27] is set to `"never"` (or vice-versa)
+>
+> Then [`newlines-between`][20]/[`newlines-between-types`][27] will yield to
+> `consolidateIslands` and allow new lines to separate multi-line imports
+> regardless of the `"never"` setting.
+>
+> This configuration is useful, for instance, to keep single-line type-only
+> imports stacked tightly together at the bottom of your import block to
+> preserve space while still logically organizing normal imports for quick and
+> pleasant reference.
+
+#### Example
+
+Given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "newlines-between": "always-and-inside-groups",
+    "consolidateIslands": "inside-groups"
+  }]
+}
+```
+
+This will fail the rule check:
+
+```ts
+var fs = require('fs');
+var path = require('path');
+var { util1, util2, util3 } = require('util');
+var async = require('async');
+var relParent1 = require('../foo');
+var {
+  relParent21,
+  relParent22,
+  relParent23,
+  relParent24,
+} = require('../');
+var relParent3 = require('../bar');
+var { sibling1,
+  sibling2, sibling3 } = require('./foo');
+var sibling2 = require('./bar');
+var sibling3 = require('./foobar');
+```
+
+While this will succeed (and is what `--fix` would yield):
+
+```ts
+var fs = require('fs');
+var path = require('path');
+var { util1, util2, util3 } = require('util');
+
+var async = require('async');
+
+var relParent1 = require('../foo');
+
+var {
+  relParent21,
+  relParent22,
+  relParent23,
+  relParent24,
+} = require('../');
+
+var relParent3 = require('../bar');
+
+var { sibling1,
+  sibling2, sibling3 } = require('./foo');
+
+var sibling2 = require('./bar');
+var sibling3 = require('./foobar');
+```
+
+Note the intragroup "islands" of grouped single-line imports, as well as multi-line imports, are surrounded by new lines. At the same time, note the typical new lines separating different groups are still maintained thanks to [`newlines-between`][20].
+
+The same holds true for the next example; when given the following settings:
+
+```jsonc
+{
+  "import/order": ["error", {
+    "alphabetize": { "order": "asc" },
+    "groups": ["external", "internal", "index", "type"],
+    "pathGroups": [
+      {
+        "pattern": "dirA/**",
+        "group": "internal",
+        "position": "after"
+      },
+      {
+        "pattern": "dirB/**",
+        "group": "internal",
+        "position": "before"
+      },
+      {
+        "pattern": "dirC/**",
+        "group": "internal"
+      }
+    ],
+    "newlines-between": "always-and-inside-groups",
+    "newlines-between-types": "never",
+    "pathGroupsExcludedImportTypes": [],
+    "sortTypesGroup": true,
+    "consolidateIslands": "inside-groups"
+  }]
+}
+```
+
+> [!IMPORTANT]
+>
+> **Pay special attention to the value of [`pathGroupsExcludedImportTypes`][9]** in this example's settings.
+> Without it, the successful example below would fail.
+> This is because the imports with specifiers starting with "dirA/", "dirB/", and "dirC/" are all [considered part of the `"external"` group](#how-imports-are-grouped), and imports in that group are excluded from [`pathGroups`][8] matching by default.
+>
+> The fix is to remove `"external"` (and, in this example, the others) from [`pathGroupsExcludedImportTypes`][9].
+
+This will fail the rule check:
+
+```ts
+import c from 'Bar';
+import d from 'bar';
+import {
+  aa,
+  bb,
+  cc,
+  dd,
+  ee,
+  ff,
+  gg
+} from 'baz';
+import {
+  hh,
+  ii,
+  jj,
+  kk,
+  ll,
+  mm,
+  nn
+} from 'fizz';
+import a from 'foo';
+import b from 'dirA/bar';
+import index from './';
+import type { AA,
+  BB, CC } from 'abc';
+import type { Z } from 'fizz';
+import type {
+  A,
+  B
+} from 'foo';
+import type { C2 } from 'dirB/Bar';
+import type {
+  D2,
+  X2,
+  Y2
+} from 'dirB/bar';
+import type { E2 } from 'dirB/baz';
+import type { C3 } from 'dirC/Bar';
+import type {
+  D3,
+  X3,
+  Y3
+} from 'dirC/bar';
+import type { E3 } from 'dirC/baz';
+import type { F3 } from 'dirC/caz';
+import type { C1 } from 'dirA/Bar';
+import type {
+  D1,
+  X1,
+  Y1
+} from 'dirA/bar';
+import type { E1 } from 'dirA/baz';
+import type { F } from './index.js';
+import type { G } from './aaa.js';
+import type { H } from './bbb';
+```
+
+While this will succeed (and is what `--fix` would yield):
+
+```ts
+import c from 'Bar';
+import d from 'bar';
+
+import {
+  aa,
+  bb,
+  cc,
+  dd,
+  ee,
+  ff,
+  gg
+} from 'baz';
+
+import {
+  hh,
+  ii,
+  jj,
+  kk,
+  ll,
+  mm,
+  nn
+} from 'fizz';
+
+import a from 'foo';
+
+import b from 'dirA/bar';
+
+import index from './';
+
+import type { AA,
+  BB, CC } from 'abc';
+
+import type { Z } from 'fizz';
+
+import type {
+  A,
+  B
+} from 'foo';
+
+import type { C2 } from 'dirB/Bar';
+
+import type {
+  D2,
+  X2,
+  Y2
+} from 'dirB/bar';
+
+import type { E2 } from 'dirB/baz';
+import type { C3 } from 'dirC/Bar';
+
+import type {
+  D3,
+  X3,
+  Y3
+} from 'dirC/bar';
+
+import type { E3 } from 'dirC/baz';
+import type { F3 } from 'dirC/caz';
+import type { C1 } from 'dirA/Bar';
+
+import type {
+  D1,
+  X1,
+  Y1
+} from 'dirA/bar';
+
+import type { E1 } from 'dirA/baz';
+import type { F } from './index.js';
+import type { G } from './aaa.js';
+import type { H } from './bbb';
+```
+
 ## Related
 
  - [`import/external-module-folders`][29]
@@ -747,6 +1014,7 @@ import e from "./";
 [21]: https://eslint.org/docs/latest/rules/no-multiple-empty-lines
 [22]: https://prettier.io
 [23]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#type-modifiers-on-import-names
+[25]: #consolidateislands
 [27]: #newlines-between-types
 [28]: ../../README.md#importinternal-regex
 [29]: ../../README.md#importexternal-module-folders
diff --git a/src/rules/order.js b/src/rules/order.js
index 17e8735e19..b34efd0275 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -555,7 +555,17 @@ function computeRank(context, ranks, importEntry, excludedImportTypes, isSorting
 function registerNode(context, importEntry, ranks, imported, excludedImportTypes, isSortingTypesGroup) {
   const rank = computeRank(context, ranks, importEntry, excludedImportTypes, isSortingTypesGroup);
   if (rank !== -1) {
-    imported.push({ ...importEntry, rank });
+    let importNode = importEntry.node;
+
+    if (importEntry.type === 'require' && importNode.parent.parent.type === 'VariableDeclaration') {
+      importNode = importNode.parent.parent;
+    }
+
+    imported.push({
+      ...importEntry,
+      rank,
+      isMultiline: importNode.loc.end.line !== importNode.loc.start.line,
+    });
   }
 }
 
@@ -681,7 +691,7 @@ function removeNewLineAfterImport(context, currentImport, previousImport) {
   return undefined;
 }
 
-function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, newlinesBetweenTypeOnlyImports, distinctGroup, isSortingTypesGroup) {
+function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports_, newlinesBetweenTypeOnlyImports_, distinctGroup, isSortingTypesGroup, isConsolidatingSpaceBetweenImports) {
   const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
     const linesBetweenImports = getSourceCode(context).lines.slice(
       previousImport.node.loc.end.line,
@@ -707,34 +717,61 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, ne
     const isTypeOnlyImport = currentImport.node.importKind === 'type';
     const isPreviousImportTypeOnlyImport = previousImport.node.importKind === 'type';
 
-    const isNormalImportFollowingTypeOnlyImportAndRelevant = !isTypeOnlyImport && isPreviousImportTypeOnlyImport && isSortingTypesGroup;
+    const isNormalImportNextToTypeOnlyImportAndRelevant =      isTypeOnlyImport !== isPreviousImportTypeOnlyImport && isSortingTypesGroup;
 
     const isTypeOnlyImportAndRelevant = isTypeOnlyImport && isSortingTypesGroup;
 
-    const isNotIgnored = isTypeOnlyImportAndRelevant
+    // In the special case where newlinesBetweenImports and consolidateIslands
+    // want the opposite thing, consolidateIslands wins
+    const newlinesBetweenImports =      isSortingTypesGroup
+      && isConsolidatingSpaceBetweenImports
+      && (previousImport.isMultiline || currentImport.isMultiline)
+      && newlinesBetweenImports_ === 'never'
+      ? 'always-and-inside-groups'
+      : newlinesBetweenImports_;
+
+    // In the special case where newlinesBetweenTypeOnlyImports and
+    // consolidateIslands want the opposite thing, consolidateIslands wins
+    const newlinesBetweenTypeOnlyImports =      isSortingTypesGroup
+      && isConsolidatingSpaceBetweenImports
+      && (isNormalImportNextToTypeOnlyImportAndRelevant
+        || previousImport.isMultiline
+        || currentImport.isMultiline)
+      && newlinesBetweenTypeOnlyImports_ === 'never'
+      ? 'always-and-inside-groups'
+      : newlinesBetweenTypeOnlyImports_;
+
+    const isNotIgnored =      isTypeOnlyImportAndRelevant
         && newlinesBetweenTypeOnlyImports !== 'ignore'
       || !isTypeOnlyImportAndRelevant && newlinesBetweenImports !== 'ignore';
 
     if (isNotIgnored) {
-      const shouldAssertNewlineBetweenGroups = (isTypeOnlyImportAndRelevant || isNormalImportFollowingTypeOnlyImportAndRelevant)
+      const shouldAssertNewlineBetweenGroups =        (isTypeOnlyImportAndRelevant || isNormalImportNextToTypeOnlyImportAndRelevant)
           && (newlinesBetweenTypeOnlyImports === 'always'
             || newlinesBetweenTypeOnlyImports === 'always-and-inside-groups')
-        || !isTypeOnlyImportAndRelevant && !isNormalImportFollowingTypeOnlyImportAndRelevant
+        || !isTypeOnlyImportAndRelevant && !isNormalImportNextToTypeOnlyImportAndRelevant
           && (newlinesBetweenImports === 'always'
             || newlinesBetweenImports === 'always-and-inside-groups');
 
-      const shouldAssertNoNewlineWithinGroup = (isTypeOnlyImportAndRelevant || isNormalImportFollowingTypeOnlyImportAndRelevant)
+      const shouldAssertNoNewlineWithinGroup =        (isTypeOnlyImportAndRelevant || isNormalImportNextToTypeOnlyImportAndRelevant)
           && newlinesBetweenTypeOnlyImports !== 'always-and-inside-groups'
-        || !isTypeOnlyImportAndRelevant && !isNormalImportFollowingTypeOnlyImportAndRelevant
+        || !isTypeOnlyImportAndRelevant && !isNormalImportNextToTypeOnlyImportAndRelevant
           && newlinesBetweenImports !== 'always-and-inside-groups';
 
-      const shouldAssertNoNewlineBetweenGroup = !isSortingTypesGroup
-        || !isNormalImportFollowingTypeOnlyImportAndRelevant
+      const shouldAssertNoNewlineBetweenGroup =        !isSortingTypesGroup
+        || !isNormalImportNextToTypeOnlyImportAndRelevant
         || newlinesBetweenTypeOnlyImports === 'never';
 
+      const isTheNewlineBetweenImportsInTheSameGroup = distinctGroup && currentImport.rank === previousImport.rank
+      || !distinctGroup && !isStartOfDistinctGroup;
+
+      // Let's try to cut down on linting errors sent to the user
+      let alreadyReported = false;
+
       if (shouldAssertNewlineBetweenGroups) {
         if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
           if (distinctGroup || !distinctGroup && isStartOfDistinctGroup) {
+            alreadyReported = true;
             context.report({
               node: previousImport.node,
               message: 'There should be at least one empty line between import groups',
@@ -742,10 +779,8 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, ne
             });
           }
         } else if (emptyLinesBetween > 0 && shouldAssertNoNewlineWithinGroup) {
-          if (
-            distinctGroup && currentImport.rank === previousImport.rank
-            || !distinctGroup && !isStartOfDistinctGroup
-          ) {
+          if (isTheNewlineBetweenImportsInTheSameGroup) {
+            alreadyReported = true;
             context.report({
               node: previousImport.node,
               message: 'There should be no empty line within import group',
@@ -754,12 +789,41 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, ne
           }
         }
       } else if (emptyLinesBetween > 0 && shouldAssertNoNewlineBetweenGroup) {
+        alreadyReported = true;
         context.report({
           node: previousImport.node,
           message: 'There should be no empty line between import groups',
           fix: removeNewLineAfterImport(context, currentImport, previousImport),
         });
       }
+
+      if (!alreadyReported && isConsolidatingSpaceBetweenImports) {
+        if (emptyLinesBetween === 0 && currentImport.isMultiline) {
+          context.report({
+            node: previousImport.node,
+            message: 'There should be at least one empty line between this import and the multi-line import that follows it',
+            fix: fixNewLineAfterImport(context, previousImport),
+          });
+        } else if (emptyLinesBetween === 0 && previousImport.isMultiline) {
+          context.report({
+            node: previousImport.node,
+            message: 'There should be at least one empty line between this multi-line import and the import that follows it',
+            fix: fixNewLineAfterImport(context, previousImport),
+          });
+        } else if (
+          emptyLinesBetween > 0
+          && !previousImport.isMultiline
+          && !currentImport.isMultiline
+          && isTheNewlineBetweenImportsInTheSameGroup
+        ) {
+          context.report({
+            node: previousImport.node,
+            message:
+              'There should be no empty lines between this single-line import and the single-line import that follows it',
+            fix: removeNewLineAfterImport(context, currentImport, previousImport),
+          });
+        }
+      }
     }
 
     previousImport = currentImport;
@@ -842,6 +906,12 @@ module.exports = {
               'never',
             ],
           },
+          consolidateIslands: {
+            enum: [
+              'inside-groups',
+              'never',
+            ],
+          },
           sortTypesGroup: {
             type: 'boolean',
             default: false,
@@ -901,6 +971,18 @@ module.exports = {
             },
             required: ['sortTypesGroup'],
           },
+          consolidateIslands: {
+            anyOf: [{
+              properties: {
+                'newlines-between': { enum: ['always-and-inside-groups'] },
+              },
+              required: ['newlines-between'],
+            }, {
+              properties: {
+                'newlines-between-types': { enum: ['always-and-inside-groups'] },
+              },
+              required: ['newlines-between-types'],
+            }] },
         },
       },
     ],
@@ -912,6 +994,7 @@ module.exports = {
     const newlinesBetweenTypeOnlyImports = options['newlines-between-types'] || newlinesBetweenImports;
     const pathGroupsExcludedImportTypes = new Set(options.pathGroupsExcludedImportTypes || ['builtin', 'external', 'object']);
     const sortTypesGroup = options.sortTypesGroup;
+    const consolidateIslands = options.consolidateIslands || 'never';
 
     const named = {
       types: 'mixed',
@@ -1174,7 +1257,17 @@ module.exports = {
       'Program:exit'() {
         importMap.forEach((imported) => {
           if (newlinesBetweenImports !== 'ignore' || newlinesBetweenTypeOnlyImports !== 'ignore') {
-            makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, newlinesBetweenTypeOnlyImports, distinctGroup, isSortingTypesGroup);
+            makeNewlinesBetweenReport(
+              context,
+              imported,
+              newlinesBetweenImports,
+              newlinesBetweenTypeOnlyImports,
+              distinctGroup,
+              isSortingTypesGroup,
+              consolidateIslands === 'inside-groups'
+                && (newlinesBetweenImports === 'always-and-inside-groups'
+                  || newlinesBetweenTypeOnlyImports === 'always-and-inside-groups'),
+            );
           }
 
           if (alphabetize.order !== 'ignore') {
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index bde928f425..fa592c9b19 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -530,7 +530,7 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
-    // Option newlines-between: 'always' with multiline imports #1
+    // Option newlines-between: 'always' with multi-line imports #1
     test({
       code: `
         import path from 'path';
@@ -546,7 +546,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{ 'newlines-between': 'always' }],
     }),
-    // Option newlines-between: 'always' with multiline imports #2
+    // Option newlines-between: 'always' with multi-line imports #2
     test({
       code: `
         import path from 'path';
@@ -557,7 +557,7 @@ ruleTester.run('order', rule, {
       `,
       options: [{ 'newlines-between': 'always' }],
     }),
-    // Option newlines-between: 'always' with multiline imports #3
+    // Option newlines-between: 'always' with multi-line imports #3
     test({
       code: `
         import foo
@@ -671,6 +671,33 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
+    // Option newlines-between: 'always-and-inside-groups' and consolidateIslands: true
+    test({
+      code: `
+        var fs = require('fs');
+        var path = require('path');
+        var util = require('util');
+
+        var async = require('async');
+
+        var relParent1 = require('../foo');
+
+        var {
+          relParent2 } = require('../');
+
+        var relParent3 = require('../bar');
+
+        var sibling = require('./foo');
+        var sibling2 = require('./bar');
+        var sibling3 = require('./foobar');
+      `,
+      options: [
+        {
+          'newlines-between': 'always-and-inside-groups',
+          consolidateIslands: 'inside-groups',
+        },
+      ],
+    }),
     // Option alphabetize: {order: 'ignore'}
     test({
       code: `
@@ -1343,19 +1370,19 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     }),
-    // fix order with multilines comments at the end and start of line
+    // fix order with multi-lines comments at the end and start of line
     test({
       code: `
-        /* multiline1
-          comment1 */  var async = require('async'); /* multiline2
-          comment2 */  var fs = require('fs'); /* multiline3
+        /* multi-line1
+          comment1 */  var async = require('async'); /* multi-line2
+          comment2 */  var fs = require('fs'); /* multi-line3
           comment3 */
       `,
       output: `
-        /* multiline1
+        /* multi-line1
           comment1 */  var fs = require('fs');` + ' '  + `
-  var async = require('async'); /* multiline2
-          comment2 *//* multiline3
+  var async = require('async'); /* multi-line2
+          comment2 *//* multi-line3
           comment3 */
       `,
       errors: [{
@@ -1376,7 +1403,7 @@ ruleTester.run('order', rule, {
         message: '`fs` import should occur before import of `async`',
       }],
     }),
-    // fix order of multiline import
+    // fix order of multi-line import
     test({
       code: `
         var async = require('async');
@@ -1901,10 +1928,10 @@ ruleTester.run('order', rule, {
         },
       ],
     }),
-    // Cannot fix newlines-between with multiline comment after
+    // Cannot fix newlines-between with multi-line comment after
     test(withoutAutofixOutput({
       code: `
-        var fs = require('fs'); /* multiline
+        var fs = require('fs'); /* multi-line
         comment */
 
         var index = require('./');
@@ -2952,7 +2979,7 @@ ruleTester.run('order', rule, {
         message: '`A.C` export should occur after export of `A.B`',
       }],
     }),
-    // multiline named specifiers & trailing commas
+    // multi-line named specifiers & trailing commas
     test({
       code: `
         const {
@@ -3032,6 +3059,156 @@ ruleTester.run('order', rule, {
         }],
       }),
     ],
+    // Option newlines-between: 'always-and-inside-groups' and consolidateIslands: true
+    test({
+      code: `
+        var fs = require('fs');
+        var path = require('path');
+        var { util1, util2, util3 } = require('util');
+        var async = require('async');
+        var relParent1 = require('../foo');
+        var {
+          relParent21,
+          relParent22,
+          relParent23,
+          relParent24,
+        } = require('../');
+        var relParent3 = require('../bar');
+        var { sibling1,
+          sibling2, sibling3 } = require('./foo');
+        var sibling2 = require('./bar');
+        var sibling3 = require('./foobar');
+      `,
+      output: `
+        var fs = require('fs');
+        var path = require('path');
+        var { util1, util2, util3 } = require('util');
+
+        var async = require('async');
+
+        var relParent1 = require('../foo');
+
+        var {
+          relParent21,
+          relParent22,
+          relParent23,
+          relParent24,
+        } = require('../');
+
+        var relParent3 = require('../bar');
+
+        var { sibling1,
+          sibling2, sibling3 } = require('./foo');
+
+        var sibling2 = require('./bar');
+        var sibling3 = require('./foobar');
+      `,
+      options: [
+        {
+          'newlines-between': 'always-and-inside-groups',
+          consolidateIslands: 'inside-groups',
+        },
+      ],
+      errors: [
+        {
+          message: 'There should be at least one empty line between import groups',
+          line: 4,
+        },
+        {
+          message: 'There should be at least one empty line between import groups',
+          line: 5,
+        },
+        {
+          message: 'There should be at least one empty line between this import and the multi-line import that follows it',
+          line: 6,
+        },
+        {
+          message: 'There should be at least one empty line between this multi-line import and the import that follows it',
+          line: 12,
+        },
+        {
+          message: 'There should be at least one empty line between import groups',
+          line: 13,
+        },
+        {
+          message: 'There should be at least one empty line between this multi-line import and the import that follows it',
+          line: 15,
+        },
+      ],
+    }),
+    test({
+      code: `
+        var fs = require('fs');
+
+        var path = require('path');
+
+        var { util1, util2, util3 } = require('util');
+
+        var async = require('async');
+
+        var relParent1 = require('../foo');
+
+        var {
+          relParent21,
+          relParent22,
+          relParent23,
+          relParent24,
+        } = require('../');
+
+        var relParent3 = require('../bar');
+
+        var { sibling1,
+          sibling2, sibling3 } = require('./foo');
+
+        var sibling2 = require('./bar');
+
+        var sibling3 = require('./foobar');
+      `,
+      output: `
+        var fs = require('fs');
+        var path = require('path');
+        var { util1, util2, util3 } = require('util');
+
+        var async = require('async');
+
+        var relParent1 = require('../foo');
+
+        var {
+          relParent21,
+          relParent22,
+          relParent23,
+          relParent24,
+        } = require('../');
+
+        var relParent3 = require('../bar');
+
+        var { sibling1,
+          sibling2, sibling3 } = require('./foo');
+
+        var sibling2 = require('./bar');
+        var sibling3 = require('./foobar');
+      `,
+      options: [
+        {
+          'newlines-between': 'always-and-inside-groups',
+          consolidateIslands: 'inside-groups',
+        },
+      ],
+      errors: [
+        {
+          message: 'There should be no empty lines between this single-line import and the single-line import that follows it',
+          line: 2,
+        },
+        {
+          message: 'There should be no empty lines between this single-line import and the single-line import that follows it',
+          line: 4,
+        },
+        {
+          message: 'There should be no empty lines between this single-line import and the single-line import that follows it',
+          line: 24,
+        },
+      ],
+    }),
   ].filter(Boolean),
 });
 
@@ -3767,261 +3944,2289 @@ context('TypeScript', function () {
               },
             ],
           }),
-        ),
-        invalid: [].concat(
-          // Option alphabetize: {order: 'asc'}
+          // Option: sortTypesGroup: true and newlines-between-types: 'always-and-inside-groups' and consolidateIslands: 'inside-groups'
           test({
             code: `
-              import b from 'bar';
               import c from 'Bar';
-              import type { C } from 'Bar';
-              import a from 'foo';
-              import type { A } from 'foo';
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
 
-              import index from './';
-            `,
-            output: `
-              import c from 'Bar';
-              import type { C } from 'Bar';
-              import b from 'bar';
               import a from 'foo';
-              import type { A } from 'foo';
+
+              import b from 'dirA/bar';
 
               import index from './';
+
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+
+              import type { F } from './index.js';
+
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
             `,
             ...parserConfig,
             options: [
               {
-                groups: ['external', 'index'],
                 alphabetize: { order: 'asc' },
-              },
-            ],
-            errors: [
-              {
-                message: semver.satisfies(eslintPkg.version, '< 3')
-                  ? '`bar` import should occur after type import of `Bar`'
-                  : /(`bar` import should occur after type import of `Bar`)|(`Bar` type import should occur before import of `bar`)/,
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'always-and-inside-groups',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
               },
             ],
           }),
-          // Option alphabetize: {order: 'desc'}
+          // Option: sortTypesGroup: true and newlines-between-types: 'always-and-inside-groups' and consolidateIslands: 'never' (default)
           test({
             code: `
-              import a from 'foo';
-              import type { A } from 'foo';
               import c from 'Bar';
-              import type { C } from 'Bar';
-              import b from 'bar';
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
 
-              import index from './';
-            `,
-            output: `
               import a from 'foo';
-              import type { A } from 'foo';
-              import b from 'bar';
-              import c from 'Bar';
-              import type { C } from 'Bar';
+
+              import b from 'dirA/bar';
 
               import index from './';
+
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+
+              import type { F } from './index.js';
+
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
             `,
             ...parserConfig,
             options: [
               {
-                groups: ['external', 'index'],
-                alphabetize: { order: 'desc' },
-              },
-            ],
-            errors: [
-              {
-                message: semver.satisfies(eslintPkg.version, '< 3')
-                  ? '`bar` import should occur before import of `Bar`'
-                  : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'always-and-inside-groups',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'never',
               },
             ],
           }),
-          // Option alphabetize: {order: 'asc'} with type group
+          // Ensure consolidateIslands: 'inside-groups', newlines-between: 'always-and-inside-groups', and newlines-between-types: 'never' do not fight for dominance
           test({
             code: `
-              import b from 'bar';
-              import c from 'Bar';
-              import a from 'foo';
-
-              import index from './';
-
-              import type { A } from 'foo';
-              import type { C } from 'Bar';
-            `,
-            output: `
-              import c from 'Bar';
-              import b from 'bar';
-              import a from 'foo';
-
-              import index from './';
-
-              import type { C } from 'Bar';
-              import type { A } from 'foo';
+              import makeVanillaYargs from 'yargs/yargs';
+
+              import { createDebugLogger } from 'multiverse+rejoinder';
+
+              import { globalDebuggerNamespace } from 'rootverse+bfe:src/constant.ts';
+              import { ErrorMessage, type KeyValueEntry } from 'rootverse+bfe:src/error.ts';
+
+              import {
+                $artificiallyInvoked,
+                $canonical,
+                $exists,
+                $genesis
+              } from 'rootverse+bfe:src/symbols.ts';
+
+              import type {
+                Entries,
+                LiteralUnion,
+                OmitIndexSignature,
+                Promisable,
+                StringKeyOf
+              } from 'type-fest';
             `,
             ...parserConfig,
             options: [
               {
-                groups: ['external', 'index', 'type'],
-                alphabetize: { order: 'asc' },
-              },
+                alphabetize: {
+                  order: 'asc',
+                  orderImportKind: 'asc',
+                  caseInsensitive: true,
+                },
+                named: {
+                  enabled: true,
+                  types: 'types-last',
+                },
+                groups: [
+                  'builtin',
+                  'external',
+                  'internal',
+                  ['parent', 'sibling', 'index'],
+                  ['object', 'type'],
+                ],
+                pathGroups: [
+                  {
+                    pattern: 'multiverse{*,*/**}',
+                    group: 'external',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'rootverse{*,*/**}',
+                    group: 'external',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'universe{*,*/**}',
+                    group: 'external',
+                    position: 'after',
+                  },
+                ],
+                distinctGroup: true,
+                pathGroupsExcludedImportTypes: ['builtin', 'object'],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'never',
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+          }),
+          // Ensure consolidateIslands: 'inside-groups', newlines-between: 'never', and newlines-between-types: 'always-and-inside-groups' do not fight for dominance
+          test({
+            code: `
+              import makeVanillaYargs from 'yargs/yargs';
+              import { createDebugLogger } from 'multiverse+rejoinder';
+              import { globalDebuggerNamespace } from 'rootverse+bfe:src/constant.ts';
+              import { ErrorMessage, type KeyValueEntry } from 'rootverse+bfe:src/error.ts';
+              import { $artificiallyInvoked } from 'rootverse+bfe:src/symbols.ts';
+
+              import type {
+                Entries,
+                LiteralUnion,
+                OmitIndexSignature,
+                Promisable,
+                StringKeyOf
+              } from 'type-fest';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: {
+                  order: 'asc',
+                  orderImportKind: 'asc',
+                  caseInsensitive: true,
+                },
+                named: {
+                  enabled: true,
+                  types: 'types-last',
+                },
+                groups: [
+                  'builtin',
+                  'external',
+                  'internal',
+                  ['parent', 'sibling', 'index'],
+                  ['object', 'type'],
+                ],
+                pathGroups: [
+                  {
+                    pattern: 'multiverse{*,*/**}',
+                    group: 'external',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'rootverse{*,*/**}',
+                    group: 'external',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'universe{*,*/**}',
+                    group: 'external',
+                    position: 'after',
+                  },
+                ],
+                distinctGroup: true,
+                pathGroupsExcludedImportTypes: ['builtin', 'object'],
+                'newlines-between': 'never',
+                'newlines-between-types': 'always-and-inside-groups',
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+          }),
+          test({
+            code: `
+              import c from 'Bar';
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+
+              import a from 'foo';
+              import b from 'dirA/bar';
+              import index from './';
+
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+
+              import type { F } from './index.js';
+
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'never',
+                'newlines-between-types': 'always-and-inside-groups',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+          }),
+          test({
+            code: `
+              import assert from 'assert';
+              import { isNativeError } from 'util/types';
+
+              import { runNoRejectOnBadExit } from '@-xun/run';
+              import { TrialError } from 'named-app-errors';
+              import { resolve as resolverLibrary } from 'resolve.exports';
+
+              import { ${supportsImportTypeSpecifiers ? 'toAbsolutePath, type AbsolutePath' : 'AbsolutePath, toAbsolutePath'} } from 'rootverse+project-utils:src/fs.ts';
+
+              import type { PackageJson } from 'type-fest';
+              // Some comment about remembering to do something
+              import type { XPackageJson } from 'rootverse:src/assets/config/_package.json.ts';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: {
+                  order: 'asc',
+                  orderImportKind: 'asc',
+                  caseInsensitive: true,
+                },
+                named: {
+                  enabled: true,
+                  types: 'types-last',
+                },
+                groups: [
+                  'builtin',
+                  'external',
+                  'internal',
+                  ['parent', 'sibling', 'index'],
+                  ['object', 'type'],
+                ],
+                pathGroups: [
+                  {
+                    pattern: 'rootverse{*,*/**}',
+                    group: 'external',
+                    position: 'after',
+                  },
+                ],
+                distinctGroup: true,
+                pathGroupsExcludedImportTypes: ['builtin', 'object'],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'never',
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+          }),
+
+          // Documentation passing example #1 for newlines-between
+          test({
+            code: `
+              import fs from 'fs';
+              import path from 'path';
+
+              import sibling from './foo';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                'newlines-between': 'always',
+              },
+            ],
+          }),
+          // Documentation passing example #2 for newlines-between
+          test({
+            code: `
+              import fs from 'fs';
+
+              import path from 'path';
+
+              import sibling from './foo';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                'newlines-between': 'always-and-inside-groups',
+              },
+            ],
+          }),
+          // Documentation passing example #3 for newlines-between
+          test({
+            code: `
+              import fs from 'fs';
+              import path from 'path';
+              import sibling from './foo';
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                'newlines-between': 'never',
+              },
+            ],
+          }),
+          // Documentation passing example #1 for alphabetize
+          test({
+            code: `
+              import blist2 from 'blist';
+              import blist from 'BList';
+              import * as classnames from 'classnames';
+              import aTypes from 'prop-types';
+              import React, { PureComponent } from 'react';
+              import { compose, apply } from 'xcompose';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: {
+                  order: 'asc',
+                  caseInsensitive: true,
+                },
+              },
+            ],
+          }),
+          // (not an example, but we also test caseInsensitive: false for completeness)
+          test({
+            code: `
+              import blist from 'BList';
+              import blist2 from 'blist';
+              import * as classnames from 'classnames';
+              import aTypes from 'prop-types';
+              import React, { PureComponent } from 'react';
+              import { compose, apply } from 'xcompose';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: {
+                  order: 'asc',
+                  caseInsensitive: false,
+                },
+              },
+            ],
+          }),
+          // Documentation passing example #1 for named
+          test({
+            code: `
+              import { apply, compose } from 'xcompose';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                named: true,
+                alphabetize: {
+                  order: 'asc',
+                },
+              },
+            ],
+          }),
+          // Documentation passing example #1 for warnOnUnassignedImports
+          test({
+            code: `
+              import fs from 'fs';
+              import path from 'path';
+              import './styles.css';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                warnOnUnassignedImports: true,
+              },
+            ],
+          }),
+          // Documentation passing example #1 for sortTypesGroup
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                alphabetize: { order: 'asc' },
+                sortTypesGroup: true,
+              },
+            ],
+          }),
+          // (not an example, but we also test the reverse for completeness)
+          test({
+            code: `
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
+
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['builtin', 'parent', 'sibling', 'index', 'type'],
+                sortTypesGroup: true,
+              },
+            ],
+          }),
+          // Documentation passing example #1 for newlines-between-types
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+                'newlines-between-types': 'ignore',
+              },
+            ],
+          }),
+          // (not an example, but we also test the reverse for completeness)
+          test({
+            code: `
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['builtin', 'parent', 'sibling', 'index', 'type'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+                'newlines-between-types': 'ignore',
+              },
+            ],
+          }),
+          // Documentation passing example #2 for newlines-between-types
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+
+              import type C from "../foo.js";
+
+              import type D from "./bar.js";
+
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                sortTypesGroup: true,
+                'newlines-between': 'never',
+                'newlines-between-types': 'always',
+              },
+            ],
+          }),
+          // (not an example, but we also test the reverse for completeness)
+          test({
+            code: `
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
+
+              import type A from "fs";
+              import type B from "path";
+
+              import type C from "../foo.js";
+
+              import type D from "./bar.js";
+
+              import type E from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['builtin', 'parent', 'sibling', 'index', 'type'],
+                sortTypesGroup: true,
+                'newlines-between': 'never',
+                'newlines-between-types': 'always',
+              },
+            ],
+          }),
+          // Documentation passing example #1 for consolidateIslands
+          test({
+            code: `
+              var fs = require('fs');
+              var path = require('path');
+              var { util1, util2, util3 } = require('util');
+
+              var async = require('async');
+
+              var relParent1 = require('../foo');
+
+              var {
+                relParent21,
+                relParent22,
+                relParent23,
+                relParent24,
+              } = require('../');
+
+              var relParent3 = require('../bar');
+
+              var { sibling1,
+                sibling2, sibling3 } = require('./foo');
+
+              var sibling2 = require('./bar');
+              var sibling3 = require('./foobar');
+            `,
+            ...parserConfig,
+            options: [
+              {
+                'newlines-between': 'always-and-inside-groups',
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+          }),
+          // Documentation passing example #2 for consolidateIslands
+          test({
+            code: `
+              import c from 'Bar';
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+              import type { F } from './index.js';
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'never',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+          }),
+          // (not an example, but we also test the reverse for completeness)
+          test({
+            code: `
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+              import type { F } from './index.js';
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+
+              import c from 'Bar';
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['type', 'external', 'internal', 'index'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'never',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+          }),
+        ),
+        invalid: [].concat(
+          // Option alphabetize: {order: 'asc'}
+          test({
+            code: `
+              import b from 'bar';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import index from './';
+            `,
+            output: `
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import b from 'bar';
+              import a from 'foo';
+              import type { A } from 'foo';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index'],
+                alphabetize: { order: 'asc' },
+              },
+            ],
+            errors: [
+              {
+                message: semver.satisfies(eslintPkg.version, '< 3')
+                  ? '`bar` import should occur after type import of `Bar`'
+                  : /(`bar` import should occur after type import of `Bar`)|(`Bar` type import should occur before import of `bar`)/,
+              },
+            ],
+          }),
+          // Option alphabetize: {order: 'desc'}
+          test({
+            code: `
+              import a from 'foo';
+              import type { A } from 'foo';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+              import b from 'bar';
+
+              import index from './';
+            `,
+            output: `
+              import a from 'foo';
+              import type { A } from 'foo';
+              import b from 'bar';
+              import c from 'Bar';
+              import type { C } from 'Bar';
+
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index'],
+                alphabetize: { order: 'desc' },
+              },
+            ],
+            errors: [
+              {
+                message: semver.satisfies(eslintPkg.version, '< 3')
+                  ? '`bar` import should occur before import of `Bar`'
+                  : /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,
+              },
+            ],
+          }),
+          // Option alphabetize: {order: 'asc'} with type group
+          test({
+            code: `
+              import b from 'bar';
+              import c from 'Bar';
+              import a from 'foo';
+
+              import index from './';
+
+              import type { A } from 'foo';
+              import type { C } from 'Bar';
+            `,
+            output: `
+              import c from 'Bar';
+              import b from 'bar';
+              import a from 'foo';
+
+              import index from './';
+
+              import type { C } from 'Bar';
+              import type { A } from 'foo';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index', 'type'],
+                alphabetize: { order: 'asc' },
+              },
+            ],
+            errors: semver.satisfies(eslintPkg.version, '< 3') ? [
+              { message: '`Bar` import should occur before import of `bar`' },
+              { message: '`Bar` type import should occur before type import of `foo`' },
+            ] : [
+              { message: /(`Bar` import should occur before import of `bar`)|(`bar` import should occur after import of `Bar`)/ },
+              { message: /(`Bar` type import should occur before type import of `foo`)|(`foo` type import should occur after type import of `Bar`)/ },
+            ],
+          }),
+          // Option alphabetize: {order: 'desc'} with type group
+          test({
+            code: `
+              import a from 'foo';
+              import c from 'Bar';
+              import b from 'bar';
+
+              import index from './';
+
+              import type { C } from 'Bar';
+              import type { A } from 'foo';
+            `,
+            output: `
+              import a from 'foo';
+              import b from 'bar';
+              import c from 'Bar';
+
+              import index from './';
+
+              import type { A } from 'foo';
+              import type { C } from 'Bar';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['external', 'index', 'type'],
+                alphabetize: { order: 'desc' },
+              },
+            ],
+            errors: semver.satisfies(eslintPkg.version, '< 3') ? [
+              { message: '`bar` import should occur before import of `Bar`' },
+              { message: '`foo` type import should occur before type import of `Bar`' },
+            ] : [
+              { message: /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/ },
+              { message: /(`foo` type import should occur before type import of `Bar`)|(`Bar` type import should occur after import of type `foo`)/ },
+            ],
+          }),
+          // warns for out of order unassigned imports (warnOnUnassignedImports enabled)
+          test(withoutAutofixOutput({
+            code: `
+              import './local1';
+              import global from 'global1';
+              import local from './local2';
+              import 'global2';
+            `,
+            errors: [
+              {
+                message: '`global1` import should occur before import of `./local1`',
+              },
+              {
+                message: '`global2` import should occur before import of `./local1`',
+              },
+            ],
+            options: [{ warnOnUnassignedImports: true }],
+          })),
+          // fix cannot move below unassigned import (warnOnUnassignedImports enabled)
+          test(withoutAutofixOutput({
+            code: `
+              import local from './local';
+
+              import 'global1';
+
+              import global2 from 'global2';
+              import global3 from 'global3';
+            `,
+            errors: [{
+              message: '`./local` import should occur after import of `global3`',
+            }],
+            options: [{ warnOnUnassignedImports: true }],
+          })),
+          // Imports inside module declaration
+          test({
+            code: `
+              import type { ParsedPath } from 'path';
+              import type { CopyOptions } from 'fs';
+
+              declare module 'my-module' {
+                import type { ParsedPath } from 'path';
+                import type { CopyOptions } from 'fs';
+              }
+            `,
+            output: `
+              import type { CopyOptions } from 'fs';
+              import type { ParsedPath } from 'path';
+
+              declare module 'my-module' {
+                import type { CopyOptions } from 'fs';
+                import type { ParsedPath } from 'path';
+              }
+            `,
+            errors: [
+              { message: '`fs` type import should occur before type import of `path`' },
+              { message: '`fs` type import should occur before type import of `path`' },
+            ],
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+              },
+            ],
+          }),
+          // named import order
+          test({
+            code: `
+              import { type Z, A } from "./Z";
+              import type N, { E, D } from "./Z";
+              import type { L, G } from "./Z";
+            `,
+            output: `
+              import { A, type Z } from "./Z";
+              import type N, { D, E } from "./Z";
+              import type { G, L } from "./Z";
+            `,
+            ...parserConfig,
+            options: [{
+              named: true,
+              alphabetize: { order: 'asc' },
+            }],
+            errors: [
+              { message: `\`A\` import should occur before${supportsImportTypeSpecifiers ? ' type' : ''} import of \`Z\`` },
+              { message: '`D` import should occur before import of `E`' },
+              { message: '`G` import should occur before import of `L`' },
+            ],
+          }),
+          test({
+            code: `
+              const { B, /* Hello World */ A } = require("./Z");
+              export { B, A } from "./Z";
+            `,
+            output: `
+              const { /* Hello World */ A, B } = require("./Z");
+              export { A, B } from "./Z";
+            `,
+            ...parserConfig,
+            options: [{
+              named: true,
+              alphabetize: { order: 'asc' },
+            }],
+            errors: [{
+              message: '`A` import should occur before import of `B`',
+            }, {
+              message: '`A` export should occur before export of `B`',
+            }],
+          }),
+          // Options: sortTypesGroup + newlines-between-types example #1 from the documentation (fail)
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            output: `
+              import type A from "fs";
+              import type B from "path";
+
+              import type C from "../foo.js";
+
+              import type D from "./bar.js";
+
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+              },
+            ],
+            errors: [
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 3,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 4,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 5,
+              },
+            ],
+          }),
+          // Options: sortTypesGroup + newlines-between-types example #2 from the documentation (fail)
+          test({
+            code: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            output: `
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+              import a from "fs";
+              import b from "path";
+
+              import c from "../foo.js";
+
+              import d from "./bar.js";
+
+              import e from "./";
+            `,
+            ...parserConfig,
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                sortTypesGroup: true,
+                'newlines-between': 'always',
+                'newlines-between-types': 'never',
+              },
+            ],
+            errors: [
+              {
+                message: 'There should be no empty line between import groups',
+                line: 6,
+              },
+            ],
+          }),
+          // Option: sortTypesGroup: true and newlines-between-types: 'always-and-inside-groups' and consolidateIslands: 'inside-groups' with all newlines
+          test({
+            code: `
+              import c from 'Bar';
+
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+
+              import type { F3 } from 'dirC/caz';
+
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+
+              import type { F } from './index.js';
+
+              import type { G } from './aaa.js';
+
+              import type { H } from './bbb';
+            `,
+            output: `
+              import c from 'Bar';
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+
+              import type { F } from './index.js';
+
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'always-and-inside-groups',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+            errors: [
+              {
+                message:
+                  'There should be no empty lines between this single-line import and the single-line import that follows it',
+                line: 2,
+              },
+              {
+                message:
+                  'There should be no empty lines between this single-line import and the single-line import that follows it',
+                line: 60,
+              },
+              {
+                message:
+                  'There should be no empty lines between this single-line import and the single-line import that follows it',
+                line: 76,
+              },
+            ],
+          }),
+          // Option: sortTypesGroup: true and newlines-between-types: 'always-and-inside-groups' and consolidateIslands: 'inside-groups' with no newlines
+          test({
+            code: `
+              import c from 'Bar';
+              import d from 'bar';
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+              import a from 'foo';
+              import b from 'dirA/bar';
+              import index from './';
+              import type { AA,
+                BB, CC } from 'abc';
+              import type { Z } from 'fizz';
+              import type {
+                A,
+                B
+              } from 'foo';
+              import type { C2 } from 'dirB/Bar';
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+              import type { E2 } from 'dirB/baz';
+              import type { C3 } from 'dirC/Bar';
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+              import type { C1 } from 'dirA/Bar';
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+              import type { E1 } from 'dirA/baz';
+              import type { F } from './index.js';
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+            `,
+            output: `
+              import c from 'Bar';
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+
+              import type { F } from './index.js';
+
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'always-and-inside-groups',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
             ],
-            errors: semver.satisfies(eslintPkg.version, '< 3') ? [
-              { message: '`Bar` import should occur before import of `bar`' },
-              { message: '`Bar` type import should occur before type import of `foo`' },
-            ] : [
-              { message: /(`Bar` import should occur before import of `bar`)|(`bar` import should occur after import of `Bar`)/ },
-              { message: /(`Bar` type import should occur before type import of `foo`)|(`foo` type import should occur after type import of `Bar`)/ },
+            errors: [
+              {
+                message: 'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 3,
+              },
+              {
+                message: 'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 4,
+              },
+              {
+                message: 'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 13,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 22,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 23,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 24,
+              },
+              {
+                message: 'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 25,
+              },
+              {
+                message: 'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 27,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 28,
+              },
+              {
+                message: 'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 32,
+              },
+              {
+                message: 'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 33,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 38,
+              },
+              {
+                message: 'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 39,
+              },
+              {
+                message: 'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 40,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 46,
+              },
+              {
+                message: 'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 47,
+              },
+              {
+                message: 'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 48,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 53,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 54,
+              },
             ],
           }),
-          // Option alphabetize: {order: 'desc'} with type group
+          // Option: sortTypesGroup: true and newlines-between-types: 'always-and-inside-groups' and consolidateIslands: 'never' (default)
           test({
             code: `
+              import c from 'Bar';
+              import d from 'bar';
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
               import a from 'foo';
+              import b from 'dirA/bar';
+              import index from './';
+              import type { AA,
+                BB, CC } from 'abc';
+              import type { Z } from 'fizz';
+              import type {
+                A,
+                B
+              } from 'foo';
+              import type { C2 } from 'dirB/Bar';
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+              import type { E2 } from 'dirB/baz';
+              import type { C3 } from 'dirC/Bar';
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+              import type { C1 } from 'dirA/Bar';
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+              import type { E1 } from 'dirA/baz';
+              import type { F } from './index.js';
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+            `,
+            output: `
               import c from 'Bar';
-              import b from 'bar';
+              import d from 'bar';
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+              import a from 'foo';
+
+              import b from 'dirA/bar';
 
               import index from './';
 
-              import type { C } from 'Bar';
-              import type { A } from 'foo';
+              import type { AA,
+                BB, CC } from 'abc';
+              import type { Z } from 'fizz';
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+              import type { E2 } from 'dirB/baz';
+
+              import type { C3 } from 'dirC/Bar';
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+
+              import type { C1 } from 'dirA/Bar';
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+              import type { E1 } from 'dirA/baz';
+
+              import type { F } from './index.js';
+
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
             `,
-            output: `
-              import a from 'foo';
-              import b from 'bar';
-              import c from 'Bar';
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'always-and-inside-groups',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'never',
+              },
+            ],
+            errors: [
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 22,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 23,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 24,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 28,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 38,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 46,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 53,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 54,
+              },
+
+            ],
+          }),
 
+          // Documentation failing example #1 for newlines-between
+          test({
+            code: `
+              import fs from 'fs';
+              import path from 'path';
+              import sibling from './foo';
               import index from './';
+            `,
+            output: `
+              import fs from 'fs';
+              import path from 'path';
 
-              import type { A } from 'foo';
-              import type { C } from 'Bar';
+              import sibling from './foo';
+
+              import index from './';
             `,
             ...parserConfig,
             options: [
               {
-                groups: ['external', 'index', 'type'],
-                alphabetize: { order: 'desc' },
+                'newlines-between': 'always',
               },
             ],
-            errors: semver.satisfies(eslintPkg.version, '< 3') ? [
-              { message: '`bar` import should occur before import of `Bar`' },
-              { message: '`foo` type import should occur before type import of `Bar`' },
-            ] : [
-              { message: /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/ },
-              { message: /(`foo` type import should occur before type import of `Bar`)|(`Bar` type import should occur after import of type `foo`)/ },
+            errors: [
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 3,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 4,
+              },
             ],
           }),
-          // warns for out of order unassigned imports (warnOnUnassignedImports enabled)
-          test(withoutAutofixOutput({
+          // Documentation failing example #2 for newlines-between
+          test({
             code: `
-              import './local1';
-              import global from 'global1';
-              import local from './local2';
-              import 'global2';
+              import fs from 'fs';
+
+              import path from 'path';
+              import sibling from './foo';
+              import index from './';
+            `,
+            output: `
+              import fs from 'fs';
+
+              import path from 'path';
+
+              import sibling from './foo';
+
+              import index from './';
             `,
+            ...parserConfig,
+            options: [
+              {
+                'newlines-between': 'always-and-inside-groups',
+              },
+            ],
             errors: [
               {
-                message: '`global1` import should occur before import of `./local1`',
+                message: 'There should be at least one empty line between import groups',
+                line: 4,
               },
               {
-                message: '`global2` import should occur before import of `./local1`',
+                message: 'There should be at least one empty line between import groups',
+                line: 5,
               },
             ],
-            options: [{ warnOnUnassignedImports: true }],
-          })),
-          // fix cannot move below unassigned import (warnOnUnassignedImports enabled)
-          test(withoutAutofixOutput({
+          }),
+          // Documentation failing example #3 for newlines-between
+          test({
             code: `
-              import local from './local';
+              import fs from 'fs';
+              import path from 'path';
 
-              import 'global1';
+              import sibling from './foo';
 
-              import global2 from 'global2';
-              import global3 from 'global3';
+              import index from './';
             `,
-            errors: [{
-              message: '`./local` import should occur after import of `global3`',
-            }],
-            options: [{ warnOnUnassignedImports: true }],
-          })),
-          // Imports inside module declaration
+            output: `
+              import fs from 'fs';
+              import path from 'path';
+              import sibling from './foo';
+              import index from './';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                'newlines-between': 'never',
+              },
+            ],
+            errors: [
+              {
+                message: 'There should be no empty line between import groups',
+                line: 3,
+              },
+              {
+                message: 'There should be no empty line between import groups',
+                line: 5,
+              },
+            ],
+          }),
+          // Multiple errors
+          ...semver.satisfies(eslintPkg.version, '< 3.0.0') ? [] : [
+            // Documentation failing example #1 for alphabetize
+            test({
+              code: `
+                import React, { PureComponent } from 'react';
+                import aTypes from 'prop-types';
+                import { compose, apply } from 'xcompose';
+                import * as classnames from 'classnames';
+                import blist2 from 'blist';
+                import blist from 'BList';
+              `,
+              // The reason why this output does not match the success example after being fixed is because eslint will leave overlapping errors alone, so only one import gets reordered when fixes are applied
+              output: `
+                import aTypes from 'prop-types';
+                import React, { PureComponent } from 'react';
+                import { compose, apply } from 'xcompose';
+                import * as classnames from 'classnames';
+                import blist2 from 'blist';
+                import blist from 'BList';
+              `,
+              ...parserConfig,
+              options: [
+                {
+                  alphabetize: {
+                    order: 'asc',
+                    caseInsensitive: true,
+                  },
+                },
+              ],
+              errors: [
+                {
+                  message: '`prop-types` import should occur before import of `react`',
+                  line: 3,
+                },
+                {
+                  message: '`classnames` import should occur before import of `react`',
+                  line: 5,
+                },
+                {
+                  message: '`blist` import should occur before import of `react`',
+                  line: 6,
+                },
+                {
+                  message: '`BList` import should occur before import of `react`',
+                  line: 7,
+                },
+              ],
+            }),
+          ],
+          // Documentation failing example #1 for named
           test({
             code: `
-              import type { ParsedPath } from 'path';
-              import type { CopyOptions } from 'fs';
-
-              declare module 'my-module' {
-                import type { ParsedPath } from 'path';
-                import type { CopyOptions } from 'fs';
-              }
+              import { compose, apply } from 'xcompose';
             `,
             output: `
-              import type { CopyOptions } from 'fs';
-              import type { ParsedPath } from 'path';
-
-              declare module 'my-module' {
-                import type { CopyOptions } from 'fs';
-                import type { ParsedPath } from 'path';
-              }
+              import { apply, compose } from 'xcompose';
             `,
-            errors: [
-              { message: '`fs` type import should occur before type import of `path`' },
-              { message: '`fs` type import should occur before type import of `path`' },
-            ],
             ...parserConfig,
             options: [
               {
-                alphabetize: { order: 'asc' },
+                named: true,
+                alphabetize: {
+                  order: 'asc',
+                },
+              },
+            ],
+            errors: [
+              {
+                message: '`apply` import should occur before import of `compose`',
+                line: 2,
               },
             ],
           }),
-          // named import order
+          // Documentation failing example #1 for warnOnUnassignedImports
           test({
             code: `
-              import { type Z, A } from "./Z";
-              import type N, { E, D } from "./Z";
-              import type { L, G } from "./Z";
-            `,
-            output: `
-              import { A, type Z } from "./Z";
-              import type N, { D, E } from "./Z";
-              import type { G, L } from "./Z";
+              import fs from 'fs';
+              import './styles.css';
+              import path from 'path';
             `,
+            // Should not be fixed (eslint@>=9 expects null)
+            output: semver.satisfies(eslintPkg.version, '< 9.0.0') ? `
+              import fs from 'fs';
+              import './styles.css';
+              import path from 'path';
+            ` : null,
             ...parserConfig,
-            options: [{
-              named: true,
-              alphabetize: { order: 'asc' },
-            }],
+            options: [
+              {
+                warnOnUnassignedImports: true,
+              },
+            ],
             errors: [
-              { message: `\`A\` import should occur before${supportsImportTypeSpecifiers ? ' type' : ''} import of \`Z\`` },
-              { message: '`D` import should occur before import of `E`' },
-              { message: '`G` import should occur before import of `L`' },
+              {
+                message: '`path` import should occur before import of `./styles.css`',
+                line: 4,
+              },
             ],
           }),
+          // Documentation failing example #1 for sortTypesGroup
           test({
             code: `
-              const { B, /* Hello World */ A } = require("./Z");
-              export { B, A } from "./Z";
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
             `,
-            output: `
-              const { /* Hello World */ A, B } = require("./Z");
-              export { A, B } from "./Z";
+            // This is the "correct" behavior, but it's the wrong outcome (expectedly)
+            output: semver.satisfies(eslintPkg.version, '< 3.0.0')
+            // eslint@2 apparently attempts to fix multiple errors in one pass,
+            // which results in different erroneous output
+              ? `
+              import type E from './';
+              import type A from "fs";
+              import type B from "path";
+              import type C from "../foo.js";
+              import type D from "./bar.js";
+
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
+            ` : `
+              import type C from "../foo.js";
+              import type A from "fs";
+              import type B from "path";
+              import type D from "./bar.js";
+              import type E from './';
+
+              import a from "fs";
+              import b from "path";
+              import c from "../foo.js";
+              import d from "./bar.js";
+              import e from "./";
             `,
             ...parserConfig,
-            options: [{
-              named: true,
-              alphabetize: { order: 'asc' },
-            }],
-            errors: [{
-              message: '`A` import should occur before import of `B`',
-            }, {
-              message: '`A` export should occur before export of `B`',
-            }],
+            options: [
+              {
+                groups: ['type', 'builtin', 'parent', 'sibling', 'index'],
+                alphabetize: { order: 'asc' },
+              },
+            ],
+            errors: [
+              {
+                message: '`../foo.js` type import should occur before type import of `fs`',
+                line: 4,
+              },
+              {
+                message: '`./bar.js` type import should occur before type import of `fs`',
+                line: 5,
+              },
+              {
+                message: '`./` type import should occur before type import of `fs`',
+                line: 6,
+              },
+            ],
           }),
-
-          // Options: sortTypesGroup + newlines-between-types example #1 from the documentation (fail)
+          // Documentation failing example #1 for newlines-between-types
           test({
             code: `
               import type A from "fs";
@@ -4081,8 +6286,7 @@ context('TypeScript', function () {
               },
             ],
           }),
-
-          // Options: sortTypesGroup + newlines-between-types example #2 from the documentation (fail)
+          // Documentation failing example #2 for newlines-between-types
           test({
             code: `
               import type A from "fs";
@@ -4131,6 +6335,320 @@ context('TypeScript', function () {
               },
             ],
           }),
+          // Documentation failing example #1 for consolidateIslands
+          test({
+            code: `
+              var fs = require('fs');
+              var path = require('path');
+              var { util1, util2, util3 } = require('util');
+              var async = require('async');
+              var relParent1 = require('../foo');
+              var {
+                relParent21,
+                relParent22,
+                relParent23,
+                relParent24,
+              } = require('../');
+              var relParent3 = require('../bar');
+              var { sibling1,
+                sibling2, sibling3 } = require('./foo');
+              var sibling2 = require('./bar');
+              var sibling3 = require('./foobar');
+            `,
+            output: `
+              var fs = require('fs');
+              var path = require('path');
+              var { util1, util2, util3 } = require('util');
+
+              var async = require('async');
+
+              var relParent1 = require('../foo');
+
+              var {
+                relParent21,
+                relParent22,
+                relParent23,
+                relParent24,
+              } = require('../');
+
+              var relParent3 = require('../bar');
+
+              var { sibling1,
+                sibling2, sibling3 } = require('./foo');
+
+              var sibling2 = require('./bar');
+              var sibling3 = require('./foobar');
+            `,
+            ...parserConfig,
+            options: [
+              {
+                'newlines-between': 'always-and-inside-groups',
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+            errors: [
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 4,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 5,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 6,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 12,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 13,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 15,
+              },
+            ],
+          }),
+          // Documentation failing example #2 for consolidateIslands
+          test({
+            code: `
+              import c from 'Bar';
+              import d from 'bar';
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+              import a from 'foo';
+              import b from 'dirA/bar';
+              import index from './';
+              import type { AA,
+                BB, CC } from 'abc';
+              import type { Z } from 'fizz';
+              import type {
+                A,
+                B
+              } from 'foo';
+              import type { C2 } from 'dirB/Bar';
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+              import type { E2 } from 'dirB/baz';
+              import type { C3 } from 'dirC/Bar';
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+              import type { C1 } from 'dirA/Bar';
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+              import type { E1 } from 'dirA/baz';
+              import type { F } from './index.js';
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+            `,
+            output: `
+              import c from 'Bar';
+              import d from 'bar';
+
+              import {
+                aa,
+                bb,
+                cc,
+                dd,
+                ee,
+                ff,
+                gg
+              } from 'baz';
+
+              import {
+                hh,
+                ii,
+                jj,
+                kk,
+                ll,
+                mm,
+                nn
+              } from 'fizz';
+
+              import a from 'foo';
+
+              import b from 'dirA/bar';
+
+              import index from './';
+
+              import type { AA,
+                BB, CC } from 'abc';
+
+              import type { Z } from 'fizz';
+
+              import type {
+                A,
+                B
+              } from 'foo';
+
+              import type { C2 } from 'dirB/Bar';
+
+              import type {
+                D2,
+                X2,
+                Y2
+              } from 'dirB/bar';
+
+              import type { E2 } from 'dirB/baz';
+              import type { C3 } from 'dirC/Bar';
+
+              import type {
+                D3,
+                X3,
+                Y3
+              } from 'dirC/bar';
+
+              import type { E3 } from 'dirC/baz';
+              import type { F3 } from 'dirC/caz';
+              import type { C1 } from 'dirA/Bar';
+
+              import type {
+                D1,
+                X1,
+                Y1
+              } from 'dirA/bar';
+
+              import type { E1 } from 'dirA/baz';
+              import type { F } from './index.js';
+              import type { G } from './aaa.js';
+              import type { H } from './bbb';
+            `,
+            ...parserConfig,
+            options: [
+              {
+                alphabetize: { order: 'asc' },
+                groups: ['external', 'internal', 'index', 'type'],
+                pathGroups: [
+                  {
+                    pattern: 'dirA/**',
+                    group: 'internal',
+                    position: 'after',
+                  },
+                  {
+                    pattern: 'dirB/**',
+                    group: 'internal',
+                    position: 'before',
+                  },
+                  {
+                    pattern: 'dirC/**',
+                    group: 'internal',
+                  },
+                ],
+                'newlines-between': 'always-and-inside-groups',
+                'newlines-between-types': 'never',
+                pathGroupsExcludedImportTypes: [],
+                sortTypesGroup: true,
+                consolidateIslands: 'inside-groups',
+              },
+            ],
+            errors: [
+              {
+                message:
+                  'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 3,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 4,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 13,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 22,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 23,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 24,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 25,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 27,
+              },
+              {
+                message: 'There should be at least one empty line between import groups',
+                line: 28,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 32,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 33,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 39,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 40,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this import and the multi-line import that follows it',
+                line: 47,
+              },
+              {
+                message:
+                  'There should be at least one empty line between this multi-line import and the import that follows it',
+                line: 48,
+              },
+            ],
+          }),
 
           supportsExportTypeSpecifiers ? [
             test({

From 243606dc24fe324c6d7add00f699a80b86db0b6f Mon Sep 17 00:00:00 2001
From: "Xunnamius (Romulus)" <Xunnamius@users.noreply.github.com>
Date: Mon, 17 Mar 2025 18:10:42 -0700
Subject: [PATCH 765/767] [Fix] `order`: resolve undefined property access
 issue when using `named` ordering

Fixes #3159.
---
 CHANGELOG.md             |  2 ++
 src/rules/order.js       |  4 +++-
 tests/src/rules/order.js | 12 ++++++++++++
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e72b3ca39e..ce804fef3e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [`no-unused-modules`]: provide more meaningful error message when no .eslintrc is present ([#3116], thanks [@michaelfaith])
 - configs: added missing name attribute for eslint config inspector ([#3151], thanks [@NishargShah])
 - [`order`]: ensure arcane imports do not cause undefined behavior ([#3128], thanks [@Xunnamius])
+- [`order`]: resolve undefined property access issue when using `named` ordering ([#3166], thanks [@Xunnamius])
 
 ### Changed
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
@@ -1173,6 +1174,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3166]: https://github.com/import-js/eslint-plugin-import/pull/3166
 [#3151]: https://github.com/import-js/eslint-plugin-import/pull/3151
 [#3138]: https://github.com/import-js/eslint-plugin-import/pull/3138
 [#3129]: https://github.com/import-js/eslint-plugin-import/pull/3129
diff --git a/src/rules/order.js b/src/rules/order.js
index b34efd0275..a9b41c2f3d 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -1219,7 +1219,9 @@ module.exports = {
               if (node.right.type === 'ObjectExpression') {
                 for (let i = 0; i < node.right.properties.length; i++) {
                   if (
-                    node.right.properties[i].key.type !== 'Identifier'
+                    !node.right.properties[i].key
+                    || node.right.properties[i].key.type !== 'Identifier'
+                    || !node.right.properties[i].value
                     || node.right.properties[i].value.type !== 'Identifier'
                   ) {
                     return;
diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js
index fa592c9b19..362fa595a1 100644
--- a/tests/src/rules/order.js
+++ b/tests/src/rules/order.js
@@ -3944,6 +3944,18 @@ context('TypeScript', function () {
               },
             ],
           }),
+          // Ensure the rule doesn't choke and die when right-hand-side AssignmentExpression properties lack a "key" attribute (e.g. SpreadElement)
+          test({
+            code: `
+              // https://prettier.io/docs/en/options.html
+
+              module.exports = {
+                  ...require('@xxxx/.prettierrc.js'),
+              };
+            `,
+            ...parserConfig,
+            options: [{ named: { enabled: true } }],
+          }),
           // Option: sortTypesGroup: true and newlines-between-types: 'always-and-inside-groups' and consolidateIslands: 'inside-groups'
           test({
             code: `

From 6e49a58751455bab5f693fff0ee16501fced6952 Mon Sep 17 00:00:00 2001
From: JounQin <admin@1stg.me>
Date: Wed, 19 Mar 2025 06:04:20 +0800
Subject: [PATCH 766/767] [Refactor] `order`: remove unnecessary negative check

---
 CHANGELOG.md       | 2 ++
 src/rules/order.js | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce804fef3e..74cd1c1034 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - [Docs] add flat config guide for using `tseslint.config()` ([#3125], thanks [@lnuvy])
 - [Docs] add missing comma ([#3122], thanks [@RyanGst])
 - [readme] Update flatConfig example to include typescript config ([#3138], thanks [@intellix])
+- [Refactor] [`order`]: remove unnecessary negative check ([#3167], thanks [@JounQin])
 
 ## [2.31.0] - 2024-10-03
 
@@ -1174,6 +1175,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3167]: https://github.com/import-js/eslint-plugin-import/pull/3167
 [#3166]: https://github.com/import-js/eslint-plugin-import/pull/3166
 [#3151]: https://github.com/import-js/eslint-plugin-import/pull/3151
 [#3138]: https://github.com/import-js/eslint-plugin-import/pull/3138
diff --git a/src/rules/order.js b/src/rules/order.js
index a9b41c2f3d..ee339e14f8 100644
--- a/src/rules/order.js
+++ b/src/rules/order.js
@@ -770,7 +770,7 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports_, n
 
       if (shouldAssertNewlineBetweenGroups) {
         if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
-          if (distinctGroup || !distinctGroup && isStartOfDistinctGroup) {
+          if (distinctGroup || isStartOfDistinctGroup) {
             alreadyReported = true;
             context.report({
               node: previousImport.node,

From da5f6ec13160cb288338db0c2a00c34b2d932f0d Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Wed, 9 Apr 2025 23:42:13 -0700
Subject: [PATCH 767/767] [Fix] `enforce-node-protocol-usage`: avoid a crash
 with some TS code

---
 CHANGELOG.md                                  |  2 ++
 src/rules/enforce-node-protocol-usage.js      |  4 +--
 .../src/rules/enforce-node-protocol-usage.js  | 27 ++++++++++++++++++-
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 74cd1c1034..d8fe04c274 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
 - configs: added missing name attribute for eslint config inspector ([#3151], thanks [@NishargShah])
 - [`order`]: ensure arcane imports do not cause undefined behavior ([#3128], thanks [@Xunnamius])
 - [`order`]: resolve undefined property access issue when using `named` ordering ([#3166], thanks [@Xunnamius])
+- [`enforce-node-protocol-usage`]: avoid a crash with some TS code ([#3173], thanks [@ljharb])
 
 ### Changed
 - [Docs] [`extensions`], [`order`]: improve documentation ([#3106], thanks [@Xunnamius])
@@ -1175,6 +1176,7 @@ for info on changes for earlier releases.
 
 [`memo-parser`]: ./memo-parser/README.md
 
+[#3173]: https://github.com/import-js/eslint-plugin-import/pull/3173
 [#3167]: https://github.com/import-js/eslint-plugin-import/pull/3167
 [#3166]: https://github.com/import-js/eslint-plugin-import/pull/3166
 [#3151]: https://github.com/import-js/eslint-plugin-import/pull/3151
diff --git a/src/rules/enforce-node-protocol-usage.js b/src/rules/enforce-node-protocol-usage.js
index 88c31fc727..603f740586 100644
--- a/src/rules/enforce-node-protocol-usage.js
+++ b/src/rules/enforce-node-protocol-usage.js
@@ -29,7 +29,7 @@ function replaceStringLiteral(
 }
 
 function isStringLiteral(node) {
-  return node.type === 'Literal' && typeof node.value === 'string';
+  return node && node.type === 'Literal' && typeof node.value === 'string';
 }
 
 function isStaticRequireWith1Param(node) {
@@ -44,7 +44,7 @@ function isStaticRequireWith1Param(node) {
 
 function checkAndReport(src, context) {
   // TODO use src.quasis[0].value.raw
-  if (src.type === 'TemplateLiteral') { return; }
+  if (!src || src.type === 'TemplateLiteral') { return; }
   const moduleName = 'value' in src ? src.value : src.name;
   if (typeof moduleName !== 'string') { console.log(src, moduleName); }
   const { settings } = context;
diff --git a/tests/src/rules/enforce-node-protocol-usage.js b/tests/src/rules/enforce-node-protocol-usage.js
index f9bbcbad1f..7bced2d1ba 100644
--- a/tests/src/rules/enforce-node-protocol-usage.js
+++ b/tests/src/rules/enforce-node-protocol-usage.js
@@ -2,7 +2,7 @@ import { RuleTester } from '../rule-tester';
 import flatMap from 'array.prototype.flatmap';
 import { satisfies } from 'semver';
 
-import { test, testVersion } from '../utils';
+import { getTSParsers, test, testVersion } from '../utils';
 
 const ruleTester = new RuleTester();
 const rule = require('rules/enforce-node-protocol-usage');
@@ -343,3 +343,28 @@ ruleTester.run('enforce-node-protocol-usage', rule, {
     })),
   ),
 });
+
+context('TypeScript', function () {
+  getTSParsers().forEach((parser) => {
+    ruleTester.run('enforce-node-protocol-usage', rule, {
+      valid: [
+        test({
+          code: `
+            export class Thing {
+              constructor(public readonly name: string) {
+                  // Do nothing.
+              }
+
+              public sayHello(): void {
+                  console.log(\`Hello, \${this.name}!\`);
+              }
+            }
+          `,
+          parser,
+          options: preferUsingProtocol,
+        }),
+      ],
+      invalid: [],
+    });
+  });
+});