@@ -72,6 +72,11 @@ namespace ts.textChanges {
7272 */
7373 export type ConfigurableStartEnd = ConfigurableStart & ConfigurableEnd ;
7474
75+ export const useNonAdjustedPositions : ConfigurableStartEnd = {
76+ useNonAdjustedStartPosition : true ,
77+ useNonAdjustedEndPosition : true ,
78+ } ;
79+
7580 export interface InsertNodeOptions {
7681 /**
7782 * Text to be inserted before the new node
@@ -119,13 +124,10 @@ namespace ts.textChanges {
119124 readonly options ?: never ;
120125 }
121126
122- interface ChangeMultipleNodesOptions extends ChangeNodeOptions {
123- nodeSeparator : string ;
124- }
125127 interface ReplaceWithMultipleNodes extends BaseChange {
126128 readonly kind : ChangeKind . ReplaceWithMultipleNodes ;
127129 readonly nodes : ReadonlyArray < Node > ;
128- readonly options ?: ChangeMultipleNodesOptions ;
130+ readonly options ?: ChangeNodeOptions ;
129131 }
130132
131133 export function getSeparatorCharacter ( separator : Token < SyntaxKind . CommaToken | SyntaxKind . SemicolonToken > ) {
@@ -282,43 +284,38 @@ namespace ts.textChanges {
282284 return this ;
283285 }
284286
287+ // TODO (https://github.com/Microsoft/TypeScript/issues/21246): default should probably be useNonAdjustedPositions
285288 public replaceRange ( sourceFile : SourceFile , range : TextRange , newNode : Node , options : ChangeNodeOptions = { } ) {
286289 this . changes . push ( { kind : ChangeKind . ReplaceWithSingleNode , sourceFile, range, options, node : newNode } ) ;
287290 return this ;
288291 }
289292
293+ // TODO (https://github.com/Microsoft/TypeScript/issues/21246): default should probably be useNonAdjustedPositions
290294 public replaceNode ( sourceFile : SourceFile , oldNode : Node , newNode : Node , options : ChangeNodeOptions = { } ) {
291295 const pos = getAdjustedStartPosition ( sourceFile , oldNode , options , Position . Start ) ;
292296 const end = getAdjustedEndPosition ( sourceFile , oldNode , options ) ;
293297 return this . replaceRange ( sourceFile , { pos, end } , newNode , options ) ;
294298 }
295299
300+ // TODO (https://github.com/Microsoft/TypeScript/issues/21246): default should probably be useNonAdjustedPositions
296301 public replaceNodeRange ( sourceFile : SourceFile , startNode : Node , endNode : Node , newNode : Node , options : ChangeNodeOptions = { } ) {
297302 const pos = getAdjustedStartPosition ( sourceFile , startNode , options , Position . Start ) ;
298303 const end = getAdjustedEndPosition ( sourceFile , endNode , options ) ;
299304 return this . replaceRange ( sourceFile , { pos, end } , newNode , options ) ;
300305 }
301306
302- private getDefaultChangeMultipleNodesOptions ( ) : ChangeMultipleNodesOptions {
303- return {
304- nodeSeparator : this . newLineCharacter ,
305- useNonAdjustedStartPosition : true ,
306- useNonAdjustedEndPosition : true ,
307- } ;
308- }
309-
310- public replaceRangeWithNodes ( sourceFile : SourceFile , range : TextRange , newNodes : ReadonlyArray < Node > , options : ChangeMultipleNodesOptions = this . getDefaultChangeMultipleNodesOptions ( ) ) {
307+ public replaceRangeWithNodes ( sourceFile : SourceFile , range : TextRange , newNodes : ReadonlyArray < Node > , options : ChangeNodeOptions = useNonAdjustedPositions ) {
311308 this . changes . push ( { kind : ChangeKind . ReplaceWithMultipleNodes , sourceFile, range, options, nodes : newNodes } ) ;
312309 return this ;
313310 }
314311
315- public replaceNodeWithNodes ( sourceFile : SourceFile , oldNode : Node , newNodes : ReadonlyArray < Node > , options : ChangeMultipleNodesOptions = this . getDefaultChangeMultipleNodesOptions ( ) ) {
312+ public replaceNodeWithNodes ( sourceFile : SourceFile , oldNode : Node , newNodes : ReadonlyArray < Node > , options : ChangeNodeOptions = useNonAdjustedPositions ) {
316313 const pos = getAdjustedStartPosition ( sourceFile , oldNode , options , Position . Start ) ;
317314 const end = getAdjustedEndPosition ( sourceFile , oldNode , options ) ;
318315 return this . replaceRangeWithNodes ( sourceFile , { pos, end } , newNodes , options ) ;
319316 }
320317
321- public replaceNodeRangeWithNodes ( sourceFile : SourceFile , startNode : Node , endNode : Node , newNodes : ReadonlyArray < Node > , options : ChangeMultipleNodesOptions = this . getDefaultChangeMultipleNodesOptions ( ) ) {
318+ public replaceNodeRangeWithNodes ( sourceFile : SourceFile , startNode : Node , endNode : Node , newNodes : ReadonlyArray < Node > , options : ChangeNodeOptions = useNonAdjustedPositions ) {
322319 const pos = getAdjustedStartPosition ( sourceFile , startNode , options , Position . Start ) ;
323320 const end = getAdjustedEndPosition ( sourceFile , endNode , options ) ;
324321 return this . replaceRangeWithNodes ( sourceFile , { pos, end } , newNodes , options ) ;
@@ -640,8 +637,14 @@ namespace ts.textChanges {
640637 const pos = change . range . pos ;
641638 const posStartsLine = getLineStartPositionForPosition ( pos , sourceFile ) === pos ;
642639 if ( change . kind === ChangeKind . ReplaceWithMultipleNodes ) {
643- const parts = change . nodes . map ( n => this . getFormattedTextOfNode ( n , sourceFile , pos , options ) ) ;
644- text = parts . join ( change . options . nodeSeparator ) ;
640+ const lastIndex = change . nodes . length - 1 ;
641+ const parts = change . nodes . map ( ( n , index ) => {
642+ const formatted = this . getFormattedTextOfNode ( n , sourceFile , pos , options ) ;
643+ return index === lastIndex || endsWith ( formatted , this . newLineCharacter )
644+ ? formatted
645+ : ( formatted + this . newLineCharacter ) ;
646+ } ) ;
647+ text = parts . join ( "" ) ;
645648 }
646649 else {
647650 Debug . assert ( change . kind === ChangeKind . ReplaceWithSingleNode , "change.kind === ReplaceWithSingleNode" ) ;
0 commit comments