.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-restricted-modules.js
1 /**
2  * @fileoverview Restrict usage of specified node modules.
3  * @author Christian Schulz
4  */
5 "use strict";
6
7 //------------------------------------------------------------------------------
8 // Rule Definition
9 //------------------------------------------------------------------------------
10
11 const ignore = require("ignore");
12
13 const arrayOfStrings = {
14     type: "array",
15     items: { type: "string" },
16     uniqueItems: true
17 };
18
19 const arrayOfStringsOrObjects = {
20     type: "array",
21     items: {
22         anyOf: [
23             { type: "string" },
24             {
25                 type: "object",
26                 properties: {
27                     name: { type: "string" },
28                     message: {
29                         type: "string",
30                         minLength: 1
31                     }
32                 },
33                 additionalProperties: false,
34                 required: ["name"]
35             }
36         ]
37     },
38     uniqueItems: true
39 };
40
41 module.exports = {
42     meta: {
43         deprecated: true,
44
45         replacedBy: [],
46
47         type: "suggestion",
48
49         docs: {
50             description: "disallow specified modules when loaded by `require`",
51             category: "Node.js and CommonJS",
52             recommended: false,
53             url: "https://eslint.org/docs/rules/no-restricted-modules"
54         },
55
56         schema: {
57             anyOf: [
58                 arrayOfStringsOrObjects,
59                 {
60                     type: "array",
61                     items: {
62                         type: "object",
63                         properties: {
64                             paths: arrayOfStringsOrObjects,
65                             patterns: arrayOfStrings
66                         },
67                         additionalProperties: false
68                     },
69                     additionalItems: false
70                 }
71             ]
72         },
73
74         messages: {
75             defaultMessage: "'{{name}}' module is restricted from being used.",
76             // eslint-disable-next-line eslint-plugin/report-message-format
77             customMessage: "'{{name}}' module is restricted from being used. {{customMessage}}",
78             patternMessage: "'{{name}}' module is restricted from being used by a pattern."
79         }
80     },
81
82     create(context) {
83         const options = Array.isArray(context.options) ? context.options : [];
84         const isPathAndPatternsObject =
85             typeof options[0] === "object" &&
86             (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns"));
87
88         const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
89         const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
90
91         const restrictedPathMessages = restrictedPaths.reduce((memo, importName) => {
92             if (typeof importName === "string") {
93                 memo[importName] = null;
94             } else {
95                 memo[importName.name] = importName.message;
96             }
97             return memo;
98         }, {});
99
100         // if no imports are restricted we don"t need to check
101         if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
102             return {};
103         }
104
105         const ig = ignore().add(restrictedPatterns);
106
107
108         /**
109          * Function to check if a node is a string literal.
110          * @param {ASTNode} node The node to check.
111          * @returns {boolean} If the node is a string literal.
112          */
113         function isStringLiteral(node) {
114             return node && node.type === "Literal" && typeof node.value === "string";
115         }
116
117         /**
118          * Function to check if a node is a static string template literal.
119          * @param {ASTNode} node The node to check.
120          * @returns {boolean} If the node is a string template literal.
121          */
122         function isStaticTemplateLiteral(node) {
123             return node && node.type === "TemplateLiteral" && node.expressions.length === 0;
124         }
125
126         /**
127          * Function to check if a node is a require call.
128          * @param {ASTNode} node The node to check.
129          * @returns {boolean} If the node is a require call.
130          */
131         function isRequireCall(node) {
132             return node.callee.type === "Identifier" && node.callee.name === "require";
133         }
134
135         /**
136          * Extract string from Literal or TemplateLiteral node
137          * @param {ASTNode} node The node to extract from
138          * @returns {string|null} Extracted string or null if node doesn't represent a string
139          */
140         function getFirstArgumentString(node) {
141             if (isStringLiteral(node)) {
142                 return node.value.trim();
143             }
144
145             if (isStaticTemplateLiteral(node)) {
146                 return node.quasis[0].value.cooked.trim();
147             }
148
149             return null;
150         }
151
152         /**
153          * Report a restricted path.
154          * @param {node} node representing the restricted path reference
155          * @param {string} name restricted path
156          * @returns {void}
157          * @private
158          */
159         function reportPath(node, name) {
160             const customMessage = restrictedPathMessages[name];
161             const messageId = customMessage
162                 ? "customMessage"
163                 : "defaultMessage";
164
165             context.report({
166                 node,
167                 messageId,
168                 data: {
169                     name,
170                     customMessage
171                 }
172             });
173         }
174
175         /**
176          * Check if the given name is a restricted path name
177          * @param {string} name name of a variable
178          * @returns {boolean} whether the variable is a restricted path or not
179          * @private
180          */
181         function isRestrictedPath(name) {
182             return Object.prototype.hasOwnProperty.call(restrictedPathMessages, name);
183         }
184
185         return {
186             CallExpression(node) {
187                 if (isRequireCall(node)) {
188
189                     // node has arguments
190                     if (node.arguments.length) {
191                         const name = getFirstArgumentString(node.arguments[0]);
192
193                         // if first argument is a string literal or a static string template literal
194                         if (name) {
195
196                             // check if argument value is in restricted modules array
197                             if (isRestrictedPath(name)) {
198                                 reportPath(node, name);
199                             }
200
201                             if (restrictedPatterns.length > 0 && ig.ignores(name)) {
202                                 context.report({
203                                     node,
204                                     messageId: "patternMessage",
205                                     data: { name }
206                                 });
207                             }
208                         }
209                     }
210                 }
211             }
212         };
213     }
214 };