@@ -38,6 +38,19 @@ namespace ts.textChanges {
3838 return skipTrivia ( text , start , /*stopAfterLineBreak*/ false , /*stopAtComments*/ true ) ;
3939 }
4040
41+ function hasCommentsBeforeLineBreak ( text : string , start : number ) {
42+ let i = start ;
43+ while ( i < text . length ) {
44+ const ch = text . charCodeAt ( i ) ;
45+ if ( isWhiteSpaceSingleLine ( ch ) ) {
46+ i ++ ;
47+ continue ;
48+ }
49+ return ch === CharacterCodes . slash ;
50+ }
51+ return false ;
52+ }
53+
4154 function getPosition ( node : Node , sourceFile : SourceFile , position : Position ) {
4255 switch ( position ) {
4356 case Position . FullStart :
@@ -269,16 +282,39 @@ namespace ts.textChanges {
269282 if ( index < 0 ) {
270283 return this ;
271284 }
285+ const end = after . getEnd ( ) ;
272286 if ( containingList . length === 1 ) {
273- // list with one element - format as single line
274- const endPosition = getAdjustedEndPosition ( sourceFile , after , options ) ;
275- this . changes . push ( {
276- sourceFile,
277- range : { pos : endPosition , end : endPosition } ,
278- node : newNode ,
279- useIndentationFromFile : true ,
280- options : { prefix : ", " }
281- } ) ;
287+ // list with one element
288+ // check if element has non-whitespace only trailing trivia
289+ // if yes - format list as multiline
290+ // if no - format as singleline
291+ if ( ! hasCommentsBeforeLineBreak ( sourceFile . text , end ) ) {
292+ // format as single line
293+ this . changes . push ( {
294+ sourceFile,
295+ range : { pos : end , end } ,
296+ node : newNode ,
297+ useIndentationFromFile : true ,
298+ options : { prefix : ", " }
299+ } ) ;
300+ }
301+ else {
302+ const adjustedEndPosition = getAdjustedEndPosition ( sourceFile , after , options ) ;
303+ // format as multiline
304+ // 1. insert comma after 'after' node
305+ this . changes . push ( {
306+ sourceFile,
307+ range : { pos : end , end } ,
308+ node : createToken ( SyntaxKind . CommaToken ) ,
309+ options : { }
310+ } ) ;
311+ this . changes . push ( {
312+ sourceFile,
313+ range : { pos : adjustedEndPosition , end : adjustedEndPosition } ,
314+ node : newNode ,
315+ options : { }
316+ } ) ;
317+ }
282318 }
283319 else if ( index !== containingList . length - 1 ) {
284320 // any element except the last one
@@ -335,29 +371,47 @@ namespace ts.textChanges {
335371 // - determine if list is a multiline
336372 const afterMinusOne = containingList [ index - 1 ] ;
337373 const separatorBefore = < Token < SyntaxKind . CommaToken | SyntaxKind . SemicolonToken > > getSeparator ( sourceFile , afterMinusOne ) ;
338- const endPosition = getAdjustedEndPosition ( sourceFile , after , options ) ;
339- const range = { pos : endPosition , end : endPosition } ;
374+ const end = after . getEnd ( ) ;
340375 const afterMinusOneStartLinePosition = getLineStartPositionForPosition ( afterMinusOne . getStart ( sourceFile ) , sourceFile ) ;
341376 const afterStart = after . getStart ( sourceFile ) ;
342377 const afterStartLinePosition = getLineStartPositionForPosition ( afterStart , sourceFile ) ;
378+ let prefix = "" ;
379+ // insert separator following 'after item' if 'after' has some trailing trivia
380+ if ( hasCommentsBeforeLineBreak ( sourceFile . text , after . end ) ) {
381+ this . changes . push ( {
382+ sourceFile,
383+ range : { pos : end , end } ,
384+ node : separatorBefore ,
385+ options : { }
386+ } ) ;
387+ }
388+ else {
389+ // prepend separtor to prefix
390+ prefix = getSeparatorCharacter ( separatorBefore ) ;
391+ }
343392 if ( afterMinusOneStartLinePosition !== afterStartLinePosition ) {
344393 // multiline list
345394 // use the same indentation as 'after' item
395+ let p = skipTrivia ( sourceFile . text , end , /*stopAfterLineBreak*/ true , /*stopAtComments*/ false ) ;
396+ if ( p !== end && isLineBreak ( sourceFile . text . charCodeAt ( p - 1 ) ) ) {
397+ p --
398+ }
346399 const indentation = formatting . SmartIndenter . findFirstNonWhitespaceColumn ( afterStartLinePosition , afterStart , sourceFile , this . rulesProvider . getFormatOptions ( ) ) ;
347400 this . changes . push ( {
348401 sourceFile,
349- range,
402+ range : { pos : p , end : p } ,
350403 node : newNode ,
351- options : { prefix : `${ getSeparatorCharacter ( separatorBefore ) } ${ this . newLineCharacter } ` , indentation } ,
404+ options : { prefix : `${ prefix } ${ this . newLineCharacter } ` , indentation } ,
352405 } ) ;
353406 }
354407 else {
408+ //const adjustedEndPosition = getAdjustedEndPosition(sourceFile, after, options);
355409 // single line list
356410 this . changes . push ( {
357411 sourceFile,
358- range,
412+ range : { pos : end , end : end } ,
359413 node : newNode ,
360- options : { prefix : `${ getSeparatorCharacter ( separatorBefore ) } ` } , // ensure that new item is separate from previous item by one whitespace
414+ options : { prefix : `${ prefix } ` } , // ensure that new item is separate from previous item by one whitespace
361415 } )
362416 }
363417 }
0 commit comments