UNPKG

rxjs-tslint-rules

Version:
213 lines (212 loc) 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Rule = void 0; var tslib_1 = require("tslib"); var fs = tslib_1.__importStar(require("fs")); var path = tslib_1.__importStar(require("path")); var Lint = tslib_1.__importStar(require("tslint")); var tsutils = tslib_1.__importStar(require("tsutils")); var ts = tslib_1.__importStar(require("typescript")); var peer = tslib_1.__importStar(require("../support/peer")); var added_walker_1 = require("../support/added-walker"); var used_walker_1 = require("../support/used-walker"); var Rule = (function (_super) { tslib_1.__extends(Rule, _super); function Rule() { return _super !== null && _super.apply(this, arguments) || this; } Rule.prototype.applyWithProgram = function (sourceFile, program) { return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program)); }; Rule.metadata = { deprecationMessage: peer.v6 && !peer.compat ? peer.v6NotNeededMessage : undefined, description: "Enforces the importation of patched observables and operators used in the module.", options: { properties: { allowElsewhere: { type: "boolean" }, allowUnused: { type: "boolean" }, file: { type: "string" }, }, type: "object", }, optionsDescription: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n An optional object with the property `file`.\n This the path of the module - relative to the `tsconfig.json` - that imports the patched observables and operators.\n If `file` is specified, the `allowElsewhere` and `allowUnused` options can be used to configure whether or not\n patched imports are allowed in other files and whether or not unused patched imports are allowed.\n Both `allowElsewhere` and `allowUnused` default to `false`.\n If not specified, patched observables and operators must be imported in the modules in which they are used."], ["\n An optional object with the property \\`file\\`.\n This the path of the module - relative to the \\`tsconfig.json\\` - that imports the patched observables and operators.\n If \\`file\\` is specified, the \\`allowElsewhere\\` and \\`allowUnused\\` options can be used to configure whether or not\n patched imports are allowed in other files and whether or not unused patched imports are allowed.\n Both \\`allowElsewhere\\` and \\`allowUnused\\` default to \\`false\\`.\n If not specified, patched observables and operators must be imported in the modules in which they are used."]))), requiresTypeInfo: true, ruleName: "rxjs-add", type: "functionality", typescriptOnly: true, }; Rule.FAILURE_STRING = "RxJS add import is missing"; return Rule; }(Lint.Rules.TypedRule)); exports.Rule = Rule; var Walker = (function (_super) { tslib_1.__extends(Walker, _super); function Walker() { return _super !== null && _super.apply(this, arguments) || this; } Walker.initCaseSensitive = function () { try { fs.statSync(__filename.toLowerCase()); return false; } catch (_a) { return true; } }; Walker.prototype.onSourceFileEnd = function () { var _this = this; var _a = this, addedObservables = _a.addedObservables, addedOperators = _a.addedOperators; var failure = Rule.FAILURE_STRING; var _b = tslib_1.__read(this.getOptions(), 1), options = _b[0]; if (options && options.file) { var walker = this.walkFile(options.file); addedObservables = walker.addedObservables; addedOperators = walker.addedOperators; failure = Rule.FAILURE_STRING + " from " + options.file; if (this.normalizeFile(this.sourceFilePath) === this.normalizeFile(walker.sourceFilePath)) { if (!options.allowUnused) { var program = this.getProgram(); var sourceFiles = program.getSourceFiles(); var usedObservables_1 = {}; var usedOperators_1 = {}; var _loop_1 = function (i, length_1) { var sourceFile = sourceFiles[i]; if (!sourceFile["isDeclarationFile"]) { var sourceFileWalker_1 = new used_walker_1.UsedWalker(sourceFile, { disabledIntervals: [], ruleArguments: [], ruleName: this_1.getRuleName(), ruleSeverity: "error", }, program); sourceFileWalker_1.walk(sourceFile); Object.keys(sourceFileWalker_1.usedObservables).forEach(function (key) { sourceFileWalker_1.usedObservables[key].forEach(function (node) { used_walker_1.UsedWalker.add(usedObservables_1, key, node); }); }); Object.keys(sourceFileWalker_1.usedOperators).forEach(function (key) { sourceFileWalker_1.usedOperators[key].forEach(function (node) { used_walker_1.UsedWalker.add(usedOperators_1, key, node); }); }); } }; var this_1 = this; for (var i = 0, length_1 = sourceFiles.length; i < length_1; ++i) { _loop_1(i, length_1); } Object.keys(addedObservables).forEach(function (key) { if (!usedObservables_1[key]) { addedObservables[key].forEach(function (node) { return _this.addFailureAtNode(tsutils.isImportDeclaration(node) ? node.moduleSpecifier : node, "Unused patched observable in " + options.file + ": " + key); }); } }); Object.keys(addedOperators).forEach(function (key) { if (!usedOperators_1[key]) { addedOperators[key].forEach(function (node) { return _this.addFailureAtNode(tsutils.isImportDeclaration(node) ? node.moduleSpecifier : node, "Unused patched operator in " + options.file + ": " + key); }); } }); } } else { if (!options.allowElsewhere) { Object.keys(this.addedObservables).forEach(function (key) { _this.addedObservables[key].forEach(function (node) { return _this.addFailureAtNode(tsutils.isImportDeclaration(node) ? node.moduleSpecifier : node, "Patched observables are forbidden outside of " + options.file + ": " + key); }); }); Object.keys(this.addedOperators).forEach(function (key) { _this.addedOperators[key].forEach(function (node) { return _this.addFailureAtNode(tsutils.isImportDeclaration(node) ? node.moduleSpecifier : node, "Patched operators are forbidden outside of " + options.file + ": " + key); }); }); } } } Object.keys(this.usedObservables).forEach(function (key) { if (!addedObservables[key]) { _this.usedObservables[key].forEach(function (node) { return _this.addFailureAtNode(node, failure + ": " + key); }); } }); Object.keys(this.usedOperators).forEach(function (key) { if (!addedOperators[key]) { _this.usedOperators[key].forEach(function (node) { return _this.addFailureAtNode(node, failure + ": " + key); }); } }); }; Walker.prototype.findSourceFile = function (file) { var program = this.getProgram(); var rootFiles = program.getRootFileNames(); var fileDirCandidates = new Set(); var _loop_2 = function (i, length_2) { var configFile = ts.findConfigFile(this_2.normalizeFile(path.dirname(rootFiles[i])), ts.sys.fileExists); if (configFile && !fileDirCandidates.has(path.dirname(configFile))) { var resolvedFile_1 = this_2.normalizeFile(path.resolve(path.dirname(configFile), file)); var sourceFile = program.getSourceFileByPath(resolvedFile_1); if (sourceFile) { return { value: sourceFile }; } if (!Walker.isCaseSensitive) { var found = program.getSourceFiles().find(function (file) { return file["path"].toLowerCase() === resolvedFile_1.toLowerCase(); }); if (found) { return { value: found }; } } fileDirCandidates.add(path.dirname(configFile)); } }; var this_2 = this; for (var i = 0, length_2 = rootFiles.length; i < length_2; ++i) { var state_1 = _loop_2(i, length_2); if (typeof state_1 === "object") return state_1.value; } if (fileDirCandidates.size === 0) { throw new Error("Cannot find 'tsconfig.json'"); } else { throw new Error("Cannot find an import of '" + file + "' from any of these locations: " + ("[" + Array.from(fileDirCandidates.values()).join(", ") + "]. Has it been imported?")); } }; Walker.prototype.normalizeFile = function (file) { var normalized = ts["normalizeSlashes"](file); return ts.sys.useCaseSensitiveFileNames ? normalized : normalized.toLowerCase(); }; Walker.prototype.walkFile = function (file) { var program = this.getProgram(); var fileWalker = Walker.fileWalkerCache.get(program); if (!fileWalker) { var sourceFile = this.findSourceFile(file); fileWalker = new added_walker_1.AddedWalker(sourceFile, { disabledIntervals: [], ruleArguments: [], ruleName: this.getRuleName(), ruleSeverity: "error", }, program); fileWalker.walk(sourceFile); Walker.fileWalkerCache.set(program, fileWalker); } return fileWalker; }; Walker.isCaseSensitive = Walker.initCaseSensitive(); Walker.fileWalkerCache = new Map(); return Walker; }(used_walker_1.UsedWalker)); var templateObject_1;