Repository: eslint/eslint (js)

Issue:
require-await  Potential pitfall if used.  Doc update maybe?
Been using ESLint for a while, most rules are great.  
But I would like to point out there is a major problem in enabling this rule.

The problem, take the code below.

`async function test() { throw new Error("test"); }`

There is no `await`, but what the `async` does here is guarantee a `Promise`.  So the following code will return `got`.

`test().catch(function (e) { console.log("got"); })`

Take away the `async` and the above code is going to fail big time  Now if you can guarantee you are always going to call test with `await`, you are ok again as `await` will check if it's a `Promise`, but if you sent this to any other other Promise based consumers you have the above issue.

I'm mainly pointing this out as the Doc's say nothing of this issue, and could potential cause hard to debug issues for people who are currently mixing Promise & async / await.  So I wonder if a big warning of this potential pitfall should be put in the Doc's.

Pull request description:
Docs: Update require-await docs with exception (fixes #9540)
<!--
    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)**

[x] Documentation update
[ ] 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)**

Updated the docs for `require-await` to explain why you might not want to use it. Also, expanded the rule's description. It seems like this rule really needed a lot more documentation than it had.

**Is there anything you'd like reviewers to focus on?**

Does everything make sense?


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/rules/require-await.md b/docs/rules/require-await.md
index 4f1e4441e..2fb871cf1 100644
--- a/docs/rules/require-await.md
+++ b/docs/rules/require-await.md
@@ -1,6 +1,23 @@
 # Disallow async functions which have no `await` expression (require-await)
 
-Async functions which have no `await` expression may be the unintentional result of refactoring.
+Asynchronous functions in JavaScript behave differently than other functions in two important ways:
+
+1. The return value is always a `Promise`.
+2. You can use the `await` operator inside of them.
+
+The primary reason to use asynchronous functions is typically to use the `await` operator, such as this:
+
+```js
+async function fetchData(processDataItem) {
+    const response = await fetch(DATA_URL);
+    const data = await response.json();
+
+    return data.map(processDataItem);
+}
+```
+
+Asynchronous functions that don't use `await` might not need to be asynchronous functions and could be the unintentional result of refactoring.
+
 
 ## Rule Details
 
@@ -47,7 +64,22 @@ async function noop() {}
 
 ## When Not To Use It
 
-If you don't want to notify async functions which have no `await` expression, then it's safe to disable this rule.
+Asynchronous functions are designed to work with promises such that throwing an error will cause a promise's rejection handler (such as `catch()`) to be called. For example:
+
+```js
+async function fail() {
+    throw new Error("Failure!");
+}
+
+fail().catch(error => {
+    console.log(error.message);
+});
+```
+
+In this case, the `fail()` function throws an error that is intended to be caught by the `catch()` handler assigned later. Converting the `fail()` function into a synchronous function would require the call to `fail()` to be refactored to use a `try-catch` statement instead of a promise.
+
+If you are throwing an error inside of an asynchronous function for this purpose, then you may want to disable this rule.
+
 
 ## Related Rules
 
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.
         {