| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 | 
							- /**
 
-  * @fileoverview Checks for unreachable code due to return, throws, break, and continue.
 
-  * @author Joel Feenstra
 
-  */
 
- "use strict";
 
- //------------------------------------------------------------------------------
 
- // Helpers
 
- //------------------------------------------------------------------------------
 
- /**
 
-  * Checks whether or not a given variable declarator has the initializer.
 
-  * @param {ASTNode} node A VariableDeclarator node to check.
 
-  * @returns {boolean} `true` if the node has the initializer.
 
-  */
 
- function isInitialized(node) {
 
-     return Boolean(node.init);
 
- }
 
- /**
 
-  * Checks whether or not a given code path segment is unreachable.
 
-  * @param {CodePathSegment} segment A CodePathSegment to check.
 
-  * @returns {boolean} `true` if the segment is unreachable.
 
-  */
 
- function isUnreachable(segment) {
 
-     return !segment.reachable;
 
- }
 
- /**
 
-  * The class to distinguish consecutive unreachable statements.
 
-  */
 
- class ConsecutiveRange {
 
-     constructor(sourceCode) {
 
-         this.sourceCode = sourceCode;
 
-         this.startNode = null;
 
-         this.endNode = null;
 
-     }
 
-     /**
 
-      * The location object of this range.
 
-      * @type {Object}
 
-      */
 
-     get location() {
 
-         return {
 
-             start: this.startNode.loc.start,
 
-             end: this.endNode.loc.end
 
-         };
 
-     }
 
-     /**
 
-      * `true` if this range is empty.
 
-      * @type {boolean}
 
-      */
 
-     get isEmpty() {
 
-         return !(this.startNode && this.endNode);
 
-     }
 
-     /**
 
-      * Checks whether the given node is inside of this range.
 
-      * @param {ASTNode|Token} node The node to check.
 
-      * @returns {boolean} `true` if the node is inside of this range.
 
-      */
 
-     contains(node) {
 
-         return (
 
-             node.range[0] >= this.startNode.range[0] &&
 
-             node.range[1] <= this.endNode.range[1]
 
-         );
 
-     }
 
-     /**
 
-      * Checks whether the given node is consecutive to this range.
 
-      * @param {ASTNode} node The node to check.
 
-      * @returns {boolean} `true` if the node is consecutive to this range.
 
-      */
 
-     isConsecutive(node) {
 
-         return this.contains(this.sourceCode.getTokenBefore(node));
 
-     }
 
-     /**
 
-      * Merges the given node to this range.
 
-      * @param {ASTNode} node The node to merge.
 
-      * @returns {void}
 
-      */
 
-     merge(node) {
 
-         this.endNode = node;
 
-     }
 
-     /**
 
-      * Resets this range by the given node or null.
 
-      * @param {ASTNode|null} node The node to reset, or null.
 
-      * @returns {void}
 
-      */
 
-     reset(node) {
 
-         this.startNode = this.endNode = node;
 
-     }
 
- }
 
- //------------------------------------------------------------------------------
 
- // Rule Definition
 
- //------------------------------------------------------------------------------
 
- module.exports = {
 
-     meta: {
 
-         type: "problem",
 
-         docs: {
 
-             description: "disallow unreachable code after `return`, `throw`, `continue`, and `break` statements",
 
-             category: "Possible Errors",
 
-             recommended: true,
 
-             url: "https://eslint.org/docs/rules/no-unreachable"
 
-         },
 
-         schema: [],
 
-         messages: {
 
-             unreachableCode: "Unreachable code."
 
-         }
 
-     },
 
-     create(context) {
 
-         let currentCodePath = null;
 
-         const range = new ConsecutiveRange(context.getSourceCode());
 
-         /**
 
-          * Reports a given node if it's unreachable.
 
-          * @param {ASTNode} node A statement node to report.
 
-          * @returns {void}
 
-          */
 
-         function reportIfUnreachable(node) {
 
-             let nextNode = null;
 
-             if (node && currentCodePath.currentSegments.every(isUnreachable)) {
 
-                 // Store this statement to distinguish consecutive statements.
 
-                 if (range.isEmpty) {
 
-                     range.reset(node);
 
-                     return;
 
-                 }
 
-                 // Skip if this statement is inside of the current range.
 
-                 if (range.contains(node)) {
 
-                     return;
 
-                 }
 
-                 // Merge if this statement is consecutive to the current range.
 
-                 if (range.isConsecutive(node)) {
 
-                     range.merge(node);
 
-                     return;
 
-                 }
 
-                 nextNode = node;
 
-             }
 
-             /*
 
-              * Report the current range since this statement is reachable or is
 
-              * not consecutive to the current range.
 
-              */
 
-             if (!range.isEmpty) {
 
-                 context.report({
 
-                     messageId: "unreachableCode",
 
-                     loc: range.location,
 
-                     node: range.startNode
 
-                 });
 
-             }
 
-             // Update the current range.
 
-             range.reset(nextNode);
 
-         }
 
-         return {
 
-             // Manages the current code path.
 
-             onCodePathStart(codePath) {
 
-                 currentCodePath = codePath;
 
-             },
 
-             onCodePathEnd() {
 
-                 currentCodePath = currentCodePath.upper;
 
-             },
 
-             // Registers for all statement nodes (excludes FunctionDeclaration).
 
-             BlockStatement: reportIfUnreachable,
 
-             BreakStatement: reportIfUnreachable,
 
-             ClassDeclaration: reportIfUnreachable,
 
-             ContinueStatement: reportIfUnreachable,
 
-             DebuggerStatement: reportIfUnreachable,
 
-             DoWhileStatement: reportIfUnreachable,
 
-             ExpressionStatement: reportIfUnreachable,
 
-             ForInStatement: reportIfUnreachable,
 
-             ForOfStatement: reportIfUnreachable,
 
-             ForStatement: reportIfUnreachable,
 
-             IfStatement: reportIfUnreachable,
 
-             ImportDeclaration: reportIfUnreachable,
 
-             LabeledStatement: reportIfUnreachable,
 
-             ReturnStatement: reportIfUnreachable,
 
-             SwitchStatement: reportIfUnreachable,
 
-             ThrowStatement: reportIfUnreachable,
 
-             TryStatement: reportIfUnreachable,
 
-             VariableDeclaration(node) {
 
-                 if (node.kind !== "var" || node.declarations.some(isInitialized)) {
 
-                     reportIfUnreachable(node);
 
-                 }
 
-             },
 
-             WhileStatement: reportIfUnreachable,
 
-             WithStatement: reportIfUnreachable,
 
-             ExportNamedDeclaration: reportIfUnreachable,
 
-             ExportDefaultDeclaration: reportIfUnreachable,
 
-             ExportAllDeclaration: reportIfUnreachable,
 
-             "Program:exit"() {
 
-                 reportIfUnreachable();
 
-             }
 
-         };
 
-     }
 
- };
 
 
  |