diff options
Diffstat (limited to 'tools/eslint/lib/rules/no-use-before-define.js')
-rw-r--r-- | tools/eslint/lib/rules/no-use-before-define.js | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/tools/eslint/lib/rules/no-use-before-define.js b/tools/eslint/lib/rules/no-use-before-define.js new file mode 100644 index 0000000000..3f175dc78b --- /dev/null +++ b/tools/eslint/lib/rules/no-use-before-define.js @@ -0,0 +1,67 @@ +/** + * @fileoverview Rule to flag use of variables before they are defined + * @author Ilya Volodin + * @copyright 2013 Ilya Volodin. All rights reserved. + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Constants +//------------------------------------------------------------------------------ + +var NO_FUNC = "nofunc"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = function(context) { + + function findDeclaration(name, scope) { + // try searching in the current scope first + for (var i = 0, l = scope.variables.length; i < l; i++) { + if (scope.variables[i].name === name) { + return scope.variables[i]; + } + } + // check if there's upper scope and call recursivly till we find the variable + if (scope.upper) { + return findDeclaration(name, scope.upper); + } + } + + function findVariables() { + var scope = context.getScope(); + var typeOption = context.options[0]; + + function checkLocationAndReport(reference, declaration) { + if (typeOption !== NO_FUNC || declaration.defs[0].type !== "FunctionName") { + if (declaration.identifiers[0].range[1] > reference.identifier.range[1]) { + context.report(reference.identifier, "{{a}} was used before it was defined", {a: reference.identifier.name}); + } + } + } + + scope.references.forEach(function(reference) { + // if the reference is resolved check for declaration location + // if not, it could be function invocation, try to find manually + if (reference.resolved && reference.resolved.identifiers.length > 0) { + checkLocationAndReport(reference, reference.resolved); + } else { + var declaration = findDeclaration(reference.identifier.name, scope); + // if there're no identifiers, this is a global environment variable + if (declaration && declaration.identifiers.length !== 0) { + checkLocationAndReport(reference, declaration); + } + } + }); + } + + return { + "Program": findVariables, + "FunctionExpression": findVariables, + "FunctionDeclaration": findVariables, + "ArrowFunctionExpression": findVariables + }; +}; |