UNPKG

3.12 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to check for "block scoped" variables by binding context
3 * @author Matt DuVall <http://www.mattduvall.com>
4 * @copyright 2015 Toru Nagashima. All rights reserved.
5 * @copyright 2015 Mathieu M-Gosselin. All rights reserved.
6 */
7"use strict";
8
9//------------------------------------------------------------------------------
10// Rule Definition
11//------------------------------------------------------------------------------
12
13module.exports = function(context) {
14 var stack = [];
15
16 /**
17 * Makes a block scope.
18 * @param {ASTNode} node - A node of a scope.
19 * @returns {void}
20 */
21 function enterScope(node) {
22 stack.push(node.range);
23 }
24
25 /**
26 * Pops the last block scope.
27 * @returns {void}
28 */
29 function exitScope() {
30 stack.pop();
31 }
32
33 /**
34 * Reports a given reference.
35 * @param {escope.Reference} reference - A reference to report.
36 * @returns {void}
37 */
38 function report(reference) {
39 var identifier = reference.identifier;
40 context.report(
41 identifier,
42 "'{{name}}' used outside of binding context.",
43 {name: identifier.name});
44 }
45
46 /**
47 * Finds and reports references which are outside of valid scopes.
48 * @param {ASTNode} node - A node to get variables.
49 * @returns {void}
50 */
51 function checkForVariables(node) {
52 if (node.kind !== "var") {
53 return;
54 }
55
56 // Defines a predicate to check whether or not a given reference is outside of valid scope.
57 var scopeRange = stack[stack.length - 1];
58
59 /**
60 * Check if a reference is out of scope
61 * @param {ASTNode} reference node to examine
62 * @returns {boolean} True is its outside the scope
63 * @private
64 */
65 function isOutsideOfScope(reference) {
66 var idRange = reference.identifier.range;
67 return idRange[0] < scopeRange[0] || idRange[1] > scopeRange[1];
68 }
69
70 // Gets declared variables, and checks its references.
71 var variables = context.getDeclaredVariables(node);
72 for (var i = 0; i < variables.length; ++i) {
73 // Reports.
74 variables[i]
75 .references
76 .filter(isOutsideOfScope)
77 .forEach(report);
78 }
79 }
80
81 return {
82 "Program": function(node) {
83 stack = [node.range];
84 },
85
86 // Manages scopes.
87 "BlockStatement": enterScope,
88 "BlockStatement:exit": exitScope,
89 "ForStatement": enterScope,
90 "ForStatement:exit": exitScope,
91 "ForInStatement": enterScope,
92 "ForInStatement:exit": exitScope,
93 "ForOfStatement": enterScope,
94 "ForOfStatement:exit": exitScope,
95 "SwitchStatement": enterScope,
96 "SwitchStatement:exit": exitScope,
97 "CatchClause": enterScope,
98 "CatchClause:exit": exitScope,
99
100 // Finds and reports references which are outside of valid scope.
101 "VariableDeclaration": checkForVariables
102 };
103
104};
105
106module.exports.schema = [];