UNPKG

3.2 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 url: "https://eslint.org/docs/rules/no-redeclare"
19 },
20
21 schema: [
22 {
23 type: "object",
24 properties: {
25 builtinGlobals: { type: "boolean" }
26 },
27 additionalProperties: false
28 }
29 ]
30 },
31
32 create(context) {
33 const options = {
34 builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals)
35 };
36
37 /**
38 * Find variables in a given scope and flag redeclared ones.
39 * @param {Scope} scope - An eslint-scope scope object.
40 * @returns {void}
41 * @private
42 */
43 function findVariablesInScope(scope) {
44 scope.variables.forEach(variable => {
45 const hasBuiltin = options.builtinGlobals && "writeable" in variable;
46 const count = (hasBuiltin ? 1 : 0) + variable.identifiers.length;
47
48 if (count >= 2) {
49 variable.identifiers.sort((a, b) => a.range[1] - b.range[1]);
50
51 for (let i = (hasBuiltin ? 0 : 1), l = variable.identifiers.length; i < l; i++) {
52 context.report({ node: variable.identifiers[i], message: "'{{a}}' is already defined.", data: { a: variable.name } });
53 }
54 }
55 });
56
57 }
58
59 /**
60 * Find variables in the current scope.
61 * @param {ASTNode} node - The Program node.
62 * @returns {void}
63 * @private
64 */
65 function checkForGlobal(node) {
66 const scope = context.getScope(),
67 parserOptions = context.parserOptions,
68 ecmaFeatures = parserOptions.ecmaFeatures || {};
69
70 // Nodejs env or modules has a special scope.
71 if (ecmaFeatures.globalReturn || node.sourceType === "module") {
72 findVariablesInScope(scope.childScopes[0]);
73 } else {
74 findVariablesInScope(scope);
75 }
76 }
77
78 /**
79 * Find variables in the current scope.
80 * @returns {void}
81 * @private
82 */
83 function checkForBlock() {
84 findVariablesInScope(context.getScope());
85 }
86
87 if (context.parserOptions.ecmaVersion >= 6) {
88 return {
89 Program: checkForGlobal,
90 BlockStatement: checkForBlock,
91 SwitchStatement: checkForBlock
92 };
93 }
94 return {
95 Program: checkForGlobal,
96 FunctionDeclaration: checkForBlock,
97 FunctionExpression: checkForBlock,
98 ArrowFunctionExpression: checkForBlock
99 };
100
101 }
102};