Repository: eslint/eslint (JavaScript)

Issue:
False positive no-unreachable catch in generator 
The `no-unreachable` rule does not understand that `yield` can throw an error an report an error.

Here is small repro:

```js
/*eslint no-unreachable: "error"*/

function* generator() {
  try {
    yield 1;
    yield 2;
    return 3;
  } catch (err) { // eslint warn about the catch being unreachable
    return err;
  }
}

var gen = generator();
gen.throw(5) // this will run the code in the catch
```

[Online demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgbm8tdW5yZWFjaGFibGU6IFwiZXJyb3JcIiovXG5cbmZ1bmN0aW9uKiBnZW5lcmF0b3IoKSB7XG4gIHRyeSB7XG4gICAgeWllbGQgMTtcbiAgICB5aWVsZCAyO1xuICAgIHJldHVybiAzO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4gZXJyO1xuICB9XG59XG5cbnZhciBnZW4gPSBnZW5lcmF0b3IoKTtcbi8vIHJlYWNoIHRoZSB1bnJlYWNoYWJsZSA/XG5nZW4udGhyb3coNSlcbiIsIm9wdGlvbnMiOnsicGFyc2VyT3B0aW9ucyI6eyJlY21hVmVyc2lvbiI6MTEsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnsianN4Ijp0cnVlfX0sInJ1bGVzIjp7fSwiZW52Ijp7ImJyb3dzZXIiOmZhbHNlfX19)



Discussion:
Thanks for reporting this. Agreed that this is a bug. Documentation describing this behavior can be found [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw).



Patch:
diff --git a/lib/linter/code-path-analysis/code-path-analyzer.js b/lib/linter/code-path-analysis/code-path-analyzer.js
index 6822ae2be0a6..8a623e33ea06 100644
--- a/lib/linter/code-path-analysis/code-path-analyzer.js
+++ b/lib/linter/code-path-analysis/code-path-analyzer.js
@@ -518,6 +518,7 @@ function processCodePathToExit(analyzer, node) {
         case "ImportExpression":
         case "MemberExpression":
         case "NewExpression":
+        case "YieldExpression":
             state.makeFirstThrowablePathInTryBlock();
             break;
 


Test patch:
diff --git a/tests/lib/rules/no-unreachable.js b/tests/lib/rules/no-unreachable.js
index 1e3f71161268..e1609c8a8119 100644
--- a/tests/lib/rules/no-unreachable.js
+++ b/tests/lib/rules/no-unreachable.js
@@ -47,7 +47,25 @@ ruleTester.run("no-unreachable", rule, {
         "function foo() { var x = 1; for (x in {}) { return; } x = 2; }",
         "function foo() { var x = 1; try { return; } finally { x = 2; } }",
         "function foo() { var x = 1; for (;;) { if (x) break; } x = 2; }",
-        "A: { break A; } foo()"
+        "A: { break A; } foo()",
+        {
+            code: "function* foo() { try { yield 1; return; } catch (err) { return err; } }",
+            parserOptions: {
+                ecmaVersion: 6
+            }
+        },
+        {
+            code: "function foo() { try { bar(); return; } catch (err) { return err; } }",
+            parserOptions: {
+                ecmaVersion: 6
+            }
+        },
+        {
+            code: "function foo() { try { a.b.c = 1; return; } catch (err) { return err; } }",
+            parserOptions: {
+                ecmaVersion: 6
+            }
+        }
     ],
     invalid: [
         { code: "function foo() { return x; var x = 1; }", errors: [{ messageId: "unreachableCode", type: "VariableDeclaration" }] },
@@ -206,6 +224,84 @@ ruleTester.run("no-unreachable", rule, {
                     endColumn: 25
                 }
             ]
+        },
+        {
+            code: `
+                function* foo() {
+                    try {
+                        return;
+                    } catch (err) {
+                        return err;
+                    }
+                }`,
+            parserOptions: {
+                ecmaVersion: 6
+            },
+            errors: [
+                {
+                    messageId: "unreachableCode",
+                    type: "BlockStatement",
+                    line: 5,
+                    column: 35,
+                    endLine: 7,
+                    endColumn: 22
+                }
+            ]
+        },
+        {
+            code: `
+                function foo() {
+                    try {
+                        return;
+                    } catch (err) {
+                        return err;
+                    }
+                }`,
+            parserOptions: {
+                ecmaVersion: 6
+            },
+            errors: [
+                {
+                    messageId: "unreachableCode",
+                    type: "BlockStatement",
+                    line: 5,
+                    column: 35,
+                    endLine: 7,
+                    endColumn: 22
+                }
+            ]
+        },
+        {
+            code: `
+                function foo() {
+                    try {
+                        return;
+                        let a = 1;
+                    } catch (err) {
+                        return err;
+                    }
+                }`,
+            parserOptions: {
+                ecmaVersion: 6
+            },
+            errors: [
+                {
+                    messageId: "unreachableCode",
+                    type: "VariableDeclaration",
+                    line: 5,
+                    column: 25,
+                    endLine: 5,
+                    endColumn: 35
+                },
+                {
+                    messageId: "unreachableCode",
+                    type: "BlockStatement",
+                    line: 6,
+                    column: 35,
+                    endLine: 8,
+                    endColumn: 22
+                }
+            ]
         }
     ]
 });