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_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
|
||||
[`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_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
|
||||
|
|
|
@ -137,6 +137,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::disallowed_names::DISALLOWED_NAMES_INFO,
|
||||
crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_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_LAZY_CONTINUATION_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)]
|
||||
|
||||
mod lazy_continuation;
|
||||
mod too_long_first_doc_paragraph;
|
||||
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::attrs::is_doc_hidden;
|
||||
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::source::snippet_opt;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::visitors::Visitable;
|
||||
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 url::Url;
|
||||
|
||||
mod doc_comment_double_space_linebreaks;
|
||||
mod include_in_doc_without_cfg;
|
||||
mod lazy_continuation;
|
||||
mod link_with_quotes;
|
||||
mod markdown;
|
||||
mod missing_headers;
|
||||
mod needless_doctest_main;
|
||||
mod suspicious_doc_comments;
|
||||
mod too_long_first_doc_paragraph;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
@ -567,6 +568,39 @@ declare_clippy_lint! {
|
|||
"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 {
|
||||
valid_idents: FxHashSet<String>,
|
||||
check_private_items: bool,
|
||||
|
@ -598,6 +632,7 @@ impl_lint_pass!(Documentation => [
|
|||
DOC_OVERINDENTED_LIST_ITEMS,
|
||||
TOO_LONG_FIRST_DOC_PARAGRAPH,
|
||||
DOC_INCLUDE_WITHOUT_CFG,
|
||||
DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS
|
||||
]);
|
||||
|
||||
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 code_level = 0;
|
||||
let mut blockquote_level = 0;
|
||||
let mut collected_breaks: Vec<Span> = Vec::new();
|
||||
let mut is_first_paragraph = true;
|
||||
|
||||
let mut containers = Vec::new();
|
||||
|
@ -1069,6 +1105,14 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||
&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) => {
|
||||
paragraph_range.end = range.end;
|
||||
|
@ -1119,6 +1163,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||
FootnoteReference(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment_double_space_linebreaks::check(cx, &collected_breaks);
|
||||
|
||||
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