UNPKG

2.75 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to check for "block scoped" variables by binding context
3 * @author Matt DuVall <http://www.mattduvall.com>
4 */
5"use strict";
6
7//------------------------------------------------------------------------------
8// Rule Definition
9//------------------------------------------------------------------------------
10
11module.exports = function(context) {
12
13 var stack = [{}]; // Start with the global block
14
15 //--------------------------------------------------------------------------
16 // Helpers
17 //--------------------------------------------------------------------------
18 function pushBlock() {
19 stack.push({});
20 }
21
22 function popBlock() {
23 stack.pop();
24 }
25
26 function hasAllowedAncestorsForCheck(ancestors) {
27 var grandparent = ancestors[ancestors.length - 1],
28 belongsToFunction = grandparent.type === "FunctionDeclaration";
29
30 return belongsToFunction;
31 }
32
33 function addCommonDeclaration(node) {
34 var type = node.type,
35 topObject = stack.pop(),
36 i,
37 len,
38 declarations;
39
40 switch (type) {
41 case "VariableDeclaration":
42 declarations = node.declarations;
43 for (i = 0, len = declarations.length; i < len; i++) {
44 topObject[declarations[i].id.name] = 1;
45 }
46 break;
47
48 case "FunctionDeclaration":
49 declarations = node.params;
50 topObject[node.id.name] = 1;
51 for (i = 0, len = declarations.length; i < len; i++) {
52 topObject[declarations[i].name] = 1;
53 }
54 break;
55
56 case "CatchClause":
57 declarations = [];
58 topObject[node.param.name] = 1;
59
60 // no default
61 }
62
63 stack.push(topObject);
64 }
65
66 function checkStackForIdentifier(node) {
67 var i,
68 len,
69 ancestors = context.getAncestors();
70
71 if (!hasAllowedAncestorsForCheck(ancestors)) {
72 for (i = 0, len = stack.length; i < len; i++) {
73 if (stack[i][node.name]) {
74 return;
75 }
76 }
77
78 context.report(node, node.name + " used outside of binding context.");
79 }
80 }
81
82 //--------------------------------------------------------------------------
83 // Public API
84 //--------------------------------------------------------------------------
85
86 return {
87 "BlockStatement": pushBlock,
88 "BlockStatement:exit": popBlock,
89 "CatchClause": addCommonDeclaration,
90 "VariableDeclaration": addCommonDeclaration,
91 "FunctionDeclaration": addCommonDeclaration,
92 "Identifier": checkStackForIdentifier
93 };
94
95};