.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-implicit-globals.js
1 /**
2  * @fileoverview Rule to check for implicit global variables, functions and classes.
3  * @author Joshua Peek
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Rule Definition
10 //------------------------------------------------------------------------------
11
12 module.exports = {
13     meta: {
14         type: "suggestion",
15
16         docs: {
17             description: "disallow declarations in the global scope",
18             category: "Best Practices",
19             recommended: false,
20             url: "https://eslint.org/docs/rules/no-implicit-globals"
21         },
22
23         schema: [{
24             type: "object",
25             properties: {
26                 lexicalBindings: {
27                     type: "boolean",
28                     default: false
29                 }
30             },
31             additionalProperties: false
32         }],
33
34         messages: {
35             globalNonLexicalBinding: "Unexpected {{kind}} declaration in the global scope, wrap in an IIFE for a local variable, assign as global property for a global variable.",
36             globalLexicalBinding: "Unexpected {{kind}} declaration in the global scope, wrap in a block or in an IIFE.",
37             globalVariableLeak: "Global variable leak, declare the variable if it is intended to be local.",
38             assignmentToReadonlyGlobal: "Unexpected assignment to read-only global variable.",
39             redeclarationOfReadonlyGlobal: "Unexpected redeclaration of read-only global variable."
40         }
41     },
42
43     create(context) {
44
45         const checkLexicalBindings = context.options[0] && context.options[0].lexicalBindings === true;
46
47         /**
48          * Reports the node.
49          * @param {ASTNode} node Node to report.
50          * @param {string} messageId Id of the message to report.
51          * @param {string|undefined} kind Declaration kind, can be 'var', 'const', 'let', function or class.
52          * @returns {void}
53          */
54         function report(node, messageId, kind) {
55             context.report({
56                 node,
57                 messageId,
58                 data: {
59                     kind
60                 }
61             });
62         }
63
64         return {
65             Program() {
66                 const scope = context.getScope();
67
68                 scope.variables.forEach(variable => {
69
70                     // Only ESLint global variables have the `writable` key.
71                     const isReadonlyEslintGlobalVariable = variable.writeable === false;
72                     const isWritableEslintGlobalVariable = variable.writeable === true;
73
74                     if (isWritableEslintGlobalVariable) {
75
76                         // Everything is allowed with writable ESLint global variables.
77                         return;
78                     }
79
80                     variable.defs.forEach(def => {
81                         const defNode = def.node;
82
83                         if (def.type === "FunctionName" || (def.type === "Variable" && def.parent.kind === "var")) {
84                             if (isReadonlyEslintGlobalVariable) {
85                                 report(defNode, "redeclarationOfReadonlyGlobal");
86                             } else {
87                                 report(
88                                     defNode,
89                                     "globalNonLexicalBinding",
90                                     def.type === "FunctionName" ? "function" : `'${def.parent.kind}'`
91                                 );
92                             }
93                         }
94
95                         if (checkLexicalBindings) {
96                             if (def.type === "ClassName" ||
97                                     (def.type === "Variable" && (def.parent.kind === "let" || def.parent.kind === "const"))) {
98                                 if (isReadonlyEslintGlobalVariable) {
99                                     report(defNode, "redeclarationOfReadonlyGlobal");
100                                 } else {
101                                     report(
102                                         defNode,
103                                         "globalLexicalBinding",
104                                         def.type === "ClassName" ? "class" : `'${def.parent.kind}'`
105                                     );
106                                 }
107                             }
108                         }
109                     });
110                 });
111
112                 // Undeclared assigned variables.
113                 scope.implicit.variables.forEach(variable => {
114                     const scopeVariable = scope.set.get(variable.name);
115                     let messageId;
116
117                     if (scopeVariable) {
118
119                         // ESLint global variable
120                         if (scopeVariable.writeable) {
121                             return;
122                         }
123                         messageId = "assignmentToReadonlyGlobal";
124
125                     } else {
126
127                         // Reference to an unknown variable, possible global leak.
128                         messageId = "globalVariableLeak";
129                     }
130
131                     // def.node is an AssignmentExpression, ForInStatement or ForOfStatement.
132                     variable.defs.forEach(def => {
133                         report(def.node, messageId);
134                     });
135                 });
136             }
137         };
138
139     }
140 };