UNPKG

9.17 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = function (d, b) {
4 extendStatics = Object.setPrototypeOf ||
5 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7 return extendStatics(d, b);
8 }
9 return function (d, b) {
10 extendStatics(d, b);
11 function __() { this.constructor = d; }
12 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13 };
14})();
15Object.defineProperty(exports, "__esModule", { value: true });
16var ts = require("typescript");
17var Lint = require("tslint");
18var tsutils = require("tsutils");
19var Utils_1 = require("./utils/Utils");
20var TypeGuard_1 = require("./utils/TypeGuard");
21var Rule = (function (_super) {
22 __extends(Rule, _super);
23 function Rule() {
24 return _super !== null && _super.apply(this, arguments) || this;
25 }
26 Rule.prototype.apply = function (sourceFile) {
27 return this.applyWithFunction(sourceFile, walk, this.parseOptions(this.getOptions()));
28 };
29 Rule.prototype.parseOptions = function (options) {
30 var _this = this;
31 var result = {
32 replacements: {},
33 ignoredList: [],
34 config: {
35 ignoreExternalModule: true
36 }
37 };
38 if (options.ruleArguments instanceof Array) {
39 options.ruleArguments.forEach(function (opt, index) {
40 if (index === 1 && TypeGuard_1.isObject(opt)) {
41 result.replacements = _this.extractReplacements(opt);
42 }
43 if (index === 2 && Array.isArray(opt)) {
44 result.ignoredList = _this.extractIgnoredList(opt);
45 }
46 if (index === 3 && TypeGuard_1.isObject(opt)) {
47 result.config = _this.extractConfig(opt);
48 }
49 });
50 }
51 return result;
52 };
53 Rule.prototype.extractReplacements = function (opt) {
54 var result = {};
55 if (TypeGuard_1.isObject(opt)) {
56 Object.keys(opt).forEach(function (key) {
57 var value = opt[key];
58 if (typeof value === 'string') {
59 result[key] = value;
60 }
61 });
62 }
63 return result;
64 };
65 Rule.prototype.extractIgnoredList = function (opt) {
66 return opt.filter(function (moduleName) { return typeof moduleName === 'string'; });
67 };
68 Rule.prototype.extractConfig = function (opt) {
69 var result = { ignoreExternalModule: true };
70 var configKeyLlist = ['ignoreExternalModule'];
71 if (TypeGuard_1.isObject(opt)) {
72 return Object.keys(opt).reduce(function (accum, key) {
73 if (configKeyLlist.filter(function (configKey) { return configKey === key; }).length >= 1) {
74 accum[key] = opt[key];
75 return accum;
76 }
77 return accum;
78 }, { ignoreExternalModule: true });
79 }
80 return result;
81 };
82 Rule.metadata = {
83 ruleName: 'import-name',
84 type: 'maintainability',
85 description: 'The name of the imported module must match the name of the thing being imported',
86 hasFix: true,
87 options: null,
88 optionsDescription: '',
89 optionExamples: [
90 [true],
91 [true, { moduleName: 'importedName' }],
92 [true, { moduleName: 'importedName' }, ['moduleName1', 'moduleName2']],
93 [true, { moduleName: 'importedName' }, ['moduleName1', 'moduleName2'], { ignoreExternalModule: false }]
94 ],
95 typescriptOnly: true,
96 issueClass: 'Ignored',
97 issueType: 'Warning',
98 severity: 'Low',
99 level: 'Opportunity for Excellence',
100 group: 'Clarity',
101 commonWeaknessEnumeration: '710'
102 };
103 return Rule;
104}(Lint.Rules.AbstractRule));
105exports.Rule = Rule;
106function walk(ctx) {
107 var option = ctx.options;
108 function getNameNodeFromImportNode(node) {
109 if (tsutils.isImportEqualsDeclaration(node)) {
110 return node.name;
111 }
112 var importClause = node.importClause;
113 return importClause === undefined ? undefined : importClause.name;
114 }
115 function checkIgnoreExternalModule(moduleName, node, opt) {
116 var runtimeNode = node;
117 if (opt.ignoreExternalModule === true && runtimeNode.parent !== undefined && runtimeNode.parent.resolvedModules !== undefined) {
118 var ignoreThisExternalModule_1 = false;
119 runtimeNode.parent.resolvedModules.forEach(function (value, key) {
120 if (key === moduleName && value.isExternalLibraryImport === true) {
121 ignoreThisExternalModule_1 = true;
122 }
123 });
124 return ignoreThisExternalModule_1;
125 }
126 return false;
127 }
128 function checkIgnoredListExists(moduleName, ignoredList) {
129 return ignoredList.filter(function (ignoredModule) { return ignoredModule === moduleName; }).length >= 1;
130 }
131 function checkReplacementsExist(importedName, expectedImportedName, moduleName, replacements) {
132 var allowedReplacementKeys = [expectedImportedName, moduleName, moduleName.replace(/.*\//, '')];
133 return Utils_1.Utils.exists(Object.keys(replacements), function (replacementKey) {
134 for (var index = 0; allowedReplacementKeys.length > index; index = index + 1) {
135 if (replacementKey === allowedReplacementKeys[index]) {
136 return importedName === replacements[replacementKey];
137 }
138 }
139 return false;
140 });
141 }
142 function isImportNameValid(importedName, expectedImportedName, moduleName, node) {
143 if (expectedImportedName === importedName) {
144 return true;
145 }
146 var isReplacementsExist = checkReplacementsExist(importedName, expectedImportedName, moduleName, option.replacements);
147 if (isReplacementsExist) {
148 return true;
149 }
150 var isIgnoredModuleExist = checkIgnoredListExists(moduleName, option.ignoredList);
151 if (isIgnoredModuleExist) {
152 return true;
153 }
154 var ignoreThisExternalModule = checkIgnoreExternalModule(moduleName, node, option.config);
155 if (ignoreThisExternalModule) {
156 return true;
157 }
158 return false;
159 }
160 function makeCamelCase(input) {
161 return input.replace(/[-|\.|_](.)/g, function (_match, group1) {
162 return group1.toUpperCase();
163 });
164 }
165 function validateImport(node, importedName, moduleName) {
166 var expectedImportedName = moduleName.replace(/.*\//, '');
167 if (expectedImportedName === '' || expectedImportedName === '.' || expectedImportedName === '..') {
168 return;
169 }
170 expectedImportedName = makeCamelCase(expectedImportedName);
171 if (isImportNameValid(importedName, expectedImportedName, moduleName, node)) {
172 return;
173 }
174 var message = "Misnamed import. Import should be named '" + expectedImportedName + "' but found '" + importedName + "'";
175 var nameNode = getNameNodeFromImportNode(node);
176 if (nameNode === undefined) {
177 return;
178 }
179 var nameNodeStartPos = nameNode.getStart();
180 var fix = new Lint.Replacement(nameNodeStartPos, nameNode.end - nameNodeStartPos, expectedImportedName);
181 ctx.addFailureAt(node.getStart(), node.getWidth(), message, fix);
182 }
183 function cb(node) {
184 if (tsutils.isImportEqualsDeclaration(node)) {
185 var name_1 = node.name.text;
186 if (tsutils.isExternalModuleReference(node.moduleReference)) {
187 var moduleRef = node.moduleReference;
188 if (tsutils.isStringLiteral(moduleRef.expression)) {
189 var moduleName = moduleRef.expression.text;
190 validateImport(node, name_1, moduleName);
191 }
192 }
193 else if (tsutils.isQualifiedName(node.moduleReference)) {
194 var moduleName = node.moduleReference.getText();
195 moduleName = moduleName.replace(/.*\./, '');
196 validateImport(node, name_1, moduleName);
197 }
198 }
199 if (tsutils.isImportDeclaration(node)) {
200 if (node.importClause !== undefined && node.importClause.name !== undefined) {
201 var name_2 = node.importClause.name.text;
202 if (tsutils.isStringLiteral(node.moduleSpecifier)) {
203 var moduleName = node.moduleSpecifier.text;
204 validateImport(node, name_2, moduleName);
205 }
206 }
207 }
208 return ts.forEachChild(node, cb);
209 }
210 return ts.forEachChild(ctx.sourceFile, cb);
211}
212//# sourceMappingURL=importNameRule.js.map
\No newline at end of file