.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / tslint / lib / rules / importBlacklistRule.js
1 "use strict";
2 /**
3  * @license
4  * Copyright 2018 Palantir Technologies, Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 Object.defineProperty(exports, "__esModule", { value: true });
19 var tslib_1 = require("tslib");
20 var tsutils_1 = require("tsutils");
21 var Lint = require("../index");
22 var Rule = /** @class */ (function (_super) {
23     tslib_1.__extends(Rule, _super);
24     function Rule() {
25         return _super !== null && _super.apply(this, arguments) || this;
26     }
27     Rule.MAKE_NAMED_IMPORT_FAILURE_STRING = function (importName) {
28         return importName === "default"
29             ? "Importing (or re-exporting) the default export is blacklisted."
30             : "The export \"" + importName + "\" is blacklisted.";
31     };
32     Rule.prototype.isEnabled = function () {
33         return _super.prototype.isEnabled.call(this) && this.ruleArguments.length > 0;
34     };
35     Rule.prototype.apply = function (sourceFile) {
36         return this.applyWithFunction(sourceFile, walk, this.ruleArguments);
37     };
38     /* tslint:disable:object-literal-sort-keys */
39     Rule.metadata = {
40         ruleName: "import-blacklist",
41         description: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n            Disallows importing the specified modules via `import` and `require`,\n            or importing specific named exports of the specified modules,\n            or using imports matching specified regular expression patterns."], ["\n            Disallows importing the specified modules via \\`import\\` and \\`require\\`,\n            or importing specific named exports of the specified modules,\n            or using imports matching specified regular expression patterns."]))),
42         rationale: Lint.Utils.dedent(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n            For some libraries, importing the library directly can cause unused\n            submodules to be loaded, so you may want to block these imports and\n            require that users directly import only the submodules they need.\n            In other cases, you may simply want to ban an import because using\n            it is undesirable or unsafe."], ["\n            For some libraries, importing the library directly can cause unused\n            submodules to be loaded, so you may want to block these imports and\n            require that users directly import only the submodules they need.\n            In other cases, you may simply want to ban an import because using\n            it is undesirable or unsafe."]))),
43         optionsDescription: "A list of blacklisted modules, named imports, or regular expression patterns.",
44         options: {
45             type: "array",
46             items: {
47                 oneOf: [
48                     {
49                         type: "string",
50                         minLength: 1,
51                     },
52                     {
53                         type: "object",
54                         additionalProperties: {
55                             type: "array",
56                             minItems: 1,
57                             items: {
58                                 type: "string",
59                                 minLength: 1,
60                             },
61                         },
62                     },
63                     {
64                         type: "array",
65                         items: {
66                             type: "string",
67                         },
68                         minLength: 1,
69                     },
70                 ],
71             },
72         },
73         optionExamples: [
74             true,
75             [true, "rxjs", "lodash"],
76             [true, "lodash", { lodash: ["pull", "pullAll"] }],
77             [true, "rxjs", { lodash: ["pull", "pullAll"] }, [".*\\.temp$", ".*\\.tmp$"]],
78         ],
79         type: "functionality",
80         typescriptOnly: false,
81     };
82     Rule.WHOLE_MODULE_FAILURE_STRING = "Importing this module is blacklisted. Try importing a submodule instead.";
83     Rule.IMPLICIT_NAMED_IMPORT_FAILURE_STRING = "Some named exports from this module are blacklisted for importing " +
84         "(or re-exporting). Import/re-export only the specific values you want, " +
85         "instead of the whole module.";
86     Rule.FAILURE_STRING_REGEX = "This import is blacklisted by ";
87     return Rule;
88 }(Lint.Rules.AbstractRule));
89 exports.Rule = Rule;
90 function walk(ctx) {
91     // Merge/normalize options.
92     // E.g., ["a", { "b": ["c"], "d": ["e", "e"] }, "f", { "f": ["g"] }]
93     // becomes { "a": true, "b": Set(["c"]), "d": Set(["e"]), "f": true }.
94     var bannedImports = ctx.options.reduce(function (acc, it) {
95         if (typeof it === "string") {
96             acc[it] = true;
97         }
98         else if (!Array.isArray(it)) {
99             Object.keys(it).forEach(function (moduleName) {
100                 if (acc[moduleName] instanceof Set) {
101                     it[moduleName].forEach(function (bannedImport) {
102                         acc[moduleName].add(bannedImport);
103                     });
104                 }
105                 else if (acc[moduleName] !== true) {
106                     acc[moduleName] = new Set(it[moduleName]);
107                 }
108             });
109         }
110         return acc;
111     }, Object.create(null));
112     var regexOptions = [];
113     for (var _i = 0, _a = ctx.options; _i < _a.length; _i++) {
114         var option = _a[_i];
115         if (Array.isArray(option)) {
116             for (var _b = 0, option_1 = option; _b < option_1.length; _b++) {
117                 var pattern = option_1[_b];
118                 regexOptions.push(RegExp(pattern));
119             }
120         }
121     }
122     for (var _c = 0, _d = tsutils_1.findImports(ctx.sourceFile, 63 /* All */); _c < _d.length; _c++) {
123         var name = _d[_c];
124         // TODO #3963: Resolve/normalize relative file imports to a canonical path?
125         var importedModule = name.text;
126         var bansForModule = bannedImports[importedModule];
127         // Check if at least some imports from this module are banned.
128         if (bansForModule !== undefined) {
129             // If importing this module is totally banned, we can error now,
130             // without determining whether the user is importing the whole
131             // module or named exports.
132             if (bansForModule === true) {
133                 ctx.addFailure(name.getStart(ctx.sourceFile) + 1, name.end - 1, Rule.WHOLE_MODULE_FAILURE_STRING);
134                 continue;
135             }
136             // Otherwise, find the named imports, if any, and fail if the
137             // user tried to import any of them. We don't have named imports
138             // when the user is importing the whole module, which includes:
139             //
140             // - ImportKind.Require (i.e., `require('module-specifier')`),
141             // - ImportKind.DynamicImport (i.e., `import("module-specifier")`),
142             // - ImportKind.ImportEquals (i.e., `import x = require()`),
143             // - and ImportKind.ImportDeclaration, where there's a full namespace
144             //   import (i.e. `import * as x from "module-specifier"`)
145             //
146             // However, namedImports will be an array when we have one of the
147             // various permutations of `import x, { a, b as c } from "y"`.
148             //
149             // We treat re-exports from other modules the same as attempting to
150             // import the re-exported binding(s), as the re-export is essentially
151             // an import followed by an export, and not treating these as an
152             // import would allow backdoor imports of the banned bindings. So,
153             // our last case is `ImportKind.ExportFrom`, and for that:
154             //
155             // - `export nameForDefault from "module"` isn't part of the ESM
156             // syntax (yet), so we only have to handle two cases below:
157             // `export { x } from "y"` and `export * from "specifier"`.
158             var parentNode = name.parent;
159             // Disable strict-boolean-expressions for the next few lines so our &&
160             // checks can help type inference figure out if when don't have undefined.
161             // tslint:disable strict-boolean-expressions
162             var importClause = parentNode && tsutils_1.isImportDeclaration(parentNode) ? parentNode.importClause : undefined;
163             var importsDefaultExport = importClause && Boolean(importClause.name);
164             // Below, check isNamedImports to rule out the
165             // `import * as ns from "..."` case.
166             var importsSpecificNamedExports = importClause &&
167                 importClause.namedBindings &&
168                 tsutils_1.isNamedImports(importClause.namedBindings);
169             // If parentNode is an ExportDeclaration, it must represent an
170             // `export from`, as findImports verifies that. Then, if exportClause
171             // is undefined, we're dealing with `export * from ...`.
172             var reExportsSpecificNamedExports = parentNode && tsutils_1.isExportDeclaration(parentNode) && Boolean(parentNode.exportClause);
173             // tslint:enable strict-boolean-expressions
174             if (importsDefaultExport ||
175                 importsSpecificNamedExports ||
176                 reExportsSpecificNamedExports) {
177                 // Add an import for the default import and any named bindings.
178                 // For the named bindings, we use the name of the export from the
179                 // module (i.e., .propertyName) over its alias in the import when
180                 // the two diverge.
181                 var toExportName = function (it) {
182                     return (it.propertyName || it.name).text;
183                 }; // tslint:disable-line strict-boolean-expressions
184                 var exportClause = reExportsSpecificNamedExports
185                     ? parentNode.exportClause
186                     : undefined;
187                 var namedImportsOrReExports = (importsDefaultExport ? ["default"] : []).concat((importsSpecificNamedExports
188                     ? importClause.namedBindings.elements.map(toExportName)
189                     : []), (exportClause !== undefined ? exportClause.elements.map(toExportName) : []));
190                 for (var _e = 0, namedImportsOrReExports_1 = namedImportsOrReExports; _e < namedImportsOrReExports_1.length; _e++) {
191                     var importName = namedImportsOrReExports_1[_e];
192                     if (bansForModule.has(importName)) {
193                         ctx.addFailureAtNode(exportClause !== undefined ? exportClause : importClause, Rule.MAKE_NAMED_IMPORT_FAILURE_STRING(importName));
194                     }
195                 }
196             }
197             else {
198                 // If we're here, the user tried to import/re-export the whole module
199                 ctx.addFailure(name.getStart(ctx.sourceFile) + 1, name.end - 1, Rule.IMPLICIT_NAMED_IMPORT_FAILURE_STRING);
200             }
201         }
202         for (var _f = 0, regexOptions_1 = regexOptions; _f < regexOptions_1.length; _f++) {
203             var regex = regexOptions_1[_f];
204             if (regex.test(name.text)) {
205                 ctx.addFailure(name.getStart(ctx.sourceFile) + 1, name.end - 1, Rule.FAILURE_STRING_REGEX + regex.toString());
206             }
207         }
208     }
209 }
210 var templateObject_1, templateObject_2;