@@ -121,7 +121,7 @@ namespace ts.formatting {
121121
122122 function findOutermostParent ( position : number , expectedTokenKind : SyntaxKind , sourceFile : SourceFile ) : Node {
123123 let precedingToken = findPrecedingToken ( position , sourceFile ) ;
124-
124+
125125 // when it is claimed that trigger character was typed at given position
126126 // we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed).
127127 // If this condition is not hold - then trigger character was typed in some other context,
@@ -151,7 +151,7 @@ namespace ts.formatting {
151151
152152 return current ;
153153 }
154-
154+
155155 // Returns true if node is a element in some list in parent
156156 // i.e. parent is class declaration with the list of members and node is one of members.
157157 function isListElement ( parent : Node , node : Node ) : boolean {
@@ -198,7 +198,7 @@ namespace ts.formatting {
198198 if ( ! errors . length ) {
199199 return rangeHasNoErrors ;
200200 }
201-
201+
202202 // pick only errors that fall in range
203203 let sorted = errors
204204 . filter ( d => rangeOverlapsWithStartEnd ( originalRange , d . start , d . start + d . length ) )
@@ -340,6 +340,12 @@ namespace ts.formatting {
340340 let delta = getOwnOrInheritedDelta ( enclosingNode , options , sourceFile ) ;
341341 processNode ( enclosingNode , enclosingNode , startLine , undecoratedStartLine , initialIndentation , delta ) ;
342342 }
343+ else {
344+ let leadingTrivia = formattingScanner . readTokenInfo ( undefined ) . leadingTrivia ;
345+ if ( leadingTrivia ) {
346+ trimWhitespacesInEmptyLineTrivia ( leadingTrivia , true ) ;
347+ }
348+ }
343349
344350 formattingScanner . close ( ) ;
345351
@@ -445,7 +451,7 @@ namespace ts.formatting {
445451 if ( ( < MethodDeclaration > node ) . asteriskToken ) {
446452 return SyntaxKind . AsteriskToken ;
447453 }
448- // fall-through
454+ // fall-through
449455
450456 case SyntaxKind . PropertyDeclaration :
451457 case SyntaxKind . Parameter :
@@ -555,6 +561,13 @@ namespace ts.formatting {
555561 consumeTokenAndAdvanceScanner ( tokenInfo , node , nodeDynamicIndentation ) ;
556562 }
557563
564+ if ( ! formattingScanner . isOnToken ( ) ) {
565+ let leadingTrivia = formattingScanner . readTokenInfo ( node ) . leadingTrivia ;
566+ if ( leadingTrivia ) {
567+ trimWhitespacesInEmptyLineTrivia ( leadingTrivia , true ) ;
568+ }
569+ }
570+
558571 function processChildNode (
559572 child : Node ,
560573 inheritedIndentation : number ,
@@ -686,6 +699,7 @@ namespace ts.formatting {
686699 let indentToken = false ;
687700
688701 if ( currentTokenInfo . leadingTrivia ) {
702+ trimWhitespacesInEmptyLineTrivia ( currentTokenInfo . leadingTrivia , formattingScanner . lastTrailingTriviaWasNewLine ( ) ) ;
689703 processTrivia ( currentTokenInfo . leadingTrivia , parent , childContextNode , dynamicIndentation ) ;
690704 }
691705
@@ -838,8 +852,8 @@ namespace ts.formatting {
838852
839853 // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
840854 trimTrailingWhitespaces =
841- ( rule . Operation . Action & ( RuleAction . NewLine | RuleAction . Space ) ) &&
842- rule . Flag !== RuleFlags . CanDeleteNewLines ;
855+ ( rule . Operation . Action & ( RuleAction . NewLine | RuleAction . Space ) ) &&
856+ rule . Flag !== RuleFlags . CanDeleteNewLines ;
843857 }
844858 else {
845859 trimTrailingWhitespaces = true ;
@@ -949,6 +963,31 @@ namespace ts.formatting {
949963 }
950964 }
951965
966+ function trimWhitespacesInEmptyLineTrivia ( trivia : TextRangeWithKind [ ] , lastTraviaWasNewLine : boolean ) {
967+ let targetCandidate : TextRangeWithKind ;
968+
969+ for ( let triviaItem of trivia ) {
970+ switch ( triviaItem . kind ) {
971+ case SyntaxKind . WhitespaceTrivia :
972+ targetCandidate = lastTraviaWasNewLine ? triviaItem : undefined ;
973+ break ;
974+ case SyntaxKind . NewLineTrivia :
975+ if ( targetCandidate ) {
976+ recordDelete ( targetCandidate . pos , targetCandidate . end - targetCandidate . pos ) ;
977+ targetCandidate = undefined ;
978+ }
979+ break ;
980+ default :
981+ targetCandidate = undefined ;
982+ break ;
983+ }
984+ lastTraviaWasNewLine = triviaItem . kind === SyntaxKind . NewLineTrivia ;
985+ }
986+ if ( targetCandidate && targetCandidate . end === sourceFile . end ) {
987+ recordDelete ( targetCandidate . pos , targetCandidate . end - targetCandidate . pos ) ;
988+ }
989+ }
990+
952991 function newTextChange ( start : number , len : number , newText : string ) : TextChange {
953992 return { span : createTextSpan ( start , len ) , newText }
954993 }
0 commit comments