UNPKG

tslint-react-set-state-usage

Version:

TSLint rule for detection non-functional setState statements

85 lines 3.98 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var 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 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_1 = require("tsutils"); var tslintReactSetStateUsageOptions_1 = require("./tslintReactSetStateUsageOptions"); var syntaxWalkerUtils_1 = require("../utils/syntaxWalkerUtils"); var FAILURE_STRING = "Do not pass an object into setState. Use functional setState updater instead."; var FAILURE_STRING_UPDATER_ONLY = "Do not use callback parameter in setState. Use componentDidUpdate method instead (\"" + tslintReactSetStateUsageOptions_1.OPTION_UPDATER_ONLY + "\" switch)."; var getFailureStringForAccessedMember = function (accessedMember) { return "Do not access 'this." + accessedMember + "' in setState. Use arguments from callback function instead."; }; var Rule = (function (_super) { __extends(Rule, _super); function Rule() { return _super !== null && _super.apply(this, arguments) || this; } Rule.prototype.apply = function (sourceFile) { var options = tslintReactSetStateUsageOptions_1.parseOptions(this.ruleArguments); return this.applyWithFunction(sourceFile, walk, options); }; return Rule; }(Lint.Rules.AbstractRule)); Rule.metadata = { description: "Requires the setState function to be called with function as the first argument and without 'this.props' nor 'this.state' access within the function.", optionExamples: [true], options: { items: [ { enum: [tslintReactSetStateUsageOptions_1.OPTION_UPDATER_ONLY], type: "string", }, ], maxLength: 1, minLength: 0, type: "array", }, optionsDescription: "Not configurable.", ruleName: "tslint-react-set-state-usage", type: "functionality", typescriptOnly: false, }; exports.Rule = Rule; function walk(ctx) { var sourceFile = ctx.sourceFile, updaterOnly = ctx.options.updaterOnly; function cb(node) { if (syntaxWalkerUtils_1.isThisSetState(node)) { inspectSetStateCall(node, ctx, updaterOnly); } else if (isThisState(node) || isThisProps(node)) { inspectThisPropsOrStateContext(node, ctx); } return ts.forEachChild(node, cb); } return ts.forEachChild(sourceFile, cb); } function inspectSetStateCall(node, ctx, updaterOnly) { var _a = node.arguments, updaterArgument = _a[0], callbackArgument = _a[1], argumentsCount = _a.length; // Forbid object literal var bareUpdaterArgument = syntaxWalkerUtils_1.removeParentheses(updaterArgument); if (tsutils_1.isObjectLiteralExpression(bareUpdaterArgument)) { ctx.addFailureAtNode(updaterArgument, FAILURE_STRING); } // Forbid second argument if updaterOnly flag set if (updaterOnly && argumentsCount > 1) { ctx.addFailureAtNode(callbackArgument, FAILURE_STRING_UPDATER_ONLY); } } function inspectThisPropsOrStateContext(node, ctx) { var setStateCall = syntaxWalkerUtils_1.getFirstSetStateAncestor(node.parent); if (setStateCall) { ctx.addFailureAtNode(node, getFailureStringForAccessedMember(node.name.text)); } } var isThisState = function (node) { return syntaxWalkerUtils_1.isThisPropertyAccess(node) && node.name.text === "state"; }; var isThisProps = function (node) { return syntaxWalkerUtils_1.isThisPropertyAccess(node) && node.name.text === "props"; }; //# sourceMappingURL=tslintReactSetStateUsageRule.js.map