diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c9d8b6af5c0..7030b3baaa8 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4070,6 +4070,12 @@ namespace ts { return { start, length }; } + /* @internal */ + export function createTextRange(pos: number, end: number = pos): TextRange { + Debug.assert(end >= pos); + return { pos, end }; + } + export function createTextSpanFromBounds(start: number, end: number) { return createTextSpan(start, end - start); } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index a01eedfcb40..2c466cc01ee 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -317,8 +317,7 @@ namespace ts.textChanges { } private insertNodeAt(sourceFile: SourceFile, pos: number, newNode: Node, options: InsertNodeOptions = {}) { - this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile, options, node: newNode, range: { pos, end: pos } }); - return this; + this.replaceRange(sourceFile, createTextRange(pos), newNode, options); } private insertNodesAt(sourceFile: SourceFile, pos: number, newNodes: ReadonlyArray, options: InsertNodeOptions = {}): void { @@ -446,17 +445,11 @@ namespace ts.textChanges { // check if previous statement ends with semicolon // if not - insert semicolon to preserve the code from changing the meaning due to ASI if (sourceFile.text.charCodeAt(after.end - 1) !== CharacterCodes.semicolon) { - this.changes.push({ - kind: ChangeKind.ReplaceWithSingleNode, - sourceFile, - options: {}, - range: { pos: after.end, end: after.end }, - node: createToken(SyntaxKind.SemicolonToken) - }); + this.replaceRange(sourceFile, createTextRange(after.end), createToken(SyntaxKind.SemicolonToken)); } } const endPosition = getAdjustedEndPosition(sourceFile, after, {}); - return this.replaceRange(sourceFile, { pos: endPosition, end: endPosition }, newNode, this.getInsertNodeAfterOptions(after)); + return this.replaceRange(sourceFile, createTextRange(endPosition), newNode, this.getInsertNodeAfterOptions(after)); } private getInsertNodeAfterOptions(node: Node): InsertNodeOptions { @@ -540,17 +533,9 @@ namespace ts.textChanges { startPos = getStartPositionOfLine(lineAndCharOfNextElement.line, sourceFile); } - this.changes.push({ - kind: ChangeKind.ReplaceWithSingleNode, - sourceFile, - range: { pos: startPos, end: containingList[index + 1].getStart(sourceFile) }, - node: newNode, - options: { - prefix, - // write separator and leading trivia of the next element as suffix - suffix: `${tokenToString(nextToken.kind)}${sourceFile.text.substring(nextToken.end, containingList[index + 1].getStart(sourceFile))}` - } - }); + // write separator and leading trivia of the next element as suffix + const suffix = `${tokenToString(nextToken.kind)}${sourceFile.text.substring(nextToken.end, containingList[index + 1].getStart(sourceFile))}`; + this.replaceRange(sourceFile, createTextRange(startPos, containingList[index + 1].getStart(sourceFile)), newNode, { prefix, suffix }); } } else { @@ -584,13 +569,7 @@ namespace ts.textChanges { } if (multilineList) { // insert separator immediately following the 'after' node to preserve comments in trailing trivia - this.changes.push({ - kind: ChangeKind.ReplaceWithSingleNode, - sourceFile, - range: { pos: end, end }, - node: createToken(separator), - options: {} - }); + this.replaceRange(sourceFile, createTextRange(end), createToken(separator)); // use the same indentation as 'after' item const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options); // insert element before the line break on the line that contains 'after' element @@ -598,22 +577,10 @@ namespace ts.textChanges { if (insertPos !== end && isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) { insertPos--; } - this.changes.push({ - kind: ChangeKind.ReplaceWithSingleNode, - sourceFile, - range: { pos: insertPos, end: insertPos }, - node: newNode, - options: { indentation, prefix: this.newLineCharacter } - }); + this.replaceRange(sourceFile, createTextRange(insertPos), newNode, { indentation, prefix: this.newLineCharacter }); } else { - this.changes.push({ - kind: ChangeKind.ReplaceWithSingleNode, - sourceFile, - range: { pos: end, end }, - node: newNode, - options: { prefix: `${tokenToString(separator)} ` } - }); + this.replaceRange(sourceFile, createTextRange(end), newNode, { prefix: `${tokenToString(separator)} ` }); } } return this;