Skip to content

Instantly share code, notes, and snippets.

@not-an-aardvark
Created September 8, 2017 23:43
Show Gist options
  • Save not-an-aardvark/e7cc13acbb593f402035b587aab226ec to your computer and use it in GitHub Desktop.
Save not-an-aardvark/e7cc13acbb593f402035b587aab226ec to your computer and use it in GitHub Desktop.
"use strict";
module.exports = {
meta: {
docs: {
description: "require variables to be declared in the smallest possible scope",
category: "Internal",
recommended: false
},
schema: []
},
create(context) {
return {
VariableDeclaration(node) {
const currentScope = context.getScope();
const childScopes = new Set(currentScope.childScopes);
const inScopeReferences = new Set(currentScope.references);
/**
* Gets the ancestor scope of a given scope which is in the child scopes of the current node
* @param {eslint-scope.Scope} scope The scope to get the ancestor of
* @returns {eslint-scope.Scope} The ancestor scope
*/
function getParent(scope) {
if (childScopes.has(scope)) {
return scope;
}
if (scope.upper) {
return getParent(scope.upper);
}
return null;
}
context.getDeclaredVariables(node)
.filter(
variable =>
variable.references.length &&
variable.references.every(ref => !inScopeReferences.has(ref)) &&
new Set(variable.references.map(ref => ref.from).map(getParent)).size === 1
)
.forEach(variable => {
context.report({
node: variable.defs[0].name,
message: "`{{name}}` can be declared in a smaller scope.",
data: variable.defs[0].name
});
});
}
};
}
};
"use strict";
const RuleTester = require("../../..").RuleTester;
const rule = require("../../../lib/internal-rules/prefer-smaller-scope");
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
ruleTester.run("prefer-smaller-scope", rule, {
valid: [
"let foo; foo = 1;",
"let foo;",
"let foo; { foo = 1; } foo = 2;",
"let foo; { foo = 1; } foo;",
"let foo; { foo = 1; } { foo; }"
],
invalid: [
{
code: "let foo; { foo = 1; }",
errors: [{ message: "`foo` can be declared in a smaller scope." }]
},
{
code: "let foo; { foo = 1; foo; }",
errors: [{ message: "`foo` can be declared in a smaller scope." }]
},
{
code: "let foo; { foo = 1; { foo; } }",
errors: [{ message: "`foo` can be declared in a smaller scope." }]
}
]
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment