UNPKG

@xtrek/ts-migrate-plugins

Version:

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

94 lines 3.68 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 updateSourceText_1 = __importDefault(require("../../utils/updateSourceText")); /** * Tracks updates to a ts.SourceFile as text changes. * This is useful to preserve as much of the original whitespace in the source * file as possible. Re-printing the entire file causes blank lines to be lost. * * See: https://github.com/microsoft/TypeScript/issues/843 */ class UpdateTracker { constructor(sourceFile) { this.sourceFile = sourceFile; this.updates = []; this.printer = typescript_1.default.createPrinter(); } insert(pos, text) { this.updates.push({ kind: 'insert', index: pos, text, }); } /** * Adds a return type annotation to a function. * replaceNode would require reprinting the entire function body, losing all whitespace details. */ addReturnAnnotation(node, type) { const paren = node .getChildren(this.sourceFile) .find((node) => node.kind === typescript_1.default.SyntaxKind.CloseParenToken); let pos; if (paren) { pos = paren.pos + 1; } else { // Must be an arrow function with single parameter and no parentheses. // Add parentheses. pos = node.parameters.end; const [param] = node.parameters; this.insert(param.getStart(), '('); this.insert(pos, ')'); } const text = this.printer.printNode(typescript_1.default.EmitHint.Unspecified, type, this.sourceFile); this.insert(pos, `: ${text}`); } insertNodes(pos, nodes) { const text = this.printer.printList(typescript_1.default.ListFormat.SpaceAfterList, nodes, this.sourceFile); this.insert(pos, text); } replace(pos, length, text) { this.updates.push({ kind: 'replace', index: pos, length, text, }); } replaceNode(oldNode, newNode) { if (oldNode && newNode && oldNode !== newNode) { const printedNextNode = this.printer.printNode(typescript_1.default.EmitHint.Unspecified, newNode, this.sourceFile); const text = oldNode .getFullText(this.sourceFile) .replace(/^(\s*)[^]*?(\s*)$/, `$1${printedNextNode}$2`); this.updates.push({ kind: 'replace', index: oldNode.pos, length: oldNode.end - oldNode.pos, text, }); } } replaceNodes(oldNodes, newNodes, addParens = false) { if (oldNodes !== newNodes) { const listFormat = addParens ? typescript_1.default.ListFormat.Parenthesis : typescript_1.default.ListFormat.CommaListElements; const printedNextNode = this.printer.printList(listFormat, newNodes, this.sourceFile); const prevText = this.sourceFile.text.substring(oldNodes.pos, oldNodes.end); const text = prevText.replace(/^(\s*)[^]*?(\s*)$/, `$1${printedNextNode}$2`); this.replace(oldNodes.pos, oldNodes.end - oldNodes.pos, text); } } /** * Returns the result of applying all tracked changes to the source file. */ apply() { return updateSourceText_1.default(this.sourceFile.text, this.updates); } } exports.default = UpdateTracker; //# sourceMappingURL=update.js.map