Skip to content

Commit 6482a23

Browse files
committed
new restriction lint: doc_comment_double_space_linebreak
1 parent 436675b commit 6482a23

7 files changed

+200
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5249,6 +5249,7 @@ Released 2018-09-13
52495249
[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
52505250
[`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
52515251
[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
5252+
[`doc_comment_double_space_linebreak`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreak
52525253
[`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation
52535254
[`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
52545255
[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
140140
crate::disallowed_names::DISALLOWED_NAMES_INFO,
141141
crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO,
142142
crate::disallowed_types::DISALLOWED_TYPES_INFO,
143+
crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK_INFO,
143144
crate::doc::DOC_LAZY_CONTINUATION_INFO,
144145
crate::doc::DOC_LINK_WITH_QUOTES_INFO,
145146
crate::doc::DOC_MARKDOWN_INFO,
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use clippy_utils::diagnostics::span_lint_and_then;
2+
use rustc_ast::token::CommentKind;
3+
use rustc_ast::{AttrKind, AttrStyle, Attribute};
4+
use rustc_errors::Applicability;
5+
use rustc_lint::LateContext;
6+
use rustc_span::Span;
7+
8+
use super::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK;
9+
10+
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
11+
let replacements: Vec<_> = collect_doc_replacements(attrs);
12+
13+
if let Some((&(lo_span, _), &(hi_span, _))) = replacements.first().zip(replacements.last()) {
14+
span_lint_and_then(
15+
cx,
16+
DOC_COMMENT_DOUBLE_SPACE_LINEBREAK,
17+
lo_span.to(hi_span),
18+
"doc comments should use a back-slash (\\) instead of a double space to indicate a linebreak",
19+
|diag| {
20+
diag.multipart_suggestion(
21+
"replace this double space with a back-slash",
22+
replacements,
23+
Applicability::MachineApplicable,
24+
);
25+
},
26+
);
27+
}
28+
}
29+
30+
fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> {
31+
attrs
32+
.iter()
33+
.filter_map(|attr| {
34+
if let AttrKind::DocComment(com_kind, sym) = attr.kind
35+
&& com_kind == CommentKind::Line
36+
&& let comment = sym.as_str()
37+
&& comment.ends_with(" ")
38+
{
39+
let pre = match attr.style {
40+
AttrStyle::Outer => "///",
41+
AttrStyle::Inner => "//!",
42+
};
43+
44+
let len = comment.len();
45+
let new_comment = format!("{pre}{} \\", comment[..len - 2].to_owned());
46+
Some((attr.span, new_comment))
47+
} else {
48+
None
49+
}
50+
})
51+
.collect()
52+
}

clippy_lints/src/doc/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use rustc_span::{sym, Span};
2828
use std::ops::Range;
2929
use url::Url;
3030

31+
mod doc_comment_double_space_linebreak;
3132
mod link_with_quotes;
3233
mod markdown;
3334
mod missing_headers;
@@ -420,6 +421,39 @@ declare_clippy_lint! {
420421
"require every line of a paragraph to be indented and marked"
421422
}
422423

424+
declare_clippy_lint! {
425+
/// ### What it does
426+
/// Detects doc comment linebreaks that use double spaces to separate lines, instead of back-slash (\).
427+
///
428+
/// ### Why is this bad?
429+
/// Double spaces, when used as doc comment linebreaks, can be difficult to see, and may
430+
/// accidentally be removed during automatic fofmatting or manual refactoring. The use of a back-slash (\)
431+
/// is clearer in this regard.
432+
///
433+
/// ### Example
434+
/// The two dots in this example represent a double space.
435+
/// ```no_run
436+
/// /// This command takes two numbers as inputs and..
437+
/// /// adds them together, and then returns the result.
438+
/// fn add(l: i32, r: i32) -> i32 {
439+
/// l + r
440+
/// }
441+
/// ``````
442+
///
443+
/// Use instead:
444+
/// ```no_run
445+
/// /// This command takes two numbers as inputs and \
446+
/// /// adds them together, and then returns the result.
447+
/// fn add(l: i32, r: i32) -> i32 {
448+
/// l + r
449+
/// }
450+
/// ```
451+
#[clippy::version = "1.80.0"]
452+
pub DOC_COMMENT_DOUBLE_SPACE_LINEBREAK,
453+
restriction,
454+
"double-space used for doc comment linebreak instead of `\\`"
455+
}
456+
423457
#[derive(Clone)]
424458
pub struct Documentation {
425459
valid_idents: FxHashSet<String>,
@@ -447,6 +481,7 @@ impl_lint_pass!(Documentation => [
447481
SUSPICIOUS_DOC_COMMENTS,
448482
EMPTY_DOCS,
449483
DOC_LAZY_CONTINUATION,
484+
DOC_COMMENT_DOUBLE_SPACE_LINEBREAK
450485
]);
451486

452487
impl<'tcx> LateLintPass<'tcx> for Documentation {
@@ -569,6 +604,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
569604
}
570605

571606
suspicious_doc_comments::check(cx, attrs);
607+
doc_comment_double_space_linebreak::check(cx, attrs);
572608

573609
let (fragments, _) = attrs_to_doc_fragments(
574610
attrs.iter().filter_map(|attr| {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#![feature(custom_inner_attributes)]
2+
#![rustfmt::skip]
3+
4+
#![warn(clippy::doc_comment_double_space_linebreak)]
5+
#![allow(unused)]
6+
7+
//! Should warn on double space linebreaks \
8+
//! in file/module doc comment
9+
10+
/// Should not warn on single-line doc comments
11+
fn single_line() {}
12+
13+
/// Should not warn on single-line doc comments
14+
/// split across multiple lines
15+
fn single_line_split() {}
16+
17+
// Should not warn on normal comments
18+
19+
// note: cargo fmt can remove double spaces from normal and block comments
20+
// Should not warn on normal comments
21+
// with double spaces at the end of a line
22+
23+
fn normal_comment() {
24+
/*
25+
Should not warn on block comments
26+
*/
27+
28+
/*
29+
Should not warn on block comments
30+
with double space at the end of a line
31+
*/
32+
}
33+
34+
/// Should warn when doc comment uses double space \
35+
/// as a line-break, even when there are multiple \
36+
/// in a row
37+
fn double_space_doc_comment() {}
38+
39+
/// Should not warn when back-slash is used \
40+
/// as a line-break
41+
fn back_slash_doc_comment() {}
42+
43+
fn main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#![feature(custom_inner_attributes)]
2+
#![rustfmt::skip]
3+
4+
#![warn(clippy::doc_comment_double_space_linebreak)]
5+
#![allow(unused)]
6+
7+
//! Should warn on double space linebreaks
8+
//! in file/module doc comment
9+
10+
/// Should not warn on single-line doc comments
11+
fn single_line() {}
12+
13+
/// Should not warn on single-line doc comments
14+
/// split across multiple lines
15+
fn single_line_split() {}
16+
17+
// Should not warn on normal comments
18+
19+
// note: cargo fmt can remove double spaces from normal and block comments
20+
// Should not warn on normal comments
21+
// with double spaces at the end of a line
22+
23+
fn normal_comment() {
24+
/*
25+
Should not warn on block comments
26+
*/
27+
28+
/*
29+
Should not warn on block comments
30+
with double space at the end of a line
31+
*/
32+
}
33+
34+
/// Should warn when doc comment uses double space
35+
/// as a line-break, even when there are multiple
36+
/// in a row
37+
fn double_space_doc_comment() {}
38+
39+
/// Should not warn when back-slash is used \
40+
/// as a line-break
41+
fn back_slash_doc_comment() {}
42+
43+
fn main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: doc comments should use a back-slash (\) instead of a double space to indicate a linebreak
2+
--> tests/ui/doc/doc_comment_double_space_linebreak.rs:7:1
3+
|
4+
LL | //! Should warn on double space linebreaks
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this double space with a back-slash: `//! Should warn on double space linebreaks \`
6+
|
7+
= note: `-D clippy::doc-comment-double-space-linebreak` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreak)]`
9+
10+
error: doc comments should use a back-slash (\) instead of a double space to indicate a linebreak
11+
--> tests/ui/doc/doc_comment_double_space_linebreak.rs:34:1
12+
|
13+
LL | / /// Should warn when doc comment uses double space
14+
LL | | /// as a line-break, even when there are multiple
15+
| |___________________________________________________^
16+
|
17+
help: replace this double space with a back-slash
18+
|
19+
LL + /// Should warn when doc comment uses double space \
20+
LL + /// as a line-break, even when there are multiple \
21+
|
22+
23+
error: aborting due to 2 previous errors
24+

0 commit comments

Comments
 (0)