UNPKG

tslint-etc

Version:
86 lines (85 loc) 3.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Rule = void 0; const tsquery_1 = require("@phenomnomnominal/tsquery"); const Lint = require("tslint"); const ts = require("typescript"); const support_1 = require("../support"); class Rule extends Lint.Rules.TypedRule { applyWithProgram(sourceFile, program) { const { ruleArguments: [options], } = this.getOptions(); const allowExplicitAny = options && options.hasOwnProperty("allowExplicitAny") ? options.allowExplicitAny : false; const failures = []; const typeChecker = program.getTypeChecker(); const callExpressions = tsquery_1.tsquery(sourceFile, `CallExpression[expression.name.text=/^(catch|then)$/]`); callExpressions.forEach((callExpression) => { const { expression } = callExpression; if (!ts.isPropertyAccessExpression(expression)) { return; } const arg = expression.name.text === "catch" ? callExpression.arguments[0] : callExpression.arguments[1]; if (!arg) { return; } if (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg)) { const [parameter] = arg.parameters; if (!parameter) { return; } const object = expression.expression; if (!support_1.couldBeType(typeChecker.getTypeAtLocation(object), "Promise")) { return; } this.checkErrorNode(sourceFile, failures, allowExplicitAny, parameter); } }); const catchClauses = tsquery_1.tsquery(sourceFile, `CatchClause`); catchClauses.forEach((catchClause) => { const { variableDeclaration } = catchClause; if (variableDeclaration) { this.checkErrorNode(sourceFile, failures, allowExplicitAny, variableDeclaration); } }); return failures; } checkErrorNode(sourceFile, failures, allowExplicitAny, node) { if (node.type) { if (node.type.kind === ts.SyntaxKind.AnyKeyword) { if (allowExplicitAny) { return; } failures.push(new Lint.RuleFailure(sourceFile, node.getStart(), node.getStart() + node.getWidth(), Rule.EXPLICIT_ANY, this.ruleName, Lint.Replacement.replaceNode(node.type, "unknown"))); } else if (node.type.kind !== ts.SyntaxKind.UnknownKeyword) { failures.push(new Lint.RuleFailure(sourceFile, node.getStart(), node.getStart() + node.getWidth(), Rule.NARROWED, this.ruleName)); } } else { failures.push(new Lint.RuleFailure(sourceFile, node.getStart(), node.getStart() + node.getWidth(), Rule.IMPLICIT_ANY, this.ruleName, Lint.Replacement.appendText(node.getStart() + node.getWidth(), ": unknown"))); } } } exports.Rule = Rule; Rule.metadata = { deprecationMessage: undefined, description: "Disallows implicit `any` errors in catch clauses and promise rejections.", options: { properties: { allowExplicitAny: { type: "boolean" }, }, type: "object", }, optionsDescription: Lint.Utils.dedent ` An optional object with an optional \`allowExplicitAny\` property.`, requiresTypeInfo: true, ruleName: "no-implicit-any-catch", type: "functionality", typescriptOnly: true, }; Rule.EXPLICIT_ANY = "Explicit any"; Rule.IMPLICIT_ANY = "Implicit any"; Rule.NARROWED = "Error type must be unknown or any";