@@ -45,6 +45,9 @@ pub struct DocFragment {
45
45
pub doc : Symbol ,
46
46
pub kind : DocFragmentKind ,
47
47
pub indent : usize ,
48
+ /// Because we temper with the spans context, this information cannot be correctly retrieved
49
+ /// later on. So instead, we compute it and store it here.
50
+ pub from_expansion : bool ,
48
51
}
49
52
50
53
#[ derive( Clone , Copy , Debug ) ]
@@ -204,17 +207,18 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
204
207
for ( attr, item_id) in attrs {
205
208
if let Some ( ( doc_str, comment_kind) ) = attr. doc_str_and_comment_kind ( ) {
206
209
let doc = beautify_doc_string ( doc_str, comment_kind) ;
207
- let ( span, kind) = if attr. is_doc_comment ( ) {
208
- ( attr. span ( ) , DocFragmentKind :: SugaredDoc )
210
+ let ( span, kind, from_expansion) = if attr. is_doc_comment ( ) {
211
+ let span = attr. span ( ) ;
212
+ ( span, DocFragmentKind :: SugaredDoc , span. from_expansion ( ) )
209
213
} else {
210
- (
211
- attr. value_span ( )
212
- . map ( |i| i . with_ctxt ( attr . span ( ) . ctxt ( ) ) )
213
- . unwrap_or ( attr . span ( ) ) ,
214
- DocFragmentKind :: RawDoc ,
215
- )
214
+ let attr_span = attr . span ( ) ;
215
+ let ( span , from_expansion ) = match attr. value_span ( ) {
216
+ Some ( sp ) => ( sp . with_ctxt ( attr_span . ctxt ( ) ) , sp . from_expansion ( ) ) ,
217
+ None => ( attr_span , attr_span . from_expansion ( ) ) ,
218
+ } ;
219
+ ( span , DocFragmentKind :: RawDoc , from_expansion )
216
220
} ;
217
- let fragment = DocFragment { span, doc, kind, item_id, indent : 0 } ;
221
+ let fragment = DocFragment { span, doc, kind, item_id, indent : 0 , from_expansion } ;
218
222
doc_fragments. push ( fragment) ;
219
223
} else if !doc_only {
220
224
other_attrs. push ( attr. clone ( ) ) ;
@@ -497,16 +501,21 @@ fn collect_link_data<'input, F: BrokenLinkCallback<'input>>(
497
501
}
498
502
499
503
/// Returns a span encompassing all the document fragments.
500
- pub fn span_of_fragments ( fragments : & [ DocFragment ] ) -> Option < Span > {
501
- if fragments. is_empty ( ) {
502
- return None ;
503
- }
504
- let start = fragments[ 0 ] . span ;
505
- if start == DUMMY_SP {
504
+ pub fn span_of_fragments_with_expansion ( fragments : & [ DocFragment ] ) -> Option < ( Span , bool ) > {
505
+ let Some ( first_fragment) = fragments. first ( ) else { return None } ;
506
+ if first_fragment. span == DUMMY_SP {
506
507
return None ;
507
508
}
508
- let end = fragments. last ( ) . expect ( "no doc strings provided" ) . span ;
509
- Some ( start. to ( end) )
509
+ let last_fragment = fragments. last ( ) . expect ( "no doc strings provided" ) ;
510
+ Some ( (
511
+ first_fragment. span . to ( last_fragment. span ) ,
512
+ first_fragment. from_expansion || last_fragment. from_expansion ,
513
+ ) )
514
+ }
515
+
516
+ /// Returns a span encompassing all the document fragments.
517
+ pub fn span_of_fragments ( fragments : & [ DocFragment ] ) -> Option < Span > {
518
+ span_of_fragments_with_expansion ( fragments) . map ( |( sp, _) | sp)
510
519
}
511
520
512
521
/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
@@ -531,7 +540,7 @@ pub fn source_span_for_markdown_range(
531
540
markdown : & str ,
532
541
md_range : & Range < usize > ,
533
542
fragments : & [ DocFragment ] ,
534
- ) -> Option < Span > {
543
+ ) -> Option < ( Span , bool ) > {
535
544
use rustc_span:: BytePos ;
536
545
537
546
let map = tcx. sess . source_map ( ) ;
@@ -543,11 +552,14 @@ pub fn source_span_for_markdown_range(
543
552
&& let Ok ( md_range_hi) = u32:: try_from ( md_range. end )
544
553
{
545
554
// Single fragment with string that contains same bytes as doc.
546
- return Some ( Span :: new (
547
- fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_lo) ,
548
- fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_hi) ,
549
- fragment. span . ctxt ( ) ,
550
- fragment. span . parent ( ) ,
555
+ return Some ( (
556
+ Span :: new (
557
+ fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_lo) ,
558
+ fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_hi) ,
559
+ fragment. span . ctxt ( ) ,
560
+ fragment. span . parent ( ) ,
561
+ ) ,
562
+ fragment. from_expansion ,
551
563
) ) ;
552
564
}
553
565
@@ -573,19 +585,21 @@ pub fn source_span_for_markdown_range(
573
585
if match_data. is_none ( ) && !snippet[ match_start + 1 ..] . contains ( pat) {
574
586
match_data = Some ( ( i, match_start) ) ;
575
587
} else {
576
- // Heirustic produced ambiguity, return nothing.
588
+ // Heuristic produced ambiguity, return nothing.
577
589
return None ;
578
590
}
579
591
}
580
592
}
581
593
if let Some ( ( i, match_start) ) = match_data {
582
- let sp = fragments[ i] . span ;
594
+ let fragment = & fragments[ i] ;
595
+ let sp = fragment. span ;
583
596
// we need to calculate the span start,
584
597
// then use that in our calulations for the span end
585
598
let lo = sp. lo ( ) + BytePos ( match_start as u32 ) ;
586
- return Some (
599
+ return Some ( (
587
600
sp. with_lo ( lo) . with_hi ( lo + BytePos ( ( md_range. end - md_range. start ) as u32 ) ) ,
588
- ) ;
601
+ fragment. from_expansion ,
602
+ ) ) ;
589
603
}
590
604
return None ;
591
605
}
@@ -639,8 +653,12 @@ pub fn source_span_for_markdown_range(
639
653
}
640
654
}
641
655
642
- Some ( span_of_fragments ( fragments) ?. from_inner ( InnerSpan :: new (
643
- md_range. start + start_bytes,
644
- md_range. end + start_bytes + end_bytes,
645
- ) ) )
656
+ let ( span, from_expansion) = span_of_fragments_with_expansion ( fragments) ?;
657
+ Some ( (
658
+ span. from_inner ( InnerSpan :: new (
659
+ md_range. start + start_bytes,
660
+ md_range. end + start_bytes + end_bytes,
661
+ ) ) ,
662
+ from_expansion,
663
+ ) )
646
664
}
0 commit comments