a9f2858126b4b383709a50c1df8e0b8ee9fcfc78
[platform/framework/web/crosswalk-tizen.git] /
1 /**
2  * @fileoverview Rule to flag use of function declaration identifiers as variables.
3  * @author Ian Christian Myers
4  * @copyright 2013 Ian Christian Myers. All rights reserved.
5  */
6
7 "use strict";
8
9 //------------------------------------------------------------------------------
10 // Rule Definition
11 //------------------------------------------------------------------------------
12
13 module.exports = function(context) {
14
15     //--------------------------------------------------------------------------
16     // Helpers
17     //--------------------------------------------------------------------------
18
19     /*
20      * Walk the scope chain looking for either a FunctionDeclaration or a
21      * VariableDeclaration with the same name as left-hand side of the
22      * AssignmentExpression. If we find the FunctionDeclaration first, then we
23      * warn, because a FunctionDeclaration is trying to become a Variable or a
24      * FunctionExpression. If we find a VariableDeclaration first, then we have
25      * a legitimate shadow variable.
26      */
27     function checkIfIdentifierIsFunction(scope, name) {
28         var variable,
29             def,
30             i,
31             j;
32
33         // Loop over all of the identifiers available in scope.
34         for (i = 0; i < scope.variables.length; i++) {
35             variable = scope.variables[i];
36
37             // For each identifier, see if it was defined in _this_ scope.
38             for (j = 0; j < variable.defs.length; j++) {
39                 def = variable.defs[j];
40
41                 // Identifier is a function and was declared in this scope
42                 if (def.type === "FunctionName" && def.name.name === name) {
43                     return true;
44                 }
45
46                 // Identifier is a variable and was declared in this scope. This
47                 // is a legitimate shadow variable.
48                 if (def.name && def.name.name === name) {
49                     return false;
50                 }
51             }
52         }
53
54         // Check the upper scope.
55         if (scope.upper) {
56             return checkIfIdentifierIsFunction(scope.upper, name);
57         }
58
59         // We've reached the global scope and haven't found anything.
60         return false;
61     }
62
63     //--------------------------------------------------------------------------
64     // Public API
65     //--------------------------------------------------------------------------
66
67     return {
68
69         "AssignmentExpression": function(node) {
70             var scope = context.getScope(),
71                 name = node.left.name;
72
73             if (checkIfIdentifierIsFunction(scope, name)) {
74                 context.report(node, "'{{name}}' is a function.", { name: name });
75             }
76
77         }
78
79     };
80
81 };