new lint: doc_comment_double_space_linebreaks
(#12876)
Fixes https://github.com/rust-lang/rust-clippy/issues/12163 I decided to initially make this a restriction lint because it felt a bit niche and opinionated to be a warn-by-default style lint. It may be appropriate as a style lint if the standard or convention *is* to use `\` as doc comment linebreaks - not sure if they are! The wording on the help message could be improved, as well as the name of the lint itself since it's a bit wordy - suggestions welcome. This lint works on both `///` and `//!` doc comments. changelog: new lint: `doc_comment_double_space_linebreaks`
This commit is contained in:
commit
3c7dfacf44
7 changed files with 331 additions and 3 deletions
|
@ -5570,6 +5570,7 @@ Released 2018-09-13
|
||||||
[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
|
[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
|
||||||
[`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
|
[`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
|
||||||
[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
|
[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
|
||||||
|
[`doc_comment_double_space_linebreaks`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreaks
|
||||||
[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg
|
[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg
|
||||||
[`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation
|
[`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation
|
||||||
[`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code
|
[`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code
|
||||||
|
|
|
@ -137,6 +137,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
|
||||||
crate::disallowed_names::DISALLOWED_NAMES_INFO,
|
crate::disallowed_names::DISALLOWED_NAMES_INFO,
|
||||||
crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO,
|
crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO,
|
||||||
crate::disallowed_types::DISALLOWED_TYPES_INFO,
|
crate::disallowed_types::DISALLOWED_TYPES_INFO,
|
||||||
|
crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS_INFO,
|
||||||
crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO,
|
crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO,
|
||||||
crate::doc::DOC_LAZY_CONTINUATION_INFO,
|
crate::doc::DOC_LAZY_CONTINUATION_INFO,
|
||||||
crate::doc::DOC_LINK_CODE_INFO,
|
crate::doc::DOC_LINK_CODE_INFO,
|
||||||
|
|
33
clippy_lints/src/doc/doc_comment_double_space_linebreaks.rs
Normal file
33
clippy_lints/src/doc/doc_comment_double_space_linebreaks.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_lint::LateContext;
|
||||||
|
use rustc_span::{BytePos, Span};
|
||||||
|
|
||||||
|
use super::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS;
|
||||||
|
|
||||||
|
pub fn check(cx: &LateContext<'_>, collected_breaks: &[Span]) {
|
||||||
|
if collected_breaks.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let breaks: Vec<_> = collected_breaks
|
||||||
|
.iter()
|
||||||
|
.map(|span| span.with_hi(span.lo() + BytePos(2)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
span_lint_and_then(
|
||||||
|
cx,
|
||||||
|
DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS,
|
||||||
|
breaks.clone(),
|
||||||
|
"doc comment uses two spaces for a hard line break",
|
||||||
|
|diag| {
|
||||||
|
let suggs: Vec<_> = breaks.iter().map(|span| (*span, "\\".to_string())).collect();
|
||||||
|
diag.tool_only_multipart_suggestion(
|
||||||
|
"replace this double space with a backslash:",
|
||||||
|
suggs,
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
diag.help("replace this double space with a backslash: `\\`");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,12 +1,10 @@
|
||||||
#![allow(clippy::lint_without_lint_pass)]
|
#![allow(clippy::lint_without_lint_pass)]
|
||||||
|
|
||||||
mod lazy_continuation;
|
|
||||||
mod too_long_first_doc_paragraph;
|
|
||||||
|
|
||||||
use clippy_config::Conf;
|
use clippy_config::Conf;
|
||||||
use clippy_utils::attrs::is_doc_hidden;
|
use clippy_utils::attrs::is_doc_hidden;
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
|
||||||
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
|
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
|
||||||
|
use clippy_utils::source::snippet_opt;
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::visitors::Visitable;
|
use clippy_utils::visitors::Visitable;
|
||||||
use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args};
|
use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args};
|
||||||
|
@ -33,12 +31,15 @@ use rustc_span::{Span, sym};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
mod doc_comment_double_space_linebreaks;
|
||||||
mod include_in_doc_without_cfg;
|
mod include_in_doc_without_cfg;
|
||||||
|
mod lazy_continuation;
|
||||||
mod link_with_quotes;
|
mod link_with_quotes;
|
||||||
mod markdown;
|
mod markdown;
|
||||||
mod missing_headers;
|
mod missing_headers;
|
||||||
mod needless_doctest_main;
|
mod needless_doctest_main;
|
||||||
mod suspicious_doc_comments;
|
mod suspicious_doc_comments;
|
||||||
|
mod too_long_first_doc_paragraph;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
|
@ -567,6 +568,39 @@ declare_clippy_lint! {
|
||||||
"link reference defined in list item or quote"
|
"link reference defined in list item or quote"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
/// Detects doc comment linebreaks that use double spaces to separate lines, instead of back-slash (`\`).
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Double spaces, when used as doc comment linebreaks, can be difficult to see, and may
|
||||||
|
/// accidentally be removed during automatic formatting or manual refactoring. The use of a back-slash (`\`)
|
||||||
|
/// is clearer in this regard.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// The two replacement dots in this example represent a double space.
|
||||||
|
/// ```no_run
|
||||||
|
/// /// This command takes two numbers as inputs and··
|
||||||
|
/// /// adds them together, and then returns the result.
|
||||||
|
/// fn add(l: i32, r: i32) -> i32 {
|
||||||
|
/// l + r
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```no_run
|
||||||
|
/// /// This command takes two numbers as inputs and\
|
||||||
|
/// /// adds them together, and then returns the result.
|
||||||
|
/// fn add(l: i32, r: i32) -> i32 {
|
||||||
|
/// l + r
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.87.0"]
|
||||||
|
pub DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS,
|
||||||
|
pedantic,
|
||||||
|
"double-space used for doc comment linebreak instead of `\\`"
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Documentation {
|
pub struct Documentation {
|
||||||
valid_idents: FxHashSet<String>,
|
valid_idents: FxHashSet<String>,
|
||||||
check_private_items: bool,
|
check_private_items: bool,
|
||||||
|
@ -598,6 +632,7 @@ impl_lint_pass!(Documentation => [
|
||||||
DOC_OVERINDENTED_LIST_ITEMS,
|
DOC_OVERINDENTED_LIST_ITEMS,
|
||||||
TOO_LONG_FIRST_DOC_PARAGRAPH,
|
TOO_LONG_FIRST_DOC_PARAGRAPH,
|
||||||
DOC_INCLUDE_WITHOUT_CFG,
|
DOC_INCLUDE_WITHOUT_CFG,
|
||||||
|
DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl EarlyLintPass for Documentation {
|
impl EarlyLintPass for Documentation {
|
||||||
|
@ -894,6 +929,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
||||||
let mut paragraph_range = 0..0;
|
let mut paragraph_range = 0..0;
|
||||||
let mut code_level = 0;
|
let mut code_level = 0;
|
||||||
let mut blockquote_level = 0;
|
let mut blockquote_level = 0;
|
||||||
|
let mut collected_breaks: Vec<Span> = Vec::new();
|
||||||
let mut is_first_paragraph = true;
|
let mut is_first_paragraph = true;
|
||||||
|
|
||||||
let mut containers = Vec::new();
|
let mut containers = Vec::new();
|
||||||
|
@ -1069,6 +1105,14 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
||||||
&containers[..],
|
&containers[..],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(span) = fragments.span(cx, range.clone())
|
||||||
|
&& !span.from_expansion()
|
||||||
|
&& let Some(snippet) = snippet_opt(cx, span)
|
||||||
|
&& !snippet.trim().starts_with('\\')
|
||||||
|
&& event == HardBreak {
|
||||||
|
collected_breaks.push(span);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Text(text) => {
|
Text(text) => {
|
||||||
paragraph_range.end = range.end;
|
paragraph_range.end = range.end;
|
||||||
|
@ -1119,6 +1163,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
||||||
FootnoteReference(_) => {}
|
FootnoteReference(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc_comment_double_space_linebreaks::check(cx, &collected_breaks);
|
||||||
|
|
||||||
headers
|
headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
98
tests/ui/doc/doc_comment_double_space_linebreaks.fixed
Normal file
98
tests/ui/doc/doc_comment_double_space_linebreaks.fixed
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#![feature(custom_inner_attributes)]
|
||||||
|
#![rustfmt::skip]
|
||||||
|
|
||||||
|
#![warn(clippy::doc_comment_double_space_linebreaks)]
|
||||||
|
#![allow(unused, clippy::empty_docs)]
|
||||||
|
|
||||||
|
//~v doc_comment_double_space_linebreaks
|
||||||
|
//! Should warn on double space linebreaks\
|
||||||
|
//! in file/module doc comment
|
||||||
|
|
||||||
|
/// Should not warn on single-line doc comments
|
||||||
|
fn single_line() {}
|
||||||
|
|
||||||
|
/// Should not warn on single-line doc comments
|
||||||
|
/// split across multiple lines
|
||||||
|
fn single_line_split() {}
|
||||||
|
|
||||||
|
// Should not warn on normal comments
|
||||||
|
|
||||||
|
// note: cargo fmt can remove double spaces from normal and block comments
|
||||||
|
// Should not warn on normal comments
|
||||||
|
// with double spaces at the end of a line
|
||||||
|
|
||||||
|
#[doc = "This is a doc attribute, which should not be linted"]
|
||||||
|
fn normal_comment() {
|
||||||
|
/*
|
||||||
|
Should not warn on block comments
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Should not warn on block comments
|
||||||
|
with double space at the end of a line
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//~v doc_comment_double_space_linebreaks
|
||||||
|
/// Should warn when doc comment uses double space\
|
||||||
|
/// as a line-break, even when there are multiple\
|
||||||
|
/// in a row
|
||||||
|
fn double_space_doc_comment() {}
|
||||||
|
|
||||||
|
/// Should not warn when back-slash is used \
|
||||||
|
/// as a line-break
|
||||||
|
fn back_slash_doc_comment() {}
|
||||||
|
|
||||||
|
//~v doc_comment_double_space_linebreaks
|
||||||
|
/// 🌹 are 🟥\
|
||||||
|
/// 🌷 are 🟦\
|
||||||
|
/// 📎 is 😎\
|
||||||
|
/// and so are 🫵\
|
||||||
|
/// (hopefully no formatting weirdness linting this)
|
||||||
|
fn multi_byte_chars_tada() {}
|
||||||
|
|
||||||
|
macro_rules! macro_that_makes_function {
|
||||||
|
() => {
|
||||||
|
/// Shouldn't lint on this!
|
||||||
|
/// (hopefully)
|
||||||
|
fn my_macro_created_function() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_that_makes_function!();
|
||||||
|
|
||||||
|
// dont lint when its alone on a line
|
||||||
|
///
|
||||||
|
fn alone() {}
|
||||||
|
|
||||||
|
/// | First column | Second column |
|
||||||
|
/// | ------------ | ------------- |
|
||||||
|
/// | Not a line | break when |
|
||||||
|
/// | after a line | in a table |
|
||||||
|
fn table() {}
|
||||||
|
|
||||||
|
/// ```text
|
||||||
|
/// It's also not a hard line break if
|
||||||
|
/// there's two spaces at the end of a
|
||||||
|
/// line in a block code.
|
||||||
|
/// ```
|
||||||
|
fn codeblock() {}
|
||||||
|
|
||||||
|
/// It's also not a hard line break `if
|
||||||
|
/// there's` two spaces in the middle of inline code.
|
||||||
|
fn inline() {}
|
||||||
|
|
||||||
|
/// It's also not a hard line break [when](
|
||||||
|
/// https://example.com) in a URL.
|
||||||
|
fn url() {}
|
||||||
|
|
||||||
|
//~v doc_comment_double_space_linebreaks
|
||||||
|
/// here we mix\
|
||||||
|
/// double spaces\
|
||||||
|
/// and also\
|
||||||
|
/// adding backslash\
|
||||||
|
/// to some of them\
|
||||||
|
/// to see how that looks
|
||||||
|
fn mixed() {}
|
||||||
|
|
||||||
|
fn main() {}
|
98
tests/ui/doc/doc_comment_double_space_linebreaks.rs
Normal file
98
tests/ui/doc/doc_comment_double_space_linebreaks.rs
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#![feature(custom_inner_attributes)]
|
||||||
|
#![rustfmt::skip]
|
||||||
|
|
||||||
|
#![warn(clippy::doc_comment_double_space_linebreaks)]
|
||||||
|
#![allow(unused, clippy::empty_docs)]
|
||||||
|
|
||||||
|
//~v doc_comment_double_space_linebreaks
|
||||||
|
//! Should warn on double space linebreaks
|
||||||
|
//! in file/module doc comment
|
||||||
|
|
||||||
|
/// Should not warn on single-line doc comments
|
||||||
|
fn single_line() {}
|
||||||
|
|
||||||
|
/// Should not warn on single-line doc comments
|
||||||
|
/// split across multiple lines
|
||||||
|
fn single_line_split() {}
|
||||||
|
|
||||||
|
// Should not warn on normal comments
|
||||||
|
|
||||||
|
// note: cargo fmt can remove double spaces from normal and block comments
|
||||||
|
// Should not warn on normal comments
|
||||||
|
// with double spaces at the end of a line
|
||||||
|
|
||||||
|
#[doc = "This is a doc attribute, which should not be linted"]
|
||||||
|
fn normal_comment() {
|
||||||
|
/*
|
||||||
|
Should not warn on block comments
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Should not warn on block comments
|
||||||
|
with double space at the end of a line
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//~v doc_comment_double_space_linebreaks
|
||||||
|
/// Should warn when doc comment uses double space
|
||||||
|
/// as a line-break, even when there are multiple
|
||||||
|
/// in a row
|
||||||
|
fn double_space_doc_comment() {}
|
||||||
|
|
||||||
|
/// Should not warn when back-slash is used \
|
||||||
|
/// as a line-break
|
||||||
|
fn back_slash_doc_comment() {}
|
||||||
|
|
||||||
|
//~v doc_comment_double_space_linebreaks
|
||||||
|
/// 🌹 are 🟥
|
||||||
|
/// 🌷 are 🟦
|
||||||
|
/// 📎 is 😎
|
||||||
|
/// and so are 🫵
|
||||||
|
/// (hopefully no formatting weirdness linting this)
|
||||||
|
fn multi_byte_chars_tada() {}
|
||||||
|
|
||||||
|
macro_rules! macro_that_makes_function {
|
||||||
|
() => {
|
||||||
|
/// Shouldn't lint on this!
|
||||||
|
/// (hopefully)
|
||||||
|
fn my_macro_created_function() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_that_makes_function!();
|
||||||
|
|
||||||
|
// dont lint when its alone on a line
|
||||||
|
///
|
||||||
|
fn alone() {}
|
||||||
|
|
||||||
|
/// | First column | Second column |
|
||||||
|
/// | ------------ | ------------- |
|
||||||
|
/// | Not a line | break when |
|
||||||
|
/// | after a line | in a table |
|
||||||
|
fn table() {}
|
||||||
|
|
||||||
|
/// ```text
|
||||||
|
/// It's also not a hard line break if
|
||||||
|
/// there's two spaces at the end of a
|
||||||
|
/// line in a block code.
|
||||||
|
/// ```
|
||||||
|
fn codeblock() {}
|
||||||
|
|
||||||
|
/// It's also not a hard line break `if
|
||||||
|
/// there's` two spaces in the middle of inline code.
|
||||||
|
fn inline() {}
|
||||||
|
|
||||||
|
/// It's also not a hard line break [when](
|
||||||
|
/// https://example.com) in a URL.
|
||||||
|
fn url() {}
|
||||||
|
|
||||||
|
//~v doc_comment_double_space_linebreaks
|
||||||
|
/// here we mix
|
||||||
|
/// double spaces\
|
||||||
|
/// and also
|
||||||
|
/// adding backslash\
|
||||||
|
/// to some of them
|
||||||
|
/// to see how that looks
|
||||||
|
fn mixed() {}
|
||||||
|
|
||||||
|
fn main() {}
|
50
tests/ui/doc/doc_comment_double_space_linebreaks.stderr
Normal file
50
tests/ui/doc/doc_comment_double_space_linebreaks.stderr
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
error: doc comment uses two spaces for a hard line break
|
||||||
|
--> tests/ui/doc/doc_comment_double_space_linebreaks.rs:8:43
|
||||||
|
|
|
||||||
|
LL | //! Should warn on double space linebreaks
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: replace this double space with a backslash: `\`
|
||||||
|
= note: `-D clippy::doc-comment-double-space-linebreaks` implied by `-D warnings`
|
||||||
|
= help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreaks)]`
|
||||||
|
|
||||||
|
error: doc comment uses two spaces for a hard line break
|
||||||
|
--> tests/ui/doc/doc_comment_double_space_linebreaks.rs:37:51
|
||||||
|
|
|
||||||
|
LL | /// Should warn when doc comment uses double space
|
||||||
|
| ^^
|
||||||
|
LL | /// as a line-break, even when there are multiple
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: replace this double space with a backslash: `\`
|
||||||
|
|
||||||
|
error: doc comment uses two spaces for a hard line break
|
||||||
|
--> tests/ui/doc/doc_comment_double_space_linebreaks.rs:47:12
|
||||||
|
|
|
||||||
|
LL | /// 🌹 are 🟥
|
||||||
|
| ^^
|
||||||
|
LL | /// 🌷 are 🟦
|
||||||
|
| ^^
|
||||||
|
LL | /// 📎 is 😎
|
||||||
|
| ^^
|
||||||
|
LL | /// and so are 🫵
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: replace this double space with a backslash: `\`
|
||||||
|
|
||||||
|
error: doc comment uses two spaces for a hard line break
|
||||||
|
--> tests/ui/doc/doc_comment_double_space_linebreaks.rs:90:16
|
||||||
|
|
|
||||||
|
LL | /// here we mix
|
||||||
|
| ^^
|
||||||
|
LL | /// double spaces\
|
||||||
|
LL | /// and also
|
||||||
|
| ^^
|
||||||
|
LL | /// adding backslash\
|
||||||
|
LL | /// to some of them
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: replace this double space with a backslash: `\`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue