3f175dc78b63063db51b4ae3ea746a6055196773
[platform/framework/web/crosswalk-tizen.git] /
1 /**
2  * @fileoverview Rule to flag use of variables before they are defined
3  * @author Ilya Volodin
4  * @copyright 2013 Ilya Volodin. All rights reserved.
5  */
6
7 "use strict";
8
9 //------------------------------------------------------------------------------
10 // Constants
11 //------------------------------------------------------------------------------
12
13 var NO_FUNC = "nofunc";
14
15 //------------------------------------------------------------------------------
16 // Rule Definition
17 //------------------------------------------------------------------------------
18
19 module.exports = function(context) {
20
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];
26             }
27         }
28         // check if there's upper scope and call recursivly till we find the variable
29         if (scope.upper) {
30             return findDeclaration(name, scope.upper);
31         }
32     }
33
34     function findVariables() {
35         var scope = context.getScope();
36         var typeOption = context.options[0];
37
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});
42                 }
43             }
44         }
45
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);
51             } else {
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);
56                 }
57             }
58         });
59     }
60
61     return {
62         "Program": findVariables,
63         "FunctionExpression": findVariables,
64         "FunctionDeclaration": findVariables,
65         "ArrowFunctionExpression": findVariables
66     };
67 };