diff --git a/lib/rules/no-else-return.js b/lib/rules/no-else-return.js index eebdec76e0e..484413066ef 100644 --- a/lib/rules/no-else-return.js +++ b/lib/rules/no-else-return.js @@ -12,6 +12,35 @@ const astUtils = require("../util/ast-utils"); const FixTracker = require("../util/fix-tracker"); +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const BLOCK_SCOPED_DECLARATION = /^(?:VariableDeclarator|ClassDeclaration)$/; + +/** + * + * @param {*} scope current scope + * @param {Token} startToken s + * @param {Token} endToken s + * @returns {boolean} s + */ +function blockScopeDeclaration(scope, startToken, endToken) { + + return scope.childScopes.some(childScope => { + const { + start, + end + } = childScope.block; + + const elseBranch = + start === startToken.start && end === endToken.end; + + return elseBranch ? childScope.variables.some(variable => BLOCK_SCOPED_DECLARATION.test(variable.defs[0].node.type)) : false; + }); +} + + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -88,6 +117,11 @@ module.exports = { } const endToken = sourceCode.getLastToken(node); + + if (blockScopeDeclaration(context.getScope(), startToken, endToken)) { + return null; + } + const lastTokenOfElseBlock = sourceCode.getTokenBefore(endToken); if (lastTokenOfElseBlock.value !== ";") { diff --git a/tests/lib/rules/no-else-return.js b/tests/lib/rules/no-else-return.js index 6111b55da65..a3b2fb6b156 100644 --- a/tests/lib/rules/no-else-return.js +++ b/tests/lib/rules/no-else-return.js @@ -182,6 +182,32 @@ ruleTester.run("no-else-return", rule, { output: "function foo21() { var x = true; if (x) { return x; } if (x === false) { return false; } }", options: [{ allowElseIf: false }], errors: [{ messageId: "unexpected", type: "IfStatement" }] + }, + { + code: "function foo() { if (true) { return bar; } else { const baz = 1; return baz; } }", + output: null, + parserOptions: { ecmaVersion: 6 }, + errors: [{ messageId: "unexpected", type: "BlockStatement" }] + }, + { + code: "function foo() { if (true) { return bar; } else { let baz = 1; return baz; } }", + output: null, + parserOptions: { ecmaVersion: 6 }, + errors: [{ messageId: "unexpected", type: "BlockStatement" }] + }, + { + code: "function foo() { let bar = true; if (baz) { return; } else { let bar = false; return; } }", + output: null, + parserOptions: { ecmaVersion: 6 }, + errors: [{ messageId: "unexpected", type: "BlockStatement" }] + }, + { + code: "function foo() { let bar = true; if (baz) { return baz; } else { { let bar = false; } return bar; } }", + output: "function foo() { let bar = true; if (baz) { return baz; } { let bar = false; } return bar; }", + parserOptions: { ecmaVersion: 6 }, + errors: [ + { messageId: "unexpected", type: "BlockStatement" } + ] } ] });