@@ -6,7 +6,7 @@ use unicode_width::UnicodeWidthChar;
6
6
use crate :: diagnostic_chain:: { DiagnosticChain , ErrorKind } ;
7
7
use crate :: handlers:: theme:: * ;
8
8
use crate :: protocol:: { Diagnostic , Severity } ;
9
- use crate :: { LabeledSpan , MietteError , ReportHandler , SourceCode , SourceSpan , SpanContents } ;
9
+ use crate :: { LabeledSpan , ReportHandler , SourceCode , SourceSpan , SpanContents } ;
10
10
11
11
/**
12
12
A [`ReportHandler`] that displays a given [`Report`](crate::Report) in a
@@ -386,66 +386,58 @@ impl GraphicalReportHandler {
386
386
diagnostic : & ( dyn Diagnostic ) ,
387
387
opt_source : Option < & dyn SourceCode > ,
388
388
) -> fmt:: Result {
389
- if let Some ( source) = opt_source {
390
- if let Some ( labels) = diagnostic. labels ( ) {
391
- let mut labels = labels. collect :: < Vec < _ > > ( ) ;
392
- labels. sort_unstable_by_key ( |l| l. inner ( ) . offset ( ) ) ;
393
- if !labels. is_empty ( ) {
394
- let contents = labels
395
- . iter ( )
396
- . map ( |label| {
397
- source. read_span ( label. inner ( ) , self . context_lines , self . context_lines )
398
- } )
399
- . collect :: < Result < Vec < Box < dyn SpanContents < ' _ > > > , MietteError > > ( )
400
- . map_err ( |_| fmt:: Error ) ?;
401
- let mut contexts = Vec :: with_capacity ( contents. len ( ) ) ;
402
- for ( right, right_conts) in labels. iter ( ) . cloned ( ) . zip ( contents. iter ( ) ) {
403
- if contexts. is_empty ( ) {
404
- contexts. push ( ( right, right_conts) ) ;
405
- } else {
406
- let ( left, left_conts) = contexts. last ( ) . unwrap ( ) . clone ( ) ;
407
- let left_end = left. offset ( ) + left. len ( ) ;
408
- let right_end = right. offset ( ) + right. len ( ) ;
409
- if left_conts. line ( ) + left_conts. line_count ( ) >= right_conts. line ( ) {
410
- // The snippets will overlap, so we create one Big Chunky Boi
411
- let new_span = LabeledSpan :: new (
412
- left. label ( ) . map ( String :: from) ,
413
- left. offset ( ) ,
414
- if right_end >= left_end {
415
- // Right end goes past left end
416
- right_end - left. offset ( )
417
- } else {
418
- // right is contained inside left
419
- left. len ( )
420
- } ,
421
- ) ;
422
- if source
423
- . read_span (
424
- new_span. inner ( ) ,
425
- self . context_lines ,
426
- self . context_lines ,
427
- )
428
- . is_ok ( )
429
- {
430
- contexts. pop ( ) ;
431
- contexts. push ( (
432
- // We'll throw this away later
433
- new_span, left_conts,
434
- ) ) ;
435
- } else {
436
- contexts. push ( ( right, right_conts) ) ;
437
- }
438
- } else {
439
- contexts. push ( ( right, right_conts) ) ;
440
- }
441
- }
442
- }
443
- for ( ctx, _) in contexts {
444
- self . render_context ( f, source, & ctx, & labels[ ..] ) ?;
445
- }
389
+ let source = match opt_source {
390
+ Some ( source) => source,
391
+ None => return Ok ( ( ) ) ,
392
+ } ;
393
+ let labels = match diagnostic. labels ( ) {
394
+ Some ( labels) => labels,
395
+ None => return Ok ( ( ) ) ,
396
+ } ;
397
+
398
+ let mut labels = labels. collect :: < Vec < _ > > ( ) ;
399
+ labels. sort_unstable_by_key ( |l| l. inner ( ) . offset ( ) ) ;
400
+
401
+ let mut contexts = Vec :: with_capacity ( labels. len ( ) ) ;
402
+ for right in labels. iter ( ) . cloned ( ) {
403
+ let right_conts = source
404
+ . read_span ( right. inner ( ) , self . context_lines , self . context_lines )
405
+ . map_err ( |_| fmt:: Error ) ?;
406
+
407
+ if contexts. is_empty ( ) {
408
+ contexts. push ( ( right, right_conts) ) ;
409
+ continue ;
410
+ }
411
+
412
+ let ( left, left_conts) = contexts. last ( ) . unwrap ( ) ;
413
+ if left_conts. line ( ) + left_conts. line_count ( ) >= right_conts. line ( ) {
414
+ // The snippets will overlap, so we create one Big Chunky Boi
415
+ let left_end = left. offset ( ) + left. len ( ) ;
416
+ let right_end = right. offset ( ) + right. len ( ) ;
417
+ let new_end = std:: cmp:: max ( left_end, right_end) ;
418
+
419
+ let new_span = LabeledSpan :: new (
420
+ left. label ( ) . map ( String :: from) ,
421
+ left. offset ( ) ,
422
+ new_end - left. offset ( ) ,
423
+ ) ;
424
+ // Check that the two contexts can be combined
425
+ if let Ok ( new_conts) =
426
+ source. read_span ( new_span. inner ( ) , self . context_lines , self . context_lines )
427
+ {
428
+ contexts. pop ( ) ;
429
+ // We'll throw the contents away later
430
+ contexts. push ( ( new_span, new_conts) ) ;
431
+ continue ;
446
432
}
447
433
}
434
+
435
+ contexts. push ( ( right, right_conts) ) ;
436
+ }
437
+ for ( ctx, _) in contexts {
438
+ self . render_context ( f, source, & ctx, & labels[ ..] ) ?;
448
439
}
440
+
449
441
Ok ( ( ) )
450
442
}
451
443
@@ -458,10 +450,16 @@ impl GraphicalReportHandler {
458
450
) -> fmt:: Result {
459
451
let ( contents, lines) = self . get_lines ( source, context. inner ( ) ) ?;
460
452
461
- let primary_label = labels
462
- . iter ( )
453
+ // only consider labels from the context as primary label
454
+ let ctx_labels = labels. iter ( ) . filter ( |l| {
455
+ context. inner ( ) . offset ( ) <= l. inner ( ) . offset ( )
456
+ && l. inner ( ) . offset ( ) + l. inner ( ) . len ( )
457
+ <= context. inner ( ) . offset ( ) + context. inner ( ) . len ( )
458
+ } ) ;
459
+ let primary_label = ctx_labels
460
+ . clone ( )
463
461
. find ( |label| label. primary ( ) )
464
- . or_else ( || labels . first ( ) ) ;
462
+ . or_else ( || ctx_labels . clone ( ) . next ( ) ) ;
465
463
466
464
// sorting is your friend
467
465
let labels = labels
0 commit comments