UNPKG

tslint-microsoft-contrib

Version:
240 lines 10.4 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); } return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var ts = require("typescript"); var Lint = require("tslint"); var tsutils = require("tsutils"); var Utils_1 = require("./utils/Utils"); var TypeGuard_1 = require("./utils/TypeGuard"); var Rule = (function (_super) { __extends(Rule, _super); function Rule() { return _super !== null && _super.apply(this, arguments) || this; } Rule.prototype.apply = function (sourceFile) { return this.applyWithFunction(sourceFile, walk, this.parseOptions(this.getOptions())); }; Rule.prototype.parseOptions = function (options) { var _this = this; var result = { replacements: {}, ignoredList: [], config: { ignoreExternalModule: true, case: StringCase.camel } }; if (options.ruleArguments instanceof Array) { options.ruleArguments.forEach(function (opt, index) { if (index === 1 && TypeGuard_1.isObject(opt)) { result.replacements = _this.extractReplacements(opt); } if (index === 2 && Array.isArray(opt)) { result.ignoredList = _this.extractIgnoredList(opt); } if (index === 3 && TypeGuard_1.isObject(opt)) { result.config = _this.extractConfig(opt); } }); } return result; }; Rule.prototype.extractReplacements = function (opt) { var result = {}; if (TypeGuard_1.isObject(opt)) { Object.keys(opt).forEach(function (key) { var value = opt[key]; if (typeof value === 'string') { result[key] = value; } }); } return result; }; Rule.prototype.extractIgnoredList = function (opt) { return opt.filter(function (moduleName) { return typeof moduleName === 'string'; }); }; Rule.prototype.extractConfig = function (opt) { var result = { ignoreExternalModule: true, case: StringCase.camel }; var configKeyList = ['ignoreExternalModule', 'case']; if (TypeGuard_1.isObject(opt)) { return Object.keys(opt).reduce(function (accum, key) { if (configKeyList.filter(function (configKey) { return configKey === key; }).length >= 1) { accum[key] = opt[key]; return accum; } return accum; }, { ignoreExternalModule: true, case: StringCase.camel }); } return result; }; Rule.metadata = { ruleName: 'import-name', type: 'maintainability', description: 'The name of the imported module must match the name of the thing being imported', hasFix: true, options: null, optionsDescription: '', optionExamples: [ [true], [true, { moduleName: 'importedName' }], [true, { moduleName: 'importedName' }, ['moduleName1', 'moduleName2']], [true, { moduleName: 'importedName' }, ['moduleName1', 'moduleName2'], { ignoreExternalModule: false }] ], typescriptOnly: true, issueClass: 'Ignored', issueType: 'Warning', severity: 'Low', level: 'Opportunity for Excellence', group: 'Clarity', commonWeaknessEnumeration: '710' }; return Rule; }(Lint.Rules.AbstractRule)); exports.Rule = Rule; var StringCase; (function (StringCase) { StringCase["any"] = "any-case"; StringCase["pascal"] = "PascalCase"; StringCase["camel"] = "camelCase"; })(StringCase || (StringCase = {})); function walk(ctx) { var option = ctx.options; function getNameNodeFromImportNode(node) { if (tsutils.isImportEqualsDeclaration(node)) { return node.name; } var importClause = node.importClause; return importClause === undefined ? undefined : importClause.name; } function checkIgnoreExternalModule(moduleName, node, opt) { var runtimeNode = node; if (opt.ignoreExternalModule === true && runtimeNode.parent !== undefined && runtimeNode.parent.resolvedModules !== undefined) { var ignoreThisExternalModule_1 = false; runtimeNode.parent.resolvedModules.forEach(function (value, key) { if (key === moduleName && value.isExternalLibraryImport === true) { ignoreThisExternalModule_1 = true; } }); return ignoreThisExternalModule_1; } return false; } function checkIgnoredListExists(moduleName, ignoredList) { return ignoredList.filter(function (ignoredModule) { return ignoredModule === moduleName; }).length >= 1; } function checkReplacementsExist(importedName, expectedImportedName, moduleName, replacements) { var allowedReplacementKeys = [ makeCamelCase(expectedImportedName), makePascalCase(expectedImportedName), moduleName, moduleName.replace(/.*\//, '') ]; return Utils_1.Utils.exists(Object.keys(replacements), function (replacementKey) { for (var index = 0; allowedReplacementKeys.length > index; index = index + 1) { if (replacementKey === allowedReplacementKeys[index]) { return importedName === replacements[replacementKey]; } } return false; }); } function isImportNameValid(importedName, expectedImportedName, moduleName, node) { if (transformName(expectedImportedName).indexOf(importedName) > -1) { return true; } var isReplacementsExist = checkReplacementsExist(importedName, expectedImportedName, moduleName, option.replacements); if (isReplacementsExist) { return true; } var isIgnoredModuleExist = checkIgnoredListExists(moduleName, option.ignoredList); if (isIgnoredModuleExist) { return true; } var ignoreThisExternalModule = checkIgnoreExternalModule(moduleName, node, option.config); if (ignoreThisExternalModule) { return true; } return false; } function transformName(input) { switch (option.config.case) { case StringCase.camel: return [makeCamelCase(input)]; case StringCase.pascal: return [makePascalCase(input)]; case StringCase.any: return [makeCamelCase(input), makePascalCase(input)]; default: throw new Error("Unknown case for import-name rule: \"" + option.config.case + "\""); } } function makeCamelCase(input) { return input.replace(/[-|\.|_](.)/g, function (_match, group1) { return group1.toUpperCase(); }); } function makePascalCase(input) { return input.replace(/(?:^|[-|\.|_|])([a-z])/g, function (_, group1) { return group1.toUpperCase(); }); } function validateImport(node, importedName, moduleName) { var expectedImportedName = moduleName.replace(/.*\//, ''); if (expectedImportedName === '' || expectedImportedName === '.' || expectedImportedName === '..') { return; } if (isImportNameValid(importedName, expectedImportedName, moduleName, node)) { return; } var expectedImportedNames = transformName(expectedImportedName); var expectedNames = expectedImportedNames.map(function (name) { return "'" + name + "'"; }).join(' or '); var message = "Misnamed import. Import should be named " + expectedNames + " but found '" + importedName + "'"; var nameNode = getNameNodeFromImportNode(node); if (nameNode === undefined) { return; } var nameNodeStartPos = nameNode.getStart(); var fix = new Lint.Replacement(nameNodeStartPos, nameNode.end - nameNodeStartPos, expectedImportedNames[0]); ctx.addFailureAt(node.getStart(), node.getWidth(), message, fix); } function cb(node) { if (tsutils.isImportEqualsDeclaration(node)) { var name_1 = node.name.text; if (tsutils.isExternalModuleReference(node.moduleReference)) { var moduleRef = node.moduleReference; if (tsutils.isStringLiteral(moduleRef.expression)) { var moduleName = moduleRef.expression.text; validateImport(node, name_1, moduleName); } } else if (tsutils.isQualifiedName(node.moduleReference)) { var moduleName = node.moduleReference.getText(); moduleName = moduleName.replace(/.*\./, ''); validateImport(node, name_1, moduleName); } } if (tsutils.isImportDeclaration(node)) { if (node.importClause !== undefined && node.importClause.name !== undefined) { var name_2 = node.importClause.name.text; if (tsutils.isStringLiteral(node.moduleSpecifier)) { var moduleName = node.moduleSpecifier.text; validateImport(node, name_2, moduleName); } } } return ts.forEachChild(node, cb); } return ts.forEachChild(ctx.sourceFile, cb); } //# sourceMappingURL=importNameRule.js.map