2 * @fileoverview Rule to flag use of variables before they are defined
4 * @copyright 2013 Ilya Volodin. All rights reserved.
9 //------------------------------------------------------------------------------
11 //------------------------------------------------------------------------------
13 var NO_FUNC = "nofunc";
15 //------------------------------------------------------------------------------
17 //------------------------------------------------------------------------------
19 module.exports = function(context) {
21 function findDeclaration(name, scope) {
22 // try searching in the current scope first
23 for (var i = 0, l = scope.variables.length; i < l; i++) {
24 if (scope.variables[i].name === name) {
25 return scope.variables[i];
28 // check if there's upper scope and call recursivly till we find the variable
30 return findDeclaration(name, scope.upper);
34 function findVariables() {
35 var scope = context.getScope();
36 var typeOption = context.options[0];
38 function checkLocationAndReport(reference, declaration) {
39 if (typeOption !== NO_FUNC || declaration.defs[0].type !== "FunctionName") {
40 if (declaration.identifiers[0].range[1] > reference.identifier.range[1]) {
41 context.report(reference.identifier, "{{a}} was used before it was defined", {a: reference.identifier.name});
46 scope.references.forEach(function(reference) {
47 // if the reference is resolved check for declaration location
48 // if not, it could be function invocation, try to find manually
49 if (reference.resolved && reference.resolved.identifiers.length > 0) {
50 checkLocationAndReport(reference, reference.resolved);
52 var declaration = findDeclaration(reference.identifier.name, scope);
53 // if there're no identifiers, this is a global environment variable
54 if (declaration && declaration.identifiers.length !== 0) {
55 checkLocationAndReport(reference, declaration);
62 "Program": findVariables,
63 "FunctionExpression": findVariables,
64 "FunctionDeclaration": findVariables,
65 "ArrowFunctionExpression": findVariables