@@ -49,6 +49,9 @@ pub struct DocFragment {
49
49
pub doc : Symbol ,
50
50
pub kind : DocFragmentKind ,
51
51
pub indent : usize ,
52
+ /// Because we temper with the spans context, this information cannot be correctly retrieved
53
+ /// later on. So instead, we compute it and store it here.
54
+ pub from_expansion : bool ,
52
55
}
53
56
54
57
#[ derive( Clone , Copy , Debug ) ]
@@ -208,17 +211,18 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
208
211
for ( attr, item_id) in attrs {
209
212
if let Some ( ( doc_str, comment_kind) ) = attr. doc_str_and_comment_kind ( ) {
210
213
let doc = beautify_doc_string ( doc_str, comment_kind) ;
211
- let ( span, kind) = if attr. is_doc_comment ( ) {
212
- ( attr. span ( ) , DocFragmentKind :: SugaredDoc )
214
+ let ( span, kind, from_expansion) = if attr. is_doc_comment ( ) {
215
+ let span = attr. span ( ) ;
216
+ ( span, DocFragmentKind :: SugaredDoc , span. from_expansion ( ) )
213
217
} else {
214
- (
215
- attr. value_span ( )
216
- . map ( |i| i . with_ctxt ( attr . span ( ) . ctxt ( ) ) )
217
- . unwrap_or ( attr . span ( ) ) ,
218
- DocFragmentKind :: RawDoc ,
219
- )
218
+ let attr_span = attr . span ( ) ;
219
+ let ( span , from_expansion ) = match attr. value_span ( ) {
220
+ Some ( sp ) => ( sp . with_ctxt ( attr_span . ctxt ( ) ) , sp . from_expansion ( ) ) ,
221
+ None => ( attr_span , attr_span . from_expansion ( ) ) ,
222
+ } ;
223
+ ( span , DocFragmentKind :: RawDoc , from_expansion )
220
224
} ;
221
- let fragment = DocFragment { span, doc, kind, item_id, indent : 0 } ;
225
+ let fragment = DocFragment { span, doc, kind, item_id, indent : 0 , from_expansion } ;
222
226
doc_fragments. push ( fragment) ;
223
227
} else if !doc_only {
224
228
other_attrs. push ( attr. clone ( ) ) ;
@@ -501,16 +505,21 @@ fn collect_link_data<'input, F: BrokenLinkCallback<'input>>(
501
505
}
502
506
503
507
/// Returns a span encompassing all the document fragments.
504
- pub fn span_of_fragments ( fragments : & [ DocFragment ] ) -> Option < Span > {
505
- if fragments. is_empty ( ) {
506
- return None ;
507
- }
508
- let start = fragments[ 0 ] . span ;
509
- if start == DUMMY_SP {
508
+ pub fn span_of_fragments_with_expansion ( fragments : & [ DocFragment ] ) -> Option < ( Span , bool ) > {
509
+ let Some ( first_fragment) = fragments. first ( ) else { return None } ;
510
+ if first_fragment. span == DUMMY_SP {
510
511
return None ;
511
512
}
512
- let end = fragments. last ( ) . expect ( "no doc strings provided" ) . span ;
513
- Some ( start. to ( end) )
513
+ let last_fragment = fragments. last ( ) . expect ( "no doc strings provided" ) ;
514
+ Some ( (
515
+ first_fragment. span . to ( last_fragment. span ) ,
516
+ first_fragment. from_expansion || last_fragment. from_expansion ,
517
+ ) )
518
+ }
519
+
520
+ /// Returns a span encompassing all the document fragments.
521
+ pub fn span_of_fragments ( fragments : & [ DocFragment ] ) -> Option < Span > {
522
+ span_of_fragments_with_expansion ( fragments) . map ( |( sp, _) | sp)
514
523
}
515
524
516
525
/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
@@ -535,7 +544,7 @@ pub fn source_span_for_markdown_range(
535
544
markdown : & str ,
536
545
md_range : & Range < usize > ,
537
546
fragments : & [ DocFragment ] ,
538
- ) -> Option < Span > {
547
+ ) -> Option < ( Span , bool ) > {
539
548
let map = tcx. sess . source_map ( ) ;
540
549
source_span_for_markdown_range_inner ( map, markdown, md_range, fragments)
541
550
}
@@ -546,7 +555,7 @@ pub fn source_span_for_markdown_range_inner(
546
555
markdown : & str ,
547
556
md_range : & Range < usize > ,
548
557
fragments : & [ DocFragment ] ,
549
- ) -> Option < Span > {
558
+ ) -> Option < ( Span , bool ) > {
550
559
use rustc_span:: BytePos ;
551
560
552
561
if let & [ fragment] = & fragments
@@ -557,11 +566,14 @@ pub fn source_span_for_markdown_range_inner(
557
566
&& let Ok ( md_range_hi) = u32:: try_from ( md_range. end )
558
567
{
559
568
// Single fragment with string that contains same bytes as doc.
560
- return Some ( Span :: new (
561
- fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_lo) ,
562
- fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_hi) ,
563
- fragment. span . ctxt ( ) ,
564
- fragment. span . parent ( ) ,
569
+ return Some ( (
570
+ Span :: new (
571
+ fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_lo) ,
572
+ fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_hi) ,
573
+ fragment. span . ctxt ( ) ,
574
+ fragment. span . parent ( ) ,
575
+ ) ,
576
+ fragment. from_expansion ,
565
577
) ) ;
566
578
}
567
579
@@ -593,19 +605,21 @@ pub fn source_span_for_markdown_range_inner(
593
605
{
594
606
match_data = Some ( ( i, match_start) ) ;
595
607
} else {
596
- // Heirustic produced ambiguity, return nothing.
608
+ // Heuristic produced ambiguity, return nothing.
597
609
return None ;
598
610
}
599
611
}
600
612
}
601
613
if let Some ( ( i, match_start) ) = match_data {
602
- let sp = fragments[ i] . span ;
614
+ let fragment = & fragments[ i] ;
615
+ let sp = fragment. span ;
603
616
// we need to calculate the span start,
604
617
// then use that in our calulations for the span end
605
618
let lo = sp. lo ( ) + BytePos ( match_start as u32 ) ;
606
- return Some (
619
+ return Some ( (
607
620
sp. with_lo ( lo) . with_hi ( lo + BytePos ( ( md_range. end - md_range. start ) as u32 ) ) ,
608
- ) ;
621
+ fragment. from_expansion ,
622
+ ) ) ;
609
623
}
610
624
return None ;
611
625
}
@@ -659,8 +673,12 @@ pub fn source_span_for_markdown_range_inner(
659
673
}
660
674
}
661
675
662
- Some ( span_of_fragments ( fragments) ?. from_inner ( InnerSpan :: new (
663
- md_range. start + start_bytes,
664
- md_range. end + start_bytes + end_bytes,
665
- ) ) )
676
+ let ( span, from_expansion) = span_of_fragments_with_expansion ( fragments) ?;
677
+ Some ( (
678
+ span. from_inner ( InnerSpan :: new (
679
+ md_range. start + start_bytes,
680
+ md_range. end + start_bytes + end_bytes,
681
+ ) ) ,
682
+ from_expansion,
683
+ ) )
666
684
}
0 commit comments