@@ -2,6 +2,7 @@ use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item,
2
2
use if_chain:: if_chain;
3
3
use itertools:: Itertools ;
4
4
use rustc_ast:: ast:: { AttrKind , Attribute } ;
5
+ use rustc_ast:: token:: CommentKind ;
5
6
use rustc_data_structures:: fx:: FxHashSet ;
6
7
use rustc_hir as hir;
7
8
use rustc_lint:: { LateContext , LateLintPass } ;
@@ -249,62 +250,53 @@ fn lint_for_missing_headers<'tcx>(
249
250
}
250
251
}
251
252
252
- /// Cleanup documentation decoration (`///` and such) .
253
+ /// Cleanup documentation decoration.
253
254
///
254
255
/// We can't use `rustc_ast::attr::AttributeMethods::with_desugared_doc` or
255
256
/// `rustc_ast::parse::lexer::comments::strip_doc_comment_decoration` because we
256
257
/// need to keep track of
257
258
/// the spans but this function is inspired from the later.
258
259
#[ allow( clippy:: cast_possible_truncation) ]
259
260
#[ 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 ) > ) {
261
262
// 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 ) ) ) ] ) ;
273
269
}
274
270
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 ;
300
293
}
301
- no_stars. push_str ( chars. as_str ( ) ) ;
302
- no_stars. push ( '\n' ) ;
303
294
}
304
- return ( no_stars, sizes) ;
295
+ no_stars. push_str ( chars. as_str ( ) ) ;
296
+ no_stars. push ( '\n' ) ;
305
297
}
306
298
307
- panic ! ( "not a doc-comment: {}" , comment ) ;
299
+ ( no_stars , sizes )
308
300
}
309
301
310
302
#[ derive( Copy , Clone ) ]
@@ -318,9 +310,8 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
318
310
let mut spans = vec ! [ ] ;
319
311
320
312
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 ) ;
324
315
spans. extend_from_slice ( & current_spans) ;
325
316
doc. push_str ( & comment) ;
326
317
} else if attr. has_name ( sym ! ( doc) ) {
0 commit comments