@@ -454,6 +454,18 @@ fn lint_for_missing_headers(
454
454
#[ expect( clippy:: cast_possible_truncation) ]
455
455
#[ must_use]
456
456
pub fn strip_doc_comment_decoration ( doc : & str , comment_kind : CommentKind , span : Span ) -> ( String , Vec < ( usize , Span ) > ) {
457
+ fn get_line_indentation ( line : & Vec < char > ) -> u32 {
458
+ let mut indent = 0 ;
459
+ for c in line {
460
+ if * c == ' ' {
461
+ indent += 1 ;
462
+ } else if * c == '\n' {
463
+ indent += 4 ;
464
+ } ; // Standard "Tab" space
465
+ }
466
+ indent
467
+ }
468
+
457
469
// one-line comments lose their prefix
458
470
if comment_kind == CommentKind :: Line {
459
471
let mut doc = doc. to_owned ( ) ;
@@ -465,15 +477,32 @@ pub fn strip_doc_comment_decoration(doc: &str, comment_kind: CommentKind, span:
465
477
466
478
let mut sizes = vec ! [ ] ;
467
479
let mut contains_initial_stars = false ;
480
+ let mut least_indented = 10 ; // (Hoping the document has less indentation than 10)
468
481
for line in doc. lines ( ) {
469
482
let offset = line. as_ptr ( ) as usize - doc. as_ptr ( ) as usize ;
470
483
debug_assert_eq ! ( offset as u32 as usize , offset) ;
484
+ if !line. is_empty ( ) {
485
+ // Empty lines don't have indentation
486
+ let line_indent = get_line_indentation ( & line. chars ( ) . collect :: < Vec < char > > ( ) ) ;
487
+ if line_indent < least_indented {
488
+ least_indented = line_indent;
489
+ } ;
490
+ } ;
471
491
contains_initial_stars |= line. trim_start ( ) . starts_with ( '*' ) ;
472
492
// +1 adds the newline, +3 skips the opening delimiter
473
493
sizes. push ( ( line. len ( ) + 1 , span. with_lo ( span. lo ( ) + BytePos ( 3 + offset as u32 ) ) ) ) ;
474
494
}
475
495
if !contains_initial_stars {
476
- return ( doc. to_string ( ) , sizes) ;
496
+ let mut new_doc = Vec :: new ( ) ;
497
+ for line in doc. lines ( ) {
498
+ if line. len ( ) >= least_indented as usize {
499
+ new_doc. push ( & line[ least_indented. saturating_sub ( 1 ) as usize ..] ) ; // Sometimes users start the comment the same line the doc comment is defined.
500
+ // /** Example of this behaviour
501
+ // (Some description)
502
+ // */
503
+ } ;
504
+ }
505
+ return ( new_doc. join ( "\n " ) , sizes) ;
477
506
}
478
507
// remove the initial '*'s if any
479
508
let mut no_stars = String :: with_capacity ( doc. len ( ) ) ;
@@ -646,9 +675,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
646
675
headers. safety |= in_heading && trimmed_text == "Implementation safety" ;
647
676
headers. safety |= in_heading && trimmed_text == "Implementation Safety" ;
648
677
headers. errors |= in_heading && trimmed_text == "Errors" ;
649
- headers. errors |= trimmed_text. contains ( "# Errors\n " ) ; // For /** Doc comments */
650
678
headers. panics |= in_heading && trimmed_text == "Panics" ;
651
- headers. panics |= trimmed_text. contains ( "# Panics\n " ) ;
652
679
if in_code {
653
680
if is_rust {
654
681
let edition = edition. unwrap_or_else ( || cx. tcx . sess . edition ( ) ) ;
0 commit comments