@@ -1202,15 +1202,15 @@ namespace ts {
1202
1202
function emitWithContext < T extends Node > ( node : T , emitCallback : ( node : T ) => void ) {
1203
1203
onBeforeEmitNode ?.( node ) ;
1204
1204
1205
+ const emitFlags = getEmitFlags ( node ) ;
1205
1206
const savedPreserveSourceNewlines = preserveSourceNewlines ;
1206
- if ( preserveSourceNewlines && ! ! ( getEmitFlags ( node ) & EmitFlags . IgnoreSourceNewlines ) ) {
1207
+ if ( preserveSourceNewlines && ( emitFlags & EmitFlags . IgnoreSourceNewlines ) ) {
1207
1208
preserveSourceNewlines = false ;
1208
1209
}
1209
1210
1210
1211
const savedContainerPos = containerPos ;
1211
1212
const savedContainerEnd = containerEnd ;
1212
1213
const savedDeclarationListContainerEnd = declarationListContainerEnd ;
1213
- const emitFlags = getEmitFlags ( node ) ;
1214
1214
const commentRange = shouldEmitComments ( node ) ? getCommentRange ( node ) : undefined ;
1215
1215
const sourceMapRange = shouldEmitSourceMaps ( node ) ? getSourceMapRange ( node ) : undefined ;
1216
1216
@@ -2520,7 +2520,62 @@ namespace ts {
2520
2520
}
2521
2521
2522
2522
function createEmitBinaryExpression ( ) {
2523
- return createBinaryExpressionWalker ( noop , maybePipelineEmitExpression , onOperator , maybePipelineEmitExpression , onExit , identity ) ;
2523
+ class EmitBinaryExpressionState {
2524
+ nested = false ;
2525
+ preserveSourceNewlines : boolean | undefined = undefined ;
2526
+ containerPos = - 1 ;
2527
+ containerEnd = - 1 ;
2528
+ declarationListContainerEnd = - 1 ;
2529
+ emitFlags = EmitFlags . None ;
2530
+ commentRange : TextRange | undefined = undefined ;
2531
+ sourceMapRange : SourceMapRange | undefined = undefined ;
2532
+ }
2533
+
2534
+ return createBinaryExpressionWalker ( onEnter , maybeEmitExpression , onOperator , maybeEmitExpression , onExit , identity ) ;
2535
+
2536
+ function onEnter ( node : BinaryExpression , prev : EmitBinaryExpressionState | undefined ) {
2537
+ const state = new EmitBinaryExpressionState ( ) ;
2538
+ if ( prev ) {
2539
+ // `prev` is only defined when recuring. We can use this fact to indicate
2540
+ // we are entering into a nested binary expression and can replicate the
2541
+ // leading comment and sourcemap emit performed by `emitWithContext`.
2542
+ state . nested = true ;
2543
+ onBeforeEmitNode ?.( node ) ;
2544
+
2545
+ state . emitFlags = getEmitFlags ( node ) ;
2546
+ state . preserveSourceNewlines = preserveSourceNewlines ;
2547
+ if ( preserveSourceNewlines && ( state . emitFlags & EmitFlags . IgnoreSourceNewlines ) ) {
2548
+ preserveSourceNewlines = false ;
2549
+ }
2550
+
2551
+ state . containerPos = containerPos ;
2552
+ state . containerEnd = containerEnd ;
2553
+ state . declarationListContainerEnd = declarationListContainerEnd ;
2554
+ state . commentRange = shouldEmitComments ( node ) ? getCommentRange ( node ) : undefined ;
2555
+ state . sourceMapRange = shouldEmitSourceMaps ( node ) ? getSourceMapRange ( node ) : undefined ;
2556
+
2557
+ // Emit leading comments
2558
+ if ( state . commentRange ) {
2559
+ emitLeadingCommentsOfNode ( node , state . emitFlags , state . commentRange . pos , state . commentRange . end ) ;
2560
+ if ( state . emitFlags & EmitFlags . NoNestedComments ) {
2561
+ commentsDisabled = true ;
2562
+ }
2563
+ }
2564
+
2565
+ // Emit leading sourcemap
2566
+ if ( state . sourceMapRange ) {
2567
+ const source = state . sourceMapRange . source || sourceMapSource ;
2568
+ if ( ( state . emitFlags & EmitFlags . NoLeadingSourceMap ) === 0
2569
+ && state . sourceMapRange . pos >= 0 ) {
2570
+ emitSourcePos ( state . sourceMapRange . source || sourceMapSource , skipSourceTrivia ( source , state . sourceMapRange . pos ) ) ;
2571
+ }
2572
+ if ( state . emitFlags & EmitFlags . NoNestedSourceMaps ) {
2573
+ sourceMapsDisabled = true ;
2574
+ }
2575
+ }
2576
+ }
2577
+ return state ;
2578
+ }
2524
2579
2525
2580
function onOperator ( operatorToken : BinaryOperatorToken , _ : unknown , node : BinaryExpression ) {
2526
2581
const isCommaOperator = operatorToken . kind !== SyntaxKind . CommaToken ;
@@ -2533,25 +2588,48 @@ namespace ts {
2533
2588
writeLinesAndIndent ( linesAfterOperator , /*writeSpaceIfNotIndenting*/ true ) ;
2534
2589
}
2535
2590
2536
- function onExit ( node : BinaryExpression ) {
2591
+ function onExit ( node : BinaryExpression , state : EmitBinaryExpressionState ) {
2537
2592
const linesBeforeOperator = getLinesBetweenNodes ( node , node . left , node . operatorToken ) ;
2538
2593
const linesAfterOperator = getLinesBetweenNodes ( node , node . operatorToken , node . right ) ;
2539
2594
decreaseIndentIf ( linesBeforeOperator , linesAfterOperator ) ;
2540
- }
2541
2595
2542
- function maybePipelineEmitExpression ( next : Expression ) {
2543
- // Then actually do the work of emitting the node `next` returned by the prior state
2544
- // The following section should be identical to `pipelineEmit` save it assumes EmitHint.Expression and offloads
2545
- // binary expression handling, where possible, to the contained work queue
2596
+ if ( state . nested ) {
2597
+ // If we are marked as nested, we are recurring. We can use this fact to indicate
2598
+ // we are exiting from a nested binary expression and can replicate the trailing
2599
+ // comment and sourcemap emit performed by `emitWithContext`.
2546
2600
2547
- if ( ! shouldEmitComments ( next ) && ! shouldEmitSourceMaps ( next ) && isBinaryExpression ( next ) ) {
2548
- // If the target pipeline phase is emit directly, and the next node's also a binary expression,
2549
- // skip all the intermediate indirection and push the expression directly onto the work stack
2550
- return next ;
2601
+ // Emit trailing sourcemap
2602
+ if ( state . sourceMapRange ) {
2603
+ if ( state . emitFlags & EmitFlags . NoNestedSourceMaps ) {
2604
+ sourceMapsDisabled = false ;
2605
+ }
2606
+ if ( ( state . emitFlags & EmitFlags . NoTrailingSourceMap ) === 0
2607
+ && state . sourceMapRange . end >= 0 ) {
2608
+ emitSourcePos ( state . sourceMapRange . source || sourceMapSource , state . sourceMapRange . end ) ;
2609
+ }
2610
+ }
2611
+
2612
+ // Emit trailing comments
2613
+ if ( state . commentRange ) {
2614
+ if ( state . emitFlags & EmitFlags . NoNestedComments ) {
2615
+ commentsDisabled = false ;
2616
+ }
2617
+ emitTrailingCommentsOfNode ( node , state . emitFlags , state . commentRange . pos , state . commentRange . end , state . containerPos , state . containerEnd , state . declarationListContainerEnd ) ;
2618
+ }
2619
+
2620
+ onAfterEmitNode ?.( node ) ;
2621
+
2622
+ preserveSourceNewlines = state . preserveSourceNewlines ;
2551
2623
}
2552
- else {
2553
- emit ( next ) ;
2624
+ }
2625
+
2626
+ function maybeEmitExpression ( next : Expression ) {
2627
+ // Push a new frame for binary expressions, otherwise emit all other expressions.
2628
+ if ( isBinaryExpression ( next ) ) {
2629
+ return next ;
2554
2630
}
2631
+
2632
+ emit ( next ) ;
2555
2633
}
2556
2634
}
2557
2635
0 commit comments