/** * @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 }; };