UNPKG

@xtrek/ts-migrate-plugins

Version:

Set of codemods, which are doing transformation of js/jsx to ts/tsx

98 lines 5.83 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const typescript_1 = __importDefault(require("typescript")); const react_1 = require("./utils/react"); const updateSourceText_1 = __importDefault(require("../utils/updateSourceText")); const validateOptions_1 = require("../utils/validateOptions"); const optionProperties = { force: { type: 'boolean' }, }; const reactClassLifecycleMethodsPlugin = { name: 'react-class-lifecycle-methods', run({ fileName, sourceFile, text, options }) { return /\.tsx$/.test(fileName) ? annotateReactComponentLifecycleMethods(sourceFile, text, options.force) : undefined; }, validate: validateOptions_1.createValidate(optionProperties), }; exports.default = reactClassLifecycleMethodsPlugin; var AnnotationKind; (function (AnnotationKind) { AnnotationKind["Props"] = "Props"; AnnotationKind["State"] = "State"; AnnotationKind["Context"] = "Context"; })(AnnotationKind || (AnnotationKind = {})); const reactLifecycleMethodAnnotations = { // shouldComponentUpdate?(nextProps: Readonly<P>, nextState: Readonly<S>, nextContext: any): boolean; shouldComponentUpdate: [AnnotationKind.Props, AnnotationKind.State, AnnotationKind.Context], // componentDidUpdate?(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot?: SS): void; componentDidUpdate: [AnnotationKind.Props, AnnotationKind.State], // componentWillReceiveProps?(nextProps: Readonly<P>, nextContext: any): void; componentWillReceiveProps: [AnnotationKind.Props, AnnotationKind.Context], // componentWillUpdate?(nextProps: Readonly<P>, nextState: Readonly<S>, nextContext: any): void; componentWillUpdate: [AnnotationKind.Props, AnnotationKind.State, AnnotationKind.Context], }; function updateParameterType(parameter, type) { return typescript_1.default.factory.updateParameterDeclaration(parameter, parameter.decorators, parameter.modifiers, parameter.dotDotDotToken, parameter.name, parameter.questionToken, type, parameter.initializer); } function annotateReactComponentLifecycleMethods(sourceFile, sourceText, force = false) { const printer = typescript_1.default.createPrinter(); const updates = []; sourceFile.statements.forEach((statement) => { if (typescript_1.default.isClassDeclaration(statement) && react_1.isReactClassComponent(statement)) { const heritageType = react_1.getReactComponentHeritageType(statement); const heritageTypeArgs = heritageType.typeArguments || []; const propsType = heritageTypeArgs[0] || typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.AnyKeyword); const stateType = heritageTypeArgs[1] || typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.AnyKeyword); const annotationToType = { [AnnotationKind.Props]: propsType, [AnnotationKind.State]: stateType, [AnnotationKind.Context]: typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.AnyKeyword), }; statement.members.forEach((member) => { if (typescript_1.default.isConstructorDeclaration(member) && member.parameters.length === 1 && (member.parameters[0].type == null || force)) { const parameter = member.parameters[0]; const updatedParameter = updateParameterType(parameter, propsType); updates.push({ kind: 'replace', index: parameter.pos, length: parameter.end - parameter.pos, text: printer.printNode(typescript_1.default.EmitHint.Unspecified, updatedParameter, sourceFile), }); } else if (typescript_1.default.isMethodDeclaration(member) && typescript_1.default.isIdentifier(member.name) && reactLifecycleMethodAnnotations[member.name.text] != null) { const annotations = reactLifecycleMethodAnnotations[member.name.text]; let didUpdateParameters = false; const parametersToPrint = [...member.parameters]; for (let i = 0; i < member.parameters.length; i += 1) { const parameter = member.parameters[i]; const annotation = annotationToType[annotations[i]]; if (annotation != null && (parameter.type == null || force)) { const updatedParameter = updateParameterType(parameter, annotation); parametersToPrint[i] = updatedParameter; didUpdateParameters = true; } } if (didUpdateParameters) { const start = member.parameters[0].pos; const { end } = member.parameters[member.parameters.length - 1]; let text = printer.printList(typescript_1.default.ListFormat.Parameters, typescript_1.default.factory.createNodeArray(parametersToPrint), sourceFile); // Remove surrounding parentheses text = text.slice(1, text.length - 1); updates.push({ kind: 'replace', index: start, length: end - start, text }); } } }); } }); return updateSourceText_1.default(sourceText, updates); } //# sourceMappingURL=react-class-lifecycle-methods.js.map