@@ -2,6 +2,7 @@ use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item,
22use if_chain:: if_chain;
33use itertools:: Itertools ;
44use rustc_ast:: ast:: { AttrKind , Attribute } ;
5+ use rustc_ast:: token:: CommentKind ;
56use rustc_data_structures:: fx:: FxHashSet ;
67use rustc_hir as hir;
78use rustc_lint:: { LateContext , LateLintPass } ;
@@ -249,62 +250,53 @@ fn lint_for_missing_headers<'tcx>(
249250 }
250251}
251252
252- /// Cleanup documentation decoration (`///` and such) .
253+ /// Cleanup documentation decoration.
253254///
254255/// We can't use `rustc_ast::attr::AttributeMethods::with_desugared_doc` or
255256/// `rustc_ast::parse::lexer::comments::strip_doc_comment_decoration` because we
256257/// need to keep track of
257258/// the spans but this function is inspired from the later.
258259#[ allow( clippy:: cast_possible_truncation) ]
259260#[ must_use]
260- pub fn strip_doc_comment_decoration ( comment : & str , span : Span ) -> ( String , Vec < ( usize , Span ) > ) {
261+ pub fn strip_doc_comment_decoration ( doc : & str , comment_kind : CommentKind , span : Span ) -> ( String , Vec < ( usize , Span ) > ) {
261262 // one-line comments lose their prefix
262- const ONELINERS : & [ & str ] = & [ "///!" , "///" , "//!" , "//" ] ;
263- for prefix in ONELINERS {
264- if comment. starts_with ( * prefix) {
265- let doc = & comment[ prefix. len ( ) ..] ;
266- let mut doc = doc. to_owned ( ) ;
267- doc. push ( '\n' ) ;
268- return (
269- doc. to_owned ( ) ,
270- vec ! [ ( doc. len( ) , span. with_lo( span. lo( ) + BytePos ( prefix. len( ) as u32 ) ) ) ] ,
271- ) ;
272- }
263+ if comment_kind == CommentKind :: Line {
264+ let mut doc = doc. to_owned ( ) ;
265+ doc. push ( '\n' ) ;
266+ let len = doc. len ( ) ;
267+ // +3 skips the opening delimiter
268+ return ( doc, vec ! [ ( len, span. with_lo( span. lo( ) + BytePos ( 3 ) ) ) ] ) ;
273269 }
274270
275- if comment. starts_with ( "/*" ) {
276- let doc = & comment[ 3 ..comment. len ( ) - 2 ] ;
277- let mut sizes = vec ! [ ] ;
278- let mut contains_initial_stars = false ;
279- for line in doc. lines ( ) {
280- let offset = line. as_ptr ( ) as usize - comment. as_ptr ( ) as usize ;
281- debug_assert_eq ! ( offset as u32 as usize , offset) ;
282- contains_initial_stars |= line. trim_start ( ) . starts_with ( '*' ) ;
283- // +1 for the newline
284- sizes. push ( ( line. len ( ) + 1 , span. with_lo ( span. lo ( ) + BytePos ( offset as u32 ) ) ) ) ;
285- }
286- if !contains_initial_stars {
287- return ( doc. to_string ( ) , sizes) ;
288- }
289- // remove the initial '*'s if any
290- let mut no_stars = String :: with_capacity ( doc. len ( ) ) ;
291- for line in doc. lines ( ) {
292- let mut chars = line. chars ( ) ;
293- while let Some ( c) = chars. next ( ) {
294- if c. is_whitespace ( ) {
295- no_stars. push ( c) ;
296- } else {
297- no_stars. push ( if c == '*' { ' ' } else { c } ) ;
298- break ;
299- }
271+ let mut sizes = vec ! [ ] ;
272+ let mut contains_initial_stars = false ;
273+ for line in doc. lines ( ) {
274+ let offset = line. as_ptr ( ) as usize - doc. as_ptr ( ) as usize ;
275+ debug_assert_eq ! ( offset as u32 as usize , offset) ;
276+ contains_initial_stars |= line. trim_start ( ) . starts_with ( '*' ) ;
277+ // +1 adds the newline, +3 skips the opening delimiter
278+ sizes. push ( ( line. len ( ) + 1 , span. with_lo ( span. lo ( ) + BytePos ( 3 + offset as u32 ) ) ) ) ;
279+ }
280+ if !contains_initial_stars {
281+ return ( doc. to_string ( ) , sizes) ;
282+ }
283+ // remove the initial '*'s if any
284+ let mut no_stars = String :: with_capacity ( doc. len ( ) ) ;
285+ for line in doc. lines ( ) {
286+ let mut chars = line. chars ( ) ;
287+ while let Some ( c) = chars. next ( ) {
288+ if c. is_whitespace ( ) {
289+ no_stars. push ( c) ;
290+ } else {
291+ no_stars. push ( if c == '*' { ' ' } else { c } ) ;
292+ break ;
300293 }
301- no_stars. push_str ( chars. as_str ( ) ) ;
302- no_stars. push ( '\n' ) ;
303294 }
304- return ( no_stars, sizes) ;
295+ no_stars. push_str ( chars. as_str ( ) ) ;
296+ no_stars. push ( '\n' ) ;
305297 }
306298
307- panic ! ( "not a doc-comment: {}" , comment ) ;
299+ ( no_stars , sizes )
308300}
309301
310302#[ derive( Copy , Clone ) ]
@@ -318,9 +310,8 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
318310 let mut spans = vec ! [ ] ;
319311
320312 for attr in attrs {
321- if let AttrKind :: DocComment ( ref comment) = attr. kind {
322- let comment = comment. to_string ( ) ;
323- let ( comment, current_spans) = strip_doc_comment_decoration ( & comment, attr. span ) ;
313+ if let AttrKind :: DocComment ( comment_kind, comment) = attr. kind {
314+ let ( comment, current_spans) = strip_doc_comment_decoration ( & comment. as_str ( ) , comment_kind, attr. span ) ;
324315 spans. extend_from_slice ( & current_spans) ;
325316 doc. push_str ( & comment) ;
326317 } else if attr. has_name ( sym ! ( doc) ) {
0 commit comments