.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-redeclare.js
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 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Rule Definition
16 //------------------------------------------------------------------------------
17
18 module.exports = {
19     meta: {
20         type: "suggestion",
21
22         docs: {
23             description: "disallow variable redeclaration",
24             category: "Best Practices",
25             recommended: true,
26             url: "https://eslint.org/docs/rules/no-redeclare"
27         },
28
29         messages: {
30             redeclared: "'{{id}}' is already defined.",
31             redeclaredAsBuiltin: "'{{id}}' is already defined as a built-in global variable.",
32             redeclaredBySyntax: "'{{id}}' is already defined by a variable declaration."
33         },
34
35         schema: [
36             {
37                 type: "object",
38                 properties: {
39                     builtinGlobals: { type: "boolean", default: true }
40                 },
41                 additionalProperties: false
42             }
43         ]
44     },
45
46     create(context) {
47         const options = {
48             builtinGlobals: Boolean(
49                 context.options.length === 0 ||
50                 context.options[0].builtinGlobals
51             )
52         };
53         const sourceCode = context.getSourceCode();
54
55         /**
56          * Iterate declarations of a given variable.
57          * @param {escope.variable} variable The variable object to iterate declarations.
58          * @returns {IterableIterator<{type:string,node:ASTNode,loc:SourceLocation}>} The declarations.
59          */
60         function *iterateDeclarations(variable) {
61             if (options.builtinGlobals && (
62                 variable.eslintImplicitGlobalSetting === "readonly" ||
63                 variable.eslintImplicitGlobalSetting === "writable"
64             )) {
65                 yield { type: "builtin" };
66             }
67
68             for (const id of variable.identifiers) {
69                 yield { type: "syntax", node: id, loc: id.loc };
70             }
71
72             if (variable.eslintExplicitGlobalComments) {
73                 for (const comment of variable.eslintExplicitGlobalComments) {
74                     yield {
75                         type: "comment",
76                         node: comment,
77                         loc: astUtils.getNameLocationInGlobalDirectiveComment(
78                             sourceCode,
79                             comment,
80                             variable.name
81                         )
82                     };
83                 }
84             }
85         }
86
87         /**
88          * Find variables in a given scope and flag redeclared ones.
89          * @param {Scope} scope An eslint-scope scope object.
90          * @returns {void}
91          * @private
92          */
93         function findVariablesInScope(scope) {
94             for (const variable of scope.variables) {
95                 const [
96                     declaration,
97                     ...extraDeclarations
98                 ] = iterateDeclarations(variable);
99
100                 if (extraDeclarations.length === 0) {
101                     continue;
102                 }
103
104                 /*
105                  * If the type of a declaration is different from the type of
106                  * the first declaration, it shows the location of the first
107                  * declaration.
108                  */
109                 const detailMessageId = declaration.type === "builtin"
110                     ? "redeclaredAsBuiltin"
111                     : "redeclaredBySyntax";
112                 const data = { id: variable.name };
113
114                 // Report extra declarations.
115                 for (const { type, node, loc } of extraDeclarations) {
116                     const messageId = type === declaration.type
117                         ? "redeclared"
118                         : detailMessageId;
119
120                     context.report({ node, loc, messageId, data });
121                 }
122             }
123         }
124
125         /**
126          * Find variables in the current scope.
127          * @param {ASTNode} node The node of the current scope.
128          * @returns {void}
129          * @private
130          */
131         function checkForBlock(node) {
132             const scope = context.getScope();
133
134             /*
135              * In ES5, some node type such as `BlockStatement` doesn't have that scope.
136              * `scope.block` is a different node in such a case.
137              */
138             if (scope.block === node) {
139                 findVariablesInScope(scope);
140             }
141         }
142
143         return {
144             Program() {
145                 const scope = context.getScope();
146
147                 findVariablesInScope(scope);
148
149                 // Node.js or ES modules has a special scope.
150                 if (
151                     scope.type === "global" &&
152                     scope.childScopes[0] &&
153
154                     // The special scope's block is the Program node.
155                     scope.block === scope.childScopes[0].block
156                 ) {
157                     findVariablesInScope(scope.childScopes[0]);
158                 }
159             },
160
161             FunctionDeclaration: checkForBlock,
162             FunctionExpression: checkForBlock,
163             ArrowFunctionExpression: checkForBlock,
164
165             BlockStatement: checkForBlock,
166             ForStatement: checkForBlock,
167             ForInStatement: checkForBlock,
168             ForOfStatement: checkForBlock,
169             SwitchStatement: checkForBlock
170         };
171     }
172 };