@@ -31,8 +31,8 @@ namespace ts.formatting {
31
31
* the first token in line so it should be indented
32
32
*/
33
33
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 ;
36
36
/**
37
37
* Indentation for open and close tokens of the node if it is block or another node that needs special indentation
38
38
* ... {
@@ -54,7 +54,7 @@ namespace ts.formatting {
54
54
* so bar inherits indentation from foo and bar.delta will be 4
55
55
*
56
56
*/
57
- getDelta ( ) : number ;
57
+ getDelta ( child : TextRangeWithKind ) : number ;
58
58
/**
59
59
* Formatter calls this function when rule adds or deletes new lines from the text
60
60
* so indentation scope can adjust values of indentation and delta.
@@ -282,19 +282,19 @@ namespace ts.formatting {
282
282
*/
283
283
function getOwnOrInheritedDelta ( n : Node , options : FormatCodeOptions , sourceFile : SourceFile ) : number {
284
284
let previousLine = Constants . Unknown ;
285
- let childKind = SyntaxKind . Unknown ;
285
+ let child : Node ;
286
286
while ( n ) {
287
287
let line = sourceFile . getLineAndCharacterOfPosition ( n . getStart ( sourceFile ) ) . line ;
288
288
if ( previousLine !== Constants . Unknown && line !== previousLine ) {
289
289
break ;
290
290
}
291
291
292
- if ( SmartIndenter . shouldIndentChildNode ( n . kind , childKind ) ) {
292
+ if ( SmartIndenter . shouldIndentChildNode ( n , child ) ) {
293
293
return options . IndentSize ;
294
294
}
295
295
296
296
previousLine = line ;
297
- childKind = n . kind ;
297
+ child = n ;
298
298
n = n . parent ;
299
299
}
300
300
return 0 ;
@@ -386,34 +386,7 @@ namespace ts.formatting {
386
386
effectiveParentStartLine : number ) : Indentation {
387
387
388
388
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 ;
417
390
418
391
if ( effectiveParentStartLine === startLine ) {
419
392
// if node is located on the same line with the parent
@@ -422,8 +395,17 @@ namespace ts.formatting {
422
395
indentation = startLine === lastIndentedLine
423
396
? indentationOnLastIndentedLine
424
397
: parentDynamicIndentation . getIndentation ( ) ;
425
- delta = Math . min ( options . IndentSize , parentDynamicIndentation . getDelta ( ) + delta ) ;
398
+ delta = Math . min ( options . IndentSize , parentDynamicIndentation . getDelta ( node ) + delta ) ;
426
399
}
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
+
427
409
return {
428
410
indentation,
429
411
delta
@@ -455,7 +437,7 @@ namespace ts.formatting {
455
437
456
438
function getDynamicIndentation ( node : Node , nodeStartLine : number , indentation : number , delta : number ) : DynamicIndentation {
457
439
return {
458
- getIndentationForComment : ( kind , tokenIndentation ) => {
440
+ getIndentationForComment : ( kind , tokenIndentation , container ) => {
459
441
switch ( kind ) {
460
442
// preceding comment to the token that closes the indentation scope inherits the indentation from the scope
461
443
// .. {
@@ -464,11 +446,11 @@ namespace ts.formatting {
464
446
case SyntaxKind . CloseBraceToken :
465
447
case SyntaxKind . CloseBracketToken :
466
448
case SyntaxKind . CloseParenToken :
467
- return indentation + delta ;
449
+ return indentation + getEffectiveDelta ( delta , container ) ;
468
450
}
469
451
return tokenIndentation !== Constants . Unknown ? tokenIndentation : indentation ;
470
452
} ,
471
- getIndentationForToken : ( line , kind ) => {
453
+ getIndentationForToken : ( line , kind , container ) => {
472
454
if ( nodeStartLine !== line && node . decorators ) {
473
455
if ( kind === getFirstNonDecoratorTokenOfNode ( node ) ) {
474
456
// 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 {
489
471
return indentation ;
490
472
default :
491
473
// 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 ;
493
475
}
494
476
} ,
495
477
getIndentation : ( ) => indentation ,
496
- getDelta : ( ) => delta ,
478
+ getDelta : child => getEffectiveDelta ( delta , child ) ,
497
479
recomputeIndentation : lineAdded => {
498
- if ( node . parent && SmartIndenter . shouldIndentChildNode ( node . parent . kind , node . kind ) ) {
480
+ if ( node . parent && SmartIndenter . shouldIndentChildNode ( node . parent , node ) ) {
499
481
if ( lineAdded ) {
500
482
indentation += options . IndentSize ;
501
483
}
502
484
else {
503
485
indentation -= options . IndentSize ;
504
486
}
505
487
506
- if ( SmartIndenter . shouldIndentChildNode ( node . kind , SyntaxKind . Unknown ) ) {
488
+ if ( SmartIndenter . shouldIndentChildNode ( node ) ) {
507
489
delta = options . IndentSize ;
508
490
}
509
491
else {
510
492
delta = 0 ;
511
493
}
512
494
}
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 ;
514
501
}
515
502
}
516
503
@@ -610,7 +597,7 @@ namespace ts.formatting {
610
597
// if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
611
598
let tokenInfo = formattingScanner . readTokenInfo ( child ) ;
612
599
Debug . assert ( tokenInfo . token . end === child . end ) ;
613
- consumeTokenAndAdvanceScanner ( tokenInfo , node , parentDynamicIndentation ) ;
600
+ consumeTokenAndAdvanceScanner ( tokenInfo , node , parentDynamicIndentation , child ) ;
614
601
return inheritedIndentation ;
615
602
}
616
603
@@ -679,7 +666,7 @@ namespace ts.formatting {
679
666
}
680
667
}
681
668
682
- function consumeTokenAndAdvanceScanner ( currentTokenInfo : TokenInfo , parent : Node , dynamicIndentation : DynamicIndentation ) : void {
669
+ function consumeTokenAndAdvanceScanner ( currentTokenInfo : TokenInfo , parent : Node , dynamicIndentation : DynamicIndentation , container ?: Node ) : void {
683
670
Debug . assert ( rangeContainsRange ( parent , currentTokenInfo . token ) ) ;
684
671
685
672
let lastTriviaWasNewLine = formattingScanner . lastTrailingTriviaWasNewLine ( ) ;
@@ -720,11 +707,11 @@ namespace ts.formatting {
720
707
721
708
if ( indentToken ) {
722
709
let tokenIndentation = ( isTokenInRange && ! rangeContainsError ( currentTokenInfo . token ) ) ?
723
- dynamicIndentation . getIndentationForToken ( tokenStart . line , currentTokenInfo . token . kind ) :
710
+ dynamicIndentation . getIndentationForToken ( tokenStart . line , currentTokenInfo . token . kind , container ) :
724
711
Constants . Unknown ;
725
712
726
713
if ( currentTokenInfo . leadingTrivia ) {
727
- let commentIndentation = dynamicIndentation . getIndentationForComment ( currentTokenInfo . token . kind , tokenIndentation ) ;
714
+ let commentIndentation = dynamicIndentation . getIndentationForComment ( currentTokenInfo . token . kind , tokenIndentation , container ) ;
728
715
let indentNextTokenOrTrivia = true ;
729
716
730
717
for ( let triviaItem of currentTokenInfo . leadingTrivia ) {
0 commit comments