UNPKG

3.14 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to flag when the same variable is declared more then once.
3 * @author Ilya Volodin
4 */
5
6"use strict";
7
8//------------------------------------------------------------------------------
9// Rule Definition
10//------------------------------------------------------------------------------
11
12module.exports = {
13 meta: {
14 docs: {
15 description: "disallow variable redeclaration",
16 category: "Best Practices",
17 recommended: true
18 },
19
20 schema: [
21 {
22 type: "object",
23 properties: {
24 builtinGlobals: { type: "boolean" }
25 },
26 additionalProperties: false
27 }
28 ]
29 },
30
31 create(context) {
32 const options = {
33 builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals)
34 };
35
36 /**
37 * Find variables in a given scope and flag redeclared ones.
38 * @param {Scope} scope - An eslint-scope scope object.
39 * @returns {void}
40 * @private
41 */
42 function findVariablesInScope(scope) {
43 scope.variables.forEach(variable => {
44 const hasBuiltin = options.builtinGlobals && "writeable" in variable;
45 const count = (hasBuiltin ? 1 : 0) + variable.identifiers.length;
46
47 if (count >= 2) {
48 variable.identifiers.sort((a, b) => a.range[1] - b.range[1]);
49
50 for (let i = (hasBuiltin ? 0 : 1), l = variable.identifiers.length; i < l; i++) {
51 context.report({ node: variable.identifiers[i], message: "'{{a}}' is already defined.", data: { a: variable.name } });
52 }
53 }
54 });
55
56 }
57
58 /**
59 * Find variables in the current scope.
60 * @param {ASTNode} node - The Program node.
61 * @returns {void}
62 * @private
63 */
64 function checkForGlobal(node) {
65 const scope = context.getScope(),
66 parserOptions = context.parserOptions,
67 ecmaFeatures = parserOptions.ecmaFeatures || {};
68
69 // Nodejs env or modules has a special scope.
70 if (ecmaFeatures.globalReturn || node.sourceType === "module") {
71 findVariablesInScope(scope.childScopes[0]);
72 } else {
73 findVariablesInScope(scope);
74 }
75 }
76
77 /**
78 * Find variables in the current scope.
79 * @returns {void}
80 * @private
81 */
82 function checkForBlock() {
83 findVariablesInScope(context.getScope());
84 }
85
86 if (context.parserOptions.ecmaVersion >= 6) {
87 return {
88 Program: checkForGlobal,
89 BlockStatement: checkForBlock,
90 SwitchStatement: checkForBlock
91 };
92 }
93 return {
94 Program: checkForGlobal,
95 FunctionDeclaration: checkForBlock,
96 FunctionExpression: checkForBlock,
97 ArrowFunctionExpression: checkForBlock
98 };
99
100 }
101};