Skip to content

Commit

Permalink
Compute block scope declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
captain-yossarian committed Dec 27, 2018
1 parent 0772a0a commit 0b3a3a4
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 34 deletions.
66 changes: 34 additions & 32 deletions lib/rules/no-else-return.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,8 @@ const FixTracker = require("../util/fix-tracker");
// Helpers
//------------------------------------------------------------------------------

/**
* @param {Token} token - The token to check
* @returns {boolean} `true` if keyword let or const exist
*/
function isVariableDeclaration(token) {
const variableDeclaration = token.value === "let" || token.value === "const";
const BLOCK_SCOPED_DECLARATION = /^(?:VariableDeclarator|ClassDeclaration)$/;

return token.type === "Keyword" && variableDeclaration;
}

//------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -104,31 +97,40 @@ module.exports = {
const endToken = sourceCode.getLastToken(node);

/**
* If else block includes block scope local variable declaration [let or const],
* then it is not safe to remove else keyword [issue 11069]
* Dig into `else` branch and receive all root level declarations.
* Checks only if @var foo is block scope declaration, @not @var x
* @example
* function foo (){
* if(baz){
* return 42
* } else {
* let foo=1;
* {
* const x=10;
* }
* return foo
* }
* }
*
*/
const isDeclarationInside = sourceCode.getTokensBetween(startToken, endToken).findIndex(isVariableDeclaration) > -1;

const childScopeVars = (childScopes, store = {}, level = 0) =>
childScopes.reduce((acc, block) => {
if (block.childScopes.length >= 0) {
acc[level] = block.variables;
let index = level + 1
return childScopeVars(block.childScopes, acc, index);
}
return acc
}, store)

const shadowedVariables = scope => {
const result = childScopeVars(scope.childScopes);
return scope.variables.filter(elem => result[0].findIndex(vars => vars.name === elem.name) > -1)
};
const shadowed = shadowedVariables(context.getScope());
console.log('test', shadowed)

if (isDeclarationInside) {
return null;
}
const blockScopeDeclaration = scope => {
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

});
};

if (blockScopeDeclaration(context.getScope())) {
return null;
}

const lastTokenOfElseBlock = sourceCode.getTokenBefore(endToken);

Expand Down
4 changes: 2 additions & 2 deletions tests/lib/rules/no-else-return.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ ruleTester.run("no-else-return", rule, {
errors: [{ messageId: "unexpected", type: "BlockStatement" }]
},
{
code: "function foo() { let bar = true; if (baz) { return; } else { { let bar = false; } return; } }",
output: null,
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" }
Expand Down

0 comments on commit 0b3a3a4

Please sign in to comment.