@@ -169,6 +169,17 @@ struct TokenHandler<'a, 'tcx, F: Write> {
169
169
write_line_number : fn ( & mut F , u32 , & ' static str ) ,
170
170
}
171
171
172
+ impl < F : Write > std:: fmt:: Debug for TokenHandler < ' _ , ' _ , F > {
173
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
174
+ f. debug_struct ( "TokenHandler" )
175
+ . field ( "closing_tags" , & self . closing_tags )
176
+ . field ( "pending_exit_span" , & self . pending_exit_span )
177
+ . field ( "current_class" , & self . current_class )
178
+ . field ( "pending_elems" , & self . pending_elems )
179
+ . finish ( )
180
+ }
181
+ }
182
+
172
183
impl < F : Write > TokenHandler < ' _ , ' _ , F > {
173
184
fn handle_exit_span ( & mut self ) {
174
185
// We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
@@ -221,6 +232,12 @@ impl<F: Write> TokenHandler<'_, '_, F> {
221
232
} else {
222
233
None
223
234
} ;
235
+ let mut last_pending = None ;
236
+ // To prevent opening a macro expansion span being closed right away because
237
+ // the currently open item is replaced by a new class.
238
+ if let Some ( ( _, Some ( Class :: Expansion ) ) ) = self . pending_elems . last ( ) {
239
+ last_pending = self . pending_elems . pop ( ) ;
240
+ }
224
241
for ( text, class) in self . pending_elems . iter ( ) {
225
242
string (
226
243
self . out ,
@@ -234,6 +251,16 @@ impl<F: Write> TokenHandler<'_, '_, F> {
234
251
if let Some ( close_tag) = close_tag {
235
252
exit_span ( self . out , close_tag) ;
236
253
}
254
+ if let Some ( ( text, class) ) = last_pending {
255
+ string (
256
+ self . out ,
257
+ EscapeBodyText ( & text) ,
258
+ class,
259
+ & self . href_context ,
260
+ close_tag. is_none ( ) ,
261
+ self . write_line_number ,
262
+ ) ;
263
+ }
237
264
}
238
265
self . pending_elems . clear ( ) ;
239
266
true
@@ -278,7 +305,7 @@ fn get_next_expansion<'a>(
278
305
span : Span ,
279
306
) -> Option < & ' a ExpandedCode > {
280
307
if let Some ( expanded_codes) = expanded_codes {
281
- expanded_codes. iter ( ) . find ( |code| code. start_line == line && code. span . lo ( ) >= span. lo ( ) )
308
+ expanded_codes. iter ( ) . find ( |code| code. start_line == line && code. span . lo ( ) > span. lo ( ) )
282
309
} else {
283
310
None
284
311
}
@@ -328,7 +355,7 @@ fn start_expansion(out: &mut Vec<(Cow<'_, str>, Option<Class>)>, expanded_code:
328
355
fn end_expansion < ' a , W : Write > (
329
356
token_handler : & mut TokenHandler < ' _ , ' _ , W > ,
330
357
expanded_codes : Option < & ' a Vec < ExpandedCode > > ,
331
- level : usize ,
358
+ expansion_start_tags : & [ ( & ' static str , Class ) ] ,
332
359
line : u32 ,
333
360
span : Span ,
334
361
) -> Option < & ' a ExpandedCode > {
@@ -337,15 +364,27 @@ fn end_expansion<'a, W: Write>(
337
364
token_handler. pending_elems . push ( ( Cow :: Borrowed ( "</span>" ) , Some ( Class :: Expansion ) ) ) ;
338
365
return Some ( expanded_code) ;
339
366
}
340
- if level == 0 {
367
+ if expansion_start_tags. is_empty ( ) && token_handler. closing_tags . is_empty ( ) {
368
+ // No need tag opened so we can just close expansion.
341
369
token_handler. pending_elems . push ( ( Cow :: Borrowed ( "</span></span>" ) , Some ( Class :: Expansion ) ) ) ;
342
370
return None ;
343
371
}
372
+
373
+ // If tags were opened inside the expansion, we need to close them and re-open them outside
374
+ // of the expansion span.
344
375
let mut out = String :: new ( ) ;
345
376
let mut end = String :: new ( ) ;
346
- for ( tag, class) in
347
- token_handler. closing_tags . iter ( ) . skip ( token_handler. closing_tags . len ( ) - level)
377
+
378
+ let mut closing_tags = token_handler. closing_tags . iter ( ) . peekable ( ) ;
379
+ let mut start_closing_tags = expansion_start_tags. iter ( ) . peekable ( ) ;
380
+
381
+ while let ( Some ( tag) , Some ( start_tag) ) = ( closing_tags. peek ( ) , start_closing_tags. peek ( ) )
382
+ && tag == start_tag
348
383
{
384
+ closing_tags. next ( ) ;
385
+ start_closing_tags. next ( ) ;
386
+ }
387
+ for ( tag, class) in start_closing_tags. chain ( closing_tags) {
349
388
out. push_str ( tag) ;
350
389
end. push_str ( & format ! ( "<span class=\" {}\" >" , class. as_html( ) ) ) ;
351
390
}
@@ -431,7 +470,7 @@ pub(super) fn write_code(
431
470
} ;
432
471
let mut current_expansion = get_expansion ( & mut token_handler, expanded_codes, line, file_span) ;
433
472
token_handler. write_pending_elems ( None ) ;
434
- let mut level = 0 ;
473
+ let mut expansion_start_tags = Vec :: new ( ) ;
435
474
436
475
Classifier :: new (
437
476
& src,
@@ -471,6 +510,12 @@ pub(super) fn write_code(
471
510
if current_expansion. is_none ( ) {
472
511
current_expansion =
473
512
get_expansion ( & mut token_handler, expanded_codes, line, span) ;
513
+ expansion_start_tags = token_handler. closing_tags . clone ( ) ;
514
+ }
515
+ if let Some ( ref current_expansion) = current_expansion
516
+ && current_expansion. span . lo ( ) == span. hi ( )
517
+ {
518
+ start_expansion ( & mut token_handler. pending_elems , current_expansion) ;
474
519
}
475
520
} else {
476
521
token_handler. pending_elems . push ( ( Cow :: Borrowed ( text) , class) ) ;
@@ -486,11 +531,13 @@ pub(super) fn write_code(
486
531
}
487
532
}
488
533
if need_end {
489
- current_expansion =
490
- end_expansion ( & mut token_handler, expanded_codes, level, line, span) ;
491
- if current_expansion. is_none ( ) {
492
- level = 0 ;
493
- }
534
+ current_expansion = end_expansion (
535
+ & mut token_handler,
536
+ expanded_codes,
537
+ & expansion_start_tags,
538
+ line,
539
+ span,
540
+ ) ;
494
541
}
495
542
}
496
543
}
@@ -511,9 +558,6 @@ pub(super) fn write_code(
511
558
if should_add {
512
559
let closing_tag =
513
560
enter_span ( token_handler. out , class, & token_handler. href_context ) ;
514
- if current_expansion. is_some ( ) {
515
- level += 1 ;
516
- }
517
561
token_handler. closing_tags . push ( ( closing_tag, class) ) ;
518
562
}
519
563
@@ -522,9 +566,6 @@ pub(super) fn write_code(
522
566
}
523
567
Highlight :: ExitSpan => {
524
568
token_handler. current_class = None ;
525
- if current_expansion. is_some ( ) {
526
- level -= 1 ;
527
- }
528
569
token_handler. pending_exit_span = Some (
529
570
token_handler
530
571
. closing_tags
0 commit comments