UNPKG

tslint-microsoft-contrib

Version:
218 lines 9.37 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 AstUtils_1 = require("./utils/AstUtils"); 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 maxBodyLength; var maxFuncBodyLength; var maxFuncExpressionBodyLength; var maxArrowBodyLength; var maxMethodBodyLength; var maxCtorBodyLength; var ignoreComments; var ignoreParametersToFunctionRegex; if (options.ruleArguments instanceof Array) { options.ruleArguments.forEach(function (opt) { if (typeof opt === 'number') { maxBodyLength = opt; return; } if (TypeGuard_1.isObject(opt)) { maxFuncBodyLength = opt[FUNC_BODY_LENGTH]; maxFuncExpressionBodyLength = opt[FUNC_EXPRESSION_BODY_LENGTH]; maxArrowBodyLength = opt[ARROW_BODY_LENGTH]; maxMethodBodyLength = opt[METHOD_BODY_LENGTH]; maxCtorBodyLength = opt[CTOR_BODY_LENGTH]; ignoreComments = !!opt[IGNORE_COMMENTS]; var regex = opt[IGNORE_PARAMETERS_TO_FUNCTION]; if (regex) { ignoreParametersToFunctionRegex = new RegExp(regex); } } }); } return { maxBodyLength: maxBodyLength, maxFuncBodyLength: maxFuncBodyLength, maxFuncExpressionBodyLength: maxFuncExpressionBodyLength, maxArrowBodyLength: maxArrowBodyLength, maxMethodBodyLength: maxMethodBodyLength, maxCtorBodyLength: maxCtorBodyLength, ignoreComments: ignoreComments, ignoreParametersToFunctionRegex: ignoreParametersToFunctionRegex }; }; Rule.metadata = { ruleName: 'max-func-body-length', type: 'maintainability', description: 'Avoid long functions.', options: null, optionsDescription: '', typescriptOnly: true, issueClass: 'Non-SDL', issueType: 'Warning', severity: 'Moderate', level: 'Opportunity for Excellence', group: 'Clarity', recommendation: '[true, 100, { "ignore-parameters-to-function-regex": "^describe$" }]', commonWeaknessEnumeration: '398, 710' }; return Rule; }(Lint.Rules.AbstractRule)); exports.Rule = Rule; var FUNC_BODY_LENGTH = 'func-body-length'; var FUNC_EXPRESSION_BODY_LENGTH = 'func-express-body-length'; var ARROW_BODY_LENGTH = 'arrow-body-length'; var METHOD_BODY_LENGTH = 'method-body-length'; var CTOR_BODY_LENGTH = 'ctor-body-length'; var IGNORE_PARAMETERS_TO_FUNCTION = 'ignore-parameters-to-function-regex'; var IGNORE_COMMENTS = 'ignore-comments'; function walk(ctx) { var _a = ctx.options, maxBodyLength = _a.maxBodyLength, maxFuncBodyLength = _a.maxFuncBodyLength, maxFuncExpressionBodyLength = _a.maxFuncExpressionBodyLength, maxArrowBodyLength = _a.maxArrowBodyLength, maxMethodBodyLength = _a.maxMethodBodyLength, maxCtorBodyLength = _a.maxCtorBodyLength, ignoreComments = _a.ignoreComments, ignoreParametersToFunctionRegex = _a.ignoreParametersToFunctionRegex; var ignoreNodes = []; var currentClassName; function calcBodyLength(node) { if (node.body === undefined) { return 0; } var sourceFile = ctx.sourceFile; var startLine = sourceFile.getLineAndCharacterOfPosition(node.body.pos).line; var endLine = sourceFile.getLineAndCharacterOfPosition(node.body.end).line; return endLine - startLine + 1; } function calcBodyCommentLength(node) { var commentLineCount = 0; commentLineCount += node .getFullText() .split(/\n/) .filter(function (line) { return line.trim().match(/^\/\//) !== null; }).length; tsutils.forEachTokenWithTrivia(node, function (text, tokenSyntaxKind) { if (tokenSyntaxKind === ts.SyntaxKind.MultiLineCommentTrivia) { commentLineCount += text.split(/\n/).length; } }); return commentLineCount; } function isFunctionTooLong(nodeKind, length) { return length > getMaxLength(nodeKind); } function getMaxLength(nodeKind) { var result; switch (nodeKind) { case ts.SyntaxKind.FunctionDeclaration: result = maxFuncBodyLength; break; case ts.SyntaxKind.FunctionExpression: result = maxFuncExpressionBodyLength; break; case ts.SyntaxKind.MethodDeclaration: result = maxMethodBodyLength; break; case ts.SyntaxKind.ArrowFunction: result = maxArrowBodyLength; break; case ts.SyntaxKind.Constructor: result = maxCtorBodyLength; break; default: throw new Error("Unsupported node kind: " + nodeKind); } return result || maxBodyLength; } function addFuncBodyTooLongFailure(node, length) { ctx.addFailureAt(node.getStart(), node.getWidth(), formatFailureText(node, length)); } function formatFailureText(node, length) { var funcTypeText = getFuncTypeText(node.kind); var maxLength = getMaxLength(node.kind); var placeText = formatPlaceText(node); return "Max " + funcTypeText + " body length exceeded" + placeText + " - max: " + maxLength + ", actual: " + length; } function formatPlaceText(node) { var funcTypeText = getFuncTypeText(node.kind); if (ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) { return " in " + funcTypeText + " " + (node.name ? node.name.getText() : '') + "()"; } if (node.kind === ts.SyntaxKind.Constructor) { return " in class " + currentClassName; } return ''; } function getFuncTypeText(nodeKind) { switch (nodeKind) { case ts.SyntaxKind.FunctionDeclaration: return 'function'; case ts.SyntaxKind.FunctionExpression: return 'function expression'; case ts.SyntaxKind.MethodDeclaration: return 'method'; case ts.SyntaxKind.ArrowFunction: return 'arrow function'; case ts.SyntaxKind.Constructor: return 'constructor'; default: throw new Error("Unsupported node kind: " + nodeKind); } } function validate(node) { if (!Utils_1.Utils.contains(ignoreNodes, node)) { var bodyLength = calcBodyLength(node); if (ignoreComments) { bodyLength -= calcBodyCommentLength(node); } if (isFunctionTooLong(node.kind, bodyLength)) { addFuncBodyTooLongFailure(node, bodyLength); } } } function cb(node) { if (tsutils.isCallExpression(node)) { var functionName = AstUtils_1.AstUtils.getFunctionName(node); if (ignoreParametersToFunctionRegex && ignoreParametersToFunctionRegex.test(functionName)) { node.arguments.forEach(function (argument) { ignoreNodes.push(argument); }); } } if (tsutils.isArrowFunction(node) || tsutils.isMethodDeclaration(node) || tsutils.isFunctionDeclaration(node) || tsutils.isFunctionExpression(node) || tsutils.isConstructorDeclaration(node)) { validate(node); } if (tsutils.isClassDeclaration(node)) { currentClassName = (node.name && node.name.text) || 'default'; } return ts.forEachChild(node, cb); } return ts.forEachChild(ctx.sourceFile, cb); } //# sourceMappingURL=maxFuncBodyLengthRule.js.map