@@ -162,6 +162,17 @@ struct TokenHandler<'a, 'tcx, F: Write> {
162
162
write_line_number : fn ( & mut F , u32 , & ' static str ) ,
163
163
}
164
164
165
+ impl < F : Write > std:: fmt:: Debug for TokenHandler < ' _ , ' _ , F > {
166
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
167
+ f. debug_struct ( "TokenHandler" )
168
+ . field ( "closing_tags" , & self . closing_tags )
169
+ . field ( "pending_exit_span" , & self . pending_exit_span )
170
+ . field ( "current_class" , & self . current_class )
171
+ . field ( "pending_elems" , & self . pending_elems )
172
+ . finish ( )
173
+ }
174
+ }
175
+
165
176
impl < F : Write > TokenHandler < ' _ , ' _ , F > {
166
177
fn handle_exit_span ( & mut self ) {
167
178
// We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
@@ -214,6 +225,12 @@ impl<F: Write> TokenHandler<'_, '_, F> {
214
225
} else {
215
226
None
216
227
} ;
228
+ let mut last_pending = None ;
229
+ // To prevent opening a macro expansion span being closed right away because
230
+ // the currently open item is replaced by a new class.
231
+ if let Some ( ( _, Some ( Class :: Expansion ) ) ) = self . pending_elems . last ( ) {
232
+ last_pending = self . pending_elems . pop ( ) ;
233
+ }
217
234
for ( text, class) in self . pending_elems . iter ( ) {
218
235
string (
219
236
self . out ,
@@ -227,6 +244,16 @@ impl<F: Write> TokenHandler<'_, '_, F> {
227
244
if let Some ( close_tag) = close_tag {
228
245
exit_span ( self . out , close_tag) ;
229
246
}
247
+ if let Some ( ( text, class) ) = last_pending {
248
+ string (
249
+ self . out ,
250
+ EscapeBodyText ( & text) ,
251
+ class,
252
+ & self . href_context ,
253
+ close_tag. is_none ( ) ,
254
+ self . write_line_number ,
255
+ ) ;
256
+ }
230
257
}
231
258
self . pending_elems . clear ( ) ;
232
259
true
@@ -271,7 +298,7 @@ fn get_next_expansion<'a>(
271
298
span : Span ,
272
299
) -> Option < & ' a ExpandedCode > {
273
300
if let Some ( expanded_codes) = expanded_codes {
274
- expanded_codes. iter ( ) . find ( |code| code. start_line == line && code. span . lo ( ) >= span. lo ( ) )
301
+ expanded_codes. iter ( ) . find ( |code| code. start_line == line && code. span . lo ( ) > span. lo ( ) )
275
302
} else {
276
303
None
277
304
}
@@ -321,7 +348,7 @@ fn start_expansion(out: &mut Vec<(Cow<'_, str>, Option<Class>)>, expanded_code:
321
348
fn end_expansion < ' a , W : Write > (
322
349
token_handler : & mut TokenHandler < ' _ , ' _ , W > ,
323
350
expanded_codes : Option < & ' a Vec < ExpandedCode > > ,
324
- level : usize ,
351
+ expansion_start_tags : & [ ( & ' static str , Class ) ] ,
325
352
line : u32 ,
326
353
span : Span ,
327
354
) -> Option < & ' a ExpandedCode > {
@@ -330,15 +357,27 @@ fn end_expansion<'a, W: Write>(
330
357
token_handler. pending_elems . push ( ( Cow :: Borrowed ( "</span>" ) , Some ( Class :: Expansion ) ) ) ;
331
358
return Some ( expanded_code) ;
332
359
}
333
- if level == 0 {
360
+ if expansion_start_tags. is_empty ( ) && token_handler. closing_tags . is_empty ( ) {
361
+ // No need tag opened so we can just close expansion.
334
362
token_handler. pending_elems . push ( ( Cow :: Borrowed ( "</span></span>" ) , Some ( Class :: Expansion ) ) ) ;
335
363
return None ;
336
364
}
365
+
366
+ // If tags were opened inside the expansion, we need to close them and re-open them outside
367
+ // of the expansion span.
337
368
let mut out = String :: new ( ) ;
338
369
let mut end = String :: new ( ) ;
339
- for ( tag, class) in
340
- token_handler. closing_tags . iter ( ) . skip ( token_handler. closing_tags . len ( ) - level)
370
+
371
+ let mut closing_tags = token_handler. closing_tags . iter ( ) . peekable ( ) ;
372
+ let mut start_closing_tags = expansion_start_tags. iter ( ) . peekable ( ) ;
373
+
374
+ while let ( Some ( tag) , Some ( start_tag) ) = ( closing_tags. peek ( ) , start_closing_tags. peek ( ) )
375
+ && tag == start_tag
341
376
{
377
+ closing_tags. next ( ) ;
378
+ start_closing_tags. next ( ) ;
379
+ }
380
+ for ( tag, class) in start_closing_tags. chain ( closing_tags) {
342
381
out. push_str ( tag) ;
343
382
end. push_str ( & format ! ( "<span class=\" {}\" >" , class. as_html( ) ) ) ;
344
383
}
@@ -424,7 +463,7 @@ pub(super) fn write_code(
424
463
} ;
425
464
let mut current_expansion = get_expansion ( & mut token_handler, expanded_codes, line, file_span) ;
426
465
token_handler. write_pending_elems ( None ) ;
427
- let mut level = 0 ;
466
+ let mut expansion_start_tags = Vec :: new ( ) ;
428
467
429
468
Classifier :: new (
430
469
& src,
@@ -464,6 +503,12 @@ pub(super) fn write_code(
464
503
if current_expansion. is_none ( ) {
465
504
current_expansion =
466
505
get_expansion ( & mut token_handler, expanded_codes, line, span) ;
506
+ expansion_start_tags = token_handler. closing_tags . clone ( ) ;
507
+ }
508
+ if let Some ( ref current_expansion) = current_expansion
509
+ && current_expansion. span . lo ( ) == span. hi ( )
510
+ {
511
+ start_expansion ( & mut token_handler. pending_elems , current_expansion) ;
467
512
}
468
513
} else {
469
514
token_handler. pending_elems . push ( ( Cow :: Borrowed ( text) , class) ) ;
@@ -479,11 +524,13 @@ pub(super) fn write_code(
479
524
}
480
525
}
481
526
if need_end {
482
- current_expansion =
483
- end_expansion ( & mut token_handler, expanded_codes, level, line, span) ;
484
- if current_expansion. is_none ( ) {
485
- level = 0 ;
486
- }
527
+ current_expansion = end_expansion (
528
+ & mut token_handler,
529
+ expanded_codes,
530
+ & expansion_start_tags,
531
+ line,
532
+ span,
533
+ ) ;
487
534
}
488
535
}
489
536
}
@@ -504,9 +551,6 @@ pub(super) fn write_code(
504
551
if should_add {
505
552
let closing_tag =
506
553
enter_span ( token_handler. out , class, & token_handler. href_context ) ;
507
- if current_expansion. is_some ( ) {
508
- level += 1 ;
509
- }
510
554
token_handler. closing_tags . push ( ( closing_tag, class) ) ;
511
555
}
512
556
@@ -515,9 +559,6 @@ pub(super) fn write_code(
515
559
}
516
560
Highlight :: ExitSpan => {
517
561
token_handler. current_class = None ;
518
- if current_expansion. is_some ( ) {
519
- level -= 1 ;
520
- }
521
562
token_handler. pending_exit_span = Some (
522
563
token_handler
523
564
. closing_tags
0 commit comments