Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-restricted-imports.js
1 /**
2  * @fileoverview Restrict usage of specified node imports.
3  * @author Guy Ellis
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                     importNames: {
33                         type: "array",
34                         items: {
35                             type: "string"
36                         }
37                     }
38                 },
39                 additionalProperties: false,
40                 required: ["name"]
41             }
42         ]
43     },
44     uniqueItems: true
45 };
46
47 module.exports = {
48     meta: {
49         type: "suggestion",
50
51         docs: {
52             description: "disallow specified modules when loaded by `import`",
53             category: "ECMAScript 6",
54             recommended: false,
55             url: "https://eslint.org/docs/rules/no-restricted-imports"
56         },
57
58         messages: {
59             path: "'{{importSource}}' import is restricted from being used.",
60             // eslint-disable-next-line eslint-plugin/report-message-format
61             pathWithCustomMessage: "'{{importSource}}' import is restricted from being used. {{customMessage}}",
62
63             patterns: "'{{importSource}}' import is restricted from being used by a pattern.",
64
65             everything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
66             // eslint-disable-next-line eslint-plugin/report-message-format
67             everythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted. {{customMessage}}"
68         },
69
70         schema: {
71             anyOf: [
72                 arrayOfStringsOrObjects,
73                 {
74                     type: "array",
75                     items: [{
76                         type: "object",
77                         properties: {
78                             paths: arrayOfStringsOrObjects,
79                             patterns: arrayOfStrings
80                         },
81                         additionalProperties: false
82                     }],
83                     additionalItems: false
84                 }
85             ]
86         }
87     },
88
89     create(context) {
90         const options = Array.isArray(context.options) ? context.options : [];
91         const isPathAndPatternsObject =
92             typeof options[0] === "object" &&
93             (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns"));
94
95         const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
96         const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
97
98         const restrictedPathMessages = restrictedPaths.reduce((memo, importSource) => {
99             if (typeof importSource === "string") {
100                 memo[importSource] = { message: null };
101             } else {
102                 memo[importSource.name] = {
103                     message: importSource.message,
104                     importNames: importSource.importNames
105                 };
106             }
107             return memo;
108         }, {});
109
110         // if no imports are restricted we don"t need to check
111         if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
112             return {};
113         }
114
115         const restrictedPatternsMatcher = ignore().add(restrictedPatterns);
116
117         /**
118          * Checks to see if "*" is being used to import everything.
119          * @param {Set.<string>} importNames Set of import names that are being imported
120          * @returns {boolean} whether everything is imported or not
121          */
122         function isEverythingImported(importNames) {
123             return importNames.has("*");
124         }
125
126         /**
127          * Report a restricted path.
128          * @param {node} node representing the restricted path reference
129          * @returns {void}
130          * @private
131          */
132         function reportPath(node) {
133             const importSource = node.source.value.trim();
134             const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
135
136             context.report({
137                 node,
138                 messageId: customMessage ? "pathWithCustomMessage" : "path",
139                 data: {
140                     importSource,
141                     customMessage
142                 }
143             });
144         }
145
146         /**
147          * Report a restricted path specifically for patterns.
148          * @param {node} node representing the restricted path reference
149          * @returns {void}
150          * @private
151          */
152         function reportPathForPatterns(node) {
153             const importSource = node.source.value.trim();
154
155             context.report({
156                 node,
157                 messageId: "patterns",
158                 data: {
159                     importSource
160                 }
161             });
162         }
163
164         /**
165          * Report a restricted path specifically when using the '*' import.
166          * @param {string} importSource path of the import
167          * @param {node} node representing the restricted path reference
168          * @returns {void}
169          * @private
170          */
171         function reportPathForEverythingImported(importSource, node) {
172             const importNames = restrictedPathMessages[importSource].importNames;
173             const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
174
175             context.report({
176                 node,
177                 messageId: customMessage ? "everythingWithCustomMessage" : "everything",
178                 data: {
179                     importSource,
180                     importNames,
181                     customMessage
182                 }
183             });
184         }
185
186         /**
187          * Check if the given importSource is restricted because '*' is being imported.
188          * @param {string} importSource path of the import
189          * @param {Set.<string>} importNames Set of import names that are being imported
190          * @returns {boolean} whether the path is restricted
191          * @private
192          */
193         function isRestrictedForEverythingImported(importSource, importNames) {
194             return Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource) &&
195                 restrictedPathMessages[importSource].importNames &&
196                 isEverythingImported(importNames);
197         }
198
199         /**
200          * Check if the given importNames are restricted given a list of restrictedImportNames.
201          * @param {Set.<string>} importNames Set of import names that are being imported
202          * @param {string[]} restrictedImportNames array of import names that are restricted for this import
203          * @returns {boolean} whether the objectName is restricted
204          * @private
205          */
206         function isRestrictedObject(importNames, restrictedImportNames) {
207             return restrictedImportNames.some(restrictedObjectName => (
208                 importNames.has(restrictedObjectName)
209             ));
210         }
211
212         /**
213          * Check if the given importSource is a restricted path.
214          * @param {string} importSource path of the import
215          * @param {Set.<string>} importNames Set of import names that are being imported
216          * @returns {boolean} whether the variable is a restricted path or not
217          * @private
218          */
219         function isRestrictedPath(importSource, importNames) {
220             let isRestricted = false;
221
222             if (Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
223                 if (restrictedPathMessages[importSource].importNames) {
224                     isRestricted = isRestrictedObject(importNames, restrictedPathMessages[importSource].importNames);
225                 } else {
226                     isRestricted = true;
227                 }
228             }
229
230             return isRestricted;
231         }
232
233         /**
234          * Check if the given importSource is restricted by a pattern.
235          * @param {string} importSource path of the import
236          * @returns {boolean} whether the variable is a restricted pattern or not
237          * @private
238          */
239         function isRestrictedPattern(importSource) {
240             return restrictedPatterns.length > 0 && restrictedPatternsMatcher.ignores(importSource);
241         }
242
243         /**
244          * Checks a node to see if any problems should be reported.
245          * @param {ASTNode} node The node to check.
246          * @returns {void}
247          * @private
248          */
249         function checkNode(node) {
250             const importSource = node.source.value.trim();
251             const importNames = node.specifiers ? node.specifiers.reduce((set, specifier) => {
252                 if (specifier.type === "ImportDefaultSpecifier") {
253                     set.add("default");
254                 } else if (specifier.type === "ImportNamespaceSpecifier") {
255                     set.add("*");
256                 } else if (specifier.imported) {
257                     set.add(specifier.imported.name);
258                 } else if (specifier.local) {
259                     set.add(specifier.local.name);
260                 }
261                 return set;
262             }, new Set()) : new Set();
263
264             if (isRestrictedForEverythingImported(importSource, importNames)) {
265                 reportPathForEverythingImported(importSource, node);
266             }
267
268             if (isRestrictedPath(importSource, importNames)) {
269                 reportPath(node);
270             }
271             if (isRestrictedPattern(importSource)) {
272                 reportPathForPatterns(node);
273             }
274         }
275
276         return {
277             ImportDeclaration: checkNode,
278             ExportNamedDeclaration(node) {
279                 if (node.source) {
280                     checkNode(node);
281                 }
282             },
283             ExportAllDeclaration: checkNode
284         };
285     }
286 };