Repository: eslint/eslint (js)

Issue:
no-restricted-imports doesn't handle re-export
* **ESLint Version:** 4.12.1

```js
{
    "parserOptions": {
        "ecmaVersion": 6,
        "sourceType": "module"
    },
    "rules": {
        "no-restricted-imports": ["error", "fs"]
    }
}
```

```js
import fs from 'fs';
export * from 'fs';
export {default as fs} from 'fs';
export {readFile} from 'fs';
```

**What did you expect to happen?**
All the statements including re-exports should be reported as errors.

**What actually happened? Please include the actual, raw output from ESLint.**
```bash
  1:1  error  'fs' import is restricted from being used  no-restricted-imports
```
Only import is reported; re-exports are ignored.

Pull request:
Fix: no-restricted-imports to check re-export (fixes #9678)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[ ] Documentation update
[x] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**

Added checks to `no-restricted-imports` to check for re-export using `export * from 'foo'` and `export {f} from 'foo'` syntax forms.

**Is there anything you'd like reviewers to focus on?**

Did I miss anything?


Patch:
diff --git a/docs/rules/no-restricted-imports.md b/docs/rules/no-restricted-imports.md
index 66b8095a0..62747ebce 100644
--- a/docs/rules/no-restricted-imports.md
+++ b/docs/rules/no-restricted-imports.md
@@ -1,6 +1,6 @@
 # Disallow specific imports (no-restricted-imports)
 
-Imports are an ES6/ES2015 standard for making the functionality of other modules available in your current module. In CommonJS this is implemented through the require() call which makes this ESLint rule roughly equivalent to its CommonJS counterpart `no-restricted-modules`.
+Imports are an ES6/ES2015 standard for making the functionality of other modules available in your current module. In CommonJS this is implemented through the `require()` call which makes this ESLint rule roughly equivalent to its CommonJS counterpart `no-restricted-modules`.
 
 Why would you want to restrict imports?
 
@@ -87,6 +87,18 @@ Examples of **incorrect** code for this rule:
 import fs from 'fs';
 ```
 
+```js
+/*eslint no-restricted-imports: ["error", "fs"]*/
+
+export { fs } from 'fs';
+```
+
+```js
+/*eslint no-restricted-imports: ["error", "fs"]*/
+
+export * from 'fs';
+```
+
 ```js
 /*eslint no-restricted-imports: ["error", { "paths": ["cluster"] }]*/
 
@@ -135,6 +147,7 @@ Examples of **correct** code for this rule:
 /*eslint no-restricted-imports: ["error", "fs"]*/
 
 import crypto from 'crypto';
+export { foo } from "bar";
 ```
 
 ```js
@@ -142,6 +155,7 @@ import crypto from 'crypto';
 
 import crypto from 'crypto';
 import eslint from 'eslint';
+export * from "path";
 ```
 
 ```js
diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md
index 3bb64faf8..13ec086ae 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -26,7 +26,7 @@ For ES6 syntax, use `{ "parserOptions": { "ecmaVersion": 6 } }`; for new ES6 glo
 { "es6": true } }` (this setting enables ES6 syntax automatically).
 Parser options are set in your `.eslintrc.*` file by using the `parserOptions` property. The available options are:
 
-* `ecmaVersion` - set to 3, 5 (default), 6, 7, 8, or 9 to specify the version of ECMAScript syntax you want to use. You can also set to 2015 (same as 6), 2016 (same as 7), 2017 (same as 8), or 2018 (same as 9) to use the year-based naming.
+* `ecmaVersion` - set to 3, 5 (default), 6, 7, 8, 9, or 10 to specify the version of ECMAScript syntax you want to use. You can also set to 2015 (same as 6), 2016 (same as 7), 2017 (same as 8), 2018 (same as 9), or 2019 (same as 10) to use the year-based naming.
 * `sourceType` - set to `"script"` (default) or `"module"` if your code is in ECMAScript modules.
 * `ecmaFeatures` - an object indicating which additional language features you'd like to use:
     * `globalReturn` - allow `return` statements in the global scope
diff --git a/lib/rules/no-restricted-imports.js b/lib/rules/no-restricted-imports.js
index e4563172e..b8fcca1aa 100644
--- a/lib/rules/no-restricted-imports.js
+++ b/lib/rules/no-restricted-imports.js
@@ -236,31 +236,47 @@ module.exports = {
             return restrictedPatterns.length > 0 && restrictedPatternsMatcher.ignores(importSource);
         }
 
-        return {
-            ImportDeclaration(node) {
-                const importSource = node.source.value.trim();
-                const importNames = node.specifiers.reduce((set, specifier) => {
-                    if (specifier.type === "ImportDefaultSpecifier") {
-                        set.add("default");
-                    } else if (specifier.type === "ImportNamespaceSpecifier") {
-                        set.add("*");
-                    } else {
-                        set.add(specifier.imported.name);
-                    }
-                    return set;
-                }, new Set());
-
-                if (isRestrictedForEverythingImported(importSource, importNames)) {
-                    reportPathForEverythingImported(importSource, node);
+        /**
+         * Checks a node to see if any problems should be reported.
+         * @param {ASTNode} node The node to check.
+         * @returns {void}
+         * @private
+         */
+        function checkNode(node) {
+            const importSource = node.source.value.trim();
+            const importNames = node.specifiers ? node.specifiers.reduce((set, specifier) => {
+                if (specifier.type === "ImportDefaultSpecifier") {
+                    set.add("default");
+                } else if (specifier.type === "ImportNamespaceSpecifier") {
+                    set.add("*");
+                } else if (specifier.imported) {
+                    set.add(specifier.imported.name);
+                } else if (specifier.local) {
+                    set.add(specifier.local.name);
                 }
+                return set;
+            }, new Set()) : new Set();
 
-                if (isRestrictedPath(importSource, importNames)) {
-                    reportPath(node);
-                }
-                if (isRestrictedPattern(importSource)) {
-                    reportPathForPatterns(node);
-                }
+            if (isRestrictedForEverythingImported(importSource, importNames)) {
+                reportPathForEverythingImported(importSource, node);
+            }
+
+            if (isRestrictedPath(importSource, importNames)) {
+                reportPath(node);
+            }
+            if (isRestrictedPattern(importSource)) {
+                reportPathForPatterns(node);
             }
+        }
+
+        return {
+            ImportDeclaration: checkNode,
+            ExportNamedDeclaration(node) {
+                if (node.source) {
+                    checkNode(node);
+                }
+            },
+            ExportAllDeclaration: checkNode
         };
     }
 };
diff --git a/lib/rules/no-unreachable.js b/lib/rules/no-unreachable.js
index 5f90500a0..8ea2583f7 100644
--- a/lib/rules/no-unreachable.js
+++ b/lib/rules/no-unreachable.js
@@ -182,7 +182,6 @@ module.exports = {
             ContinueStatement: reportIfUnreachable,
             DebuggerStatement: reportIfUnreachable,
             DoWhileStatement: reportIfUnreachable,
-            EmptyStatement: reportIfUnreachable,
             ExpressionStatement: reportIfUnreachable,
             ForInStatement: reportIfUnreachable,
             ForOfStatement: reportIfUnreachable,
diff --git a/package.json b/package.json
index c2f7626dc..633373ced 100644
--- a/package.json
+++ b/package.json
@@ -87,8 +87,8 @@
     "coveralls": "^3.0.1",
     "dateformat": "^3.0.3",
     "ejs": "^2.6.1",
-    "eslint-plugin-eslint-plugin": "^1.2.0",
-    "eslint-plugin-node": "^7.0.1",
+    "eslint-plugin-eslint-plugin": "^1.4.1",
+    "eslint-plugin-node": "^8.0.0",
     "eslint-plugin-rulesdir": "^0.1.0",
     "eslint-release": "^1.0.0",
     "eslint-rule-composer": "^0.3.0",
diff --git a/packages/eslint-config-eslint/package.json b/packages/eslint-config-eslint/package.json
index e6e0bfe4e..a12cf52a9 100644
--- a/packages/eslint-config-eslint/package.json
+++ b/packages/eslint-config-eslint/package.json
@@ -23,7 +23,7 @@
     "js-yaml": "^3.5.1"
   },
   "peerDependencies": {
-    "eslint-plugin-node": "^6.0.1 || ^7.0.1"
+    "eslint-plugin-node": "^6.0.1 || ^7.0.1 || ^8.0.0"
   },
   "keywords": [
     "eslintconfig",


Test patch:
diff --git a/tests/lib/rules/no-restricted-imports.js b/tests/lib/rules/no-restricted-imports.js
index 5d279d5a3..c4f2abb60 100644
--- a/tests/lib/rules/no-restricted-imports.js
+++ b/tests/lib/rules/no-restricted-imports.js
@@ -193,6 +193,24 @@ ruleTester.run("no-restricted-imports", rule, {
         code: "import withGitignores from \"foo/bar\";",
         options: [{ patterns: ["foo/*", "!foo/baz"] }],
         errors: [{ message: "'foo/bar' import is restricted from being used by a pattern.", type: "ImportDeclaration" }]
+    }, {
+        code: "export * from \"fs\";",
+        options: ["fs"],
+        errors: [{ message: "'fs' import is restricted from being used.", type: "ExportAllDeclaration" }]
+    }, {
+        code: "export {a} from \"fs\";",
+        options: ["fs"],
+        errors: [{ message: "'fs' import is restricted from being used.", type: "ExportNamedDeclaration" }]
+    }, {
+        code: "export {foo as b} from \"fs\";",
+        options: [{
+            paths: [{
+                name: "fs",
+                importNames: ["foo"],
+                message: "Don't import 'foo'."
+            }]
+        }],
+        errors: [{ message: "'fs' import is restricted from being used. Don't import 'foo'.", type: "ExportNamedDeclaration" }]
     }, {
         code: "import withGitignores from \"foo\";",
         options: [{
diff --git a/tests/lib/rules/no-unreachable.js b/tests/lib/rules/no-unreachable.js
index 54575cc00..1e04d687c 100644
--- a/tests/lib/rules/no-unreachable.js
+++ b/tests/lib/rules/no-unreachable.js
@@ -32,6 +32,13 @@ ruleTester.run("no-unreachable", rule, {
         "while (true) { if (true) break; var x = 1; }",
         "while (true) continue;",
         "switch (foo) { case 1: break; var x; }",
+        "switch (foo) { case 1: break; var x; default: throw true; };",
+        {
+            code: "const arrow_direction = arrow => {  switch (arrow) { default: throw new Error();  };}",
+            parserOptions: {
+                ecmaVersion: 6
+            }
+        },
         "var x = 1; y = 2; throw 'uh oh'; var y;",
         "function foo() { var x = 1; if (x) { return; } x = 2; }",
         "function foo() { var x = 1; if (x) { } else { return; } x = 2; }",
@@ -63,6 +70,20 @@ ruleTester.run("no-unreachable", rule, {
         { code: "function foo() { var x = 1; while (x) { if (x) break; else continue; x = 2; } }", errors: [{ message: "Unreachable code.", type: "ExpressionStatement" }] },
         { code: "function foo() { var x = 1; for (;;) { if (x) continue; } x = 2; }", errors: [{ message: "Unreachable code.", type: "ExpressionStatement" }] },
         { code: "function foo() { var x = 1; while (true) { } x = 2; }", errors: [{ message: "Unreachable code.", type: "ExpressionStatement" }] },
+        {
+            code: "const arrow_direction = arrow => {  switch (arrow) { default: throw new Error();  }; g() }",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Unreachable code.",
+                    type: "ExpressionStatement",
+                    line: 1,
+                    column: 86,
+                    endLine: 1,
+                    endColumn: 89
+                }
+            ]
+        },
 
         // Merge the warnings of continuous unreachable nodes.
         {