@@ -31,8 +31,8 @@ namespace ts.formatting {
3131 * the first token in line so it should be indented
3232 */
3333 interface DynamicIndentation {
34- getIndentationForToken ( tokenLine : number , tokenKind : SyntaxKind ) : number ;
35- getIndentationForComment ( owningToken : SyntaxKind , tokenIndentation : number ) : number ;
34+ getIndentationForToken ( tokenLine : number , tokenKind : SyntaxKind , container : Node ) : number ;
35+ getIndentationForComment ( owningToken : SyntaxKind , tokenIndentation : number , container : Node ) : number ;
3636 /**
3737 * Indentation for open and close tokens of the node if it is block or another node that needs special indentation
3838 * ... {
@@ -54,7 +54,7 @@ namespace ts.formatting {
5454 * so bar inherits indentation from foo and bar.delta will be 4
5555 *
5656 */
57- getDelta ( ) : number ;
57+ getDelta ( child : TextRangeWithKind ) : number ;
5858 /**
5959 * Formatter calls this function when rule adds or deletes new lines from the text
6060 * so indentation scope can adjust values of indentation and delta.
@@ -282,19 +282,19 @@ namespace ts.formatting {
282282 */
283283 function getOwnOrInheritedDelta ( n : Node , options : FormatCodeOptions , sourceFile : SourceFile ) : number {
284284 let previousLine = Constants . Unknown ;
285- let childKind = SyntaxKind . Unknown ;
285+ let child : Node ;
286286 while ( n ) {
287287 let line = sourceFile . getLineAndCharacterOfPosition ( n . getStart ( sourceFile ) ) . line ;
288288 if ( previousLine !== Constants . Unknown && line !== previousLine ) {
289289 break ;
290290 }
291291
292- if ( SmartIndenter . shouldIndentChildNode ( n . kind , childKind ) ) {
292+ if ( SmartIndenter . shouldIndentChildNode ( n , child ) ) {
293293 return options . IndentSize ;
294294 }
295295
296296 previousLine = line ;
297- childKind = n . kind ;
297+ child = n ;
298298 n = n . parent ;
299299 }
300300 return 0 ;
@@ -386,34 +386,7 @@ namespace ts.formatting {
386386 effectiveParentStartLine : number ) : Indentation {
387387
388388 let indentation = inheritedIndentation ;
389- if ( indentation === Constants . Unknown ) {
390- if ( isSomeBlock ( node . kind ) ) {
391- // blocks should be indented in
392- // - other blocks
393- // - source file
394- // - switch\default clauses
395- if ( isSomeBlock ( parent . kind ) ||
396- parent . kind === SyntaxKind . SourceFile ||
397- parent . kind === SyntaxKind . CaseClause ||
398- parent . kind === SyntaxKind . DefaultClause ) {
399-
400- indentation = parentDynamicIndentation . getIndentation ( ) + parentDynamicIndentation . getDelta ( ) ;
401- }
402- else {
403- indentation = parentDynamicIndentation . getIndentation ( ) ;
404- }
405- }
406- else {
407- if ( SmartIndenter . childStartsOnTheSameLineWithElseInIfStatement ( parent , node , startLine , sourceFile ) ) {
408- indentation = parentDynamicIndentation . getIndentation ( ) ;
409- }
410- else {
411- indentation = parentDynamicIndentation . getIndentation ( ) + parentDynamicIndentation . getDelta ( ) ;
412- }
413- }
414- }
415-
416- var delta = SmartIndenter . shouldIndentChildNode ( node . kind , SyntaxKind . Unknown ) ? options . IndentSize : 0 ;
389+ var delta = SmartIndenter . shouldIndentChildNode ( node ) ? options . IndentSize : 0 ;
417390
418391 if ( effectiveParentStartLine === startLine ) {
419392 // if node is located on the same line with the parent
@@ -422,8 +395,17 @@ namespace ts.formatting {
422395 indentation = startLine === lastIndentedLine
423396 ? indentationOnLastIndentedLine
424397 : parentDynamicIndentation . getIndentation ( ) ;
425- delta = Math . min ( options . IndentSize , parentDynamicIndentation . getDelta ( ) + delta ) ;
398+ delta = Math . min ( options . IndentSize , parentDynamicIndentation . getDelta ( node ) + delta ) ;
426399 }
400+ else if ( indentation === Constants . Unknown ) {
401+ if ( SmartIndenter . childStartsOnTheSameLineWithElseInIfStatement ( parent , node , startLine , sourceFile ) ) {
402+ indentation = parentDynamicIndentation . getIndentation ( ) ;
403+ }
404+ else {
405+ indentation = parentDynamicIndentation . getIndentation ( ) + parentDynamicIndentation . getDelta ( node ) ;
406+ }
407+ }
408+
427409 return {
428410 indentation,
429411 delta
@@ -455,7 +437,7 @@ namespace ts.formatting {
455437
456438 function getDynamicIndentation ( node : Node , nodeStartLine : number , indentation : number , delta : number ) : DynamicIndentation {
457439 return {
458- getIndentationForComment : ( kind , tokenIndentation ) => {
440+ getIndentationForComment : ( kind , tokenIndentation , container ) => {
459441 switch ( kind ) {
460442 // preceding comment to the token that closes the indentation scope inherits the indentation from the scope
461443 // .. {
@@ -464,11 +446,11 @@ namespace ts.formatting {
464446 case SyntaxKind . CloseBraceToken :
465447 case SyntaxKind . CloseBracketToken :
466448 case SyntaxKind . CloseParenToken :
467- return indentation + delta ;
449+ return indentation + getEffectiveDelta ( delta , container ) ;
468450 }
469451 return tokenIndentation !== Constants . Unknown ? tokenIndentation : indentation ;
470452 } ,
471- getIndentationForToken : ( line , kind ) => {
453+ getIndentationForToken : ( line , kind , container ) => {
472454 if ( nodeStartLine !== line && node . decorators ) {
473455 if ( kind === getFirstNonDecoratorTokenOfNode ( node ) ) {
474456 // if this token is the first token following the list of decorators, we do not need to indent
@@ -489,28 +471,33 @@ namespace ts.formatting {
489471 return indentation ;
490472 default :
491473 // if token line equals to the line of containing node (this is a first token in the node) - use node indentation
492- return nodeStartLine !== line ? indentation + delta : indentation ;
474+ return nodeStartLine !== line ? indentation + getEffectiveDelta ( delta , container ) : indentation ;
493475 }
494476 } ,
495477 getIndentation : ( ) => indentation ,
496- getDelta : ( ) => delta ,
478+ getDelta : child => getEffectiveDelta ( delta , child ) ,
497479 recomputeIndentation : lineAdded => {
498- if ( node . parent && SmartIndenter . shouldIndentChildNode ( node . parent . kind , node . kind ) ) {
480+ if ( node . parent && SmartIndenter . shouldIndentChildNode ( node . parent , node ) ) {
499481 if ( lineAdded ) {
500482 indentation += options . IndentSize ;
501483 }
502484 else {
503485 indentation -= options . IndentSize ;
504486 }
505487
506- if ( SmartIndenter . shouldIndentChildNode ( node . kind , SyntaxKind . Unknown ) ) {
488+ if ( SmartIndenter . shouldIndentChildNode ( node ) ) {
507489 delta = options . IndentSize ;
508490 }
509491 else {
510492 delta = 0 ;
511493 }
512494 }
513- } ,
495+ }
496+ }
497+
498+ function getEffectiveDelta ( delta : number , child : TextRangeWithKind ) {
499+ // Delta value should be zero when the node explicitly prevents indentation of the child node
500+ return SmartIndenter . nodeWillIndentChild ( node , child , true ) ? delta : 0 ;
514501 }
515502 }
516503
@@ -610,7 +597,7 @@ namespace ts.formatting {
610597 // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
611598 let tokenInfo = formattingScanner . readTokenInfo ( child ) ;
612599 Debug . assert ( tokenInfo . token . end === child . end ) ;
613- consumeTokenAndAdvanceScanner ( tokenInfo , node , parentDynamicIndentation ) ;
600+ consumeTokenAndAdvanceScanner ( tokenInfo , node , parentDynamicIndentation , child ) ;
614601 return inheritedIndentation ;
615602 }
616603
@@ -679,7 +666,7 @@ namespace ts.formatting {
679666 }
680667 }
681668
682- function consumeTokenAndAdvanceScanner ( currentTokenInfo : TokenInfo , parent : Node , dynamicIndentation : DynamicIndentation ) : void {
669+ function consumeTokenAndAdvanceScanner ( currentTokenInfo : TokenInfo , parent : Node , dynamicIndentation : DynamicIndentation , container ?: Node ) : void {
683670 Debug . assert ( rangeContainsRange ( parent , currentTokenInfo . token ) ) ;
684671
685672 let lastTriviaWasNewLine = formattingScanner . lastTrailingTriviaWasNewLine ( ) ;
@@ -720,11 +707,11 @@ namespace ts.formatting {
720707
721708 if ( indentToken ) {
722709 let tokenIndentation = ( isTokenInRange && ! rangeContainsError ( currentTokenInfo . token ) ) ?
723- dynamicIndentation . getIndentationForToken ( tokenStart . line , currentTokenInfo . token . kind ) :
710+ dynamicIndentation . getIndentationForToken ( tokenStart . line , currentTokenInfo . token . kind , container ) :
724711 Constants . Unknown ;
725712
726713 if ( currentTokenInfo . leadingTrivia ) {
727- let commentIndentation = dynamicIndentation . getIndentationForComment ( currentTokenInfo . token . kind , tokenIndentation ) ;
714+ let commentIndentation = dynamicIndentation . getIndentationForComment ( currentTokenInfo . token . kind , tokenIndentation , container ) ;
728715 let indentNextTokenOrTrivia = true ;
729716
730717 for ( let triviaItem of currentTokenInfo . leadingTrivia ) {
0 commit comments