Skip to content

Commit 3093b29

Browse files
committed
WIP: empty doc span is still broken
1 parent a2c1d56 commit 3093b29

File tree

5 files changed

+142
-3
lines changed

5 files changed

+142
-3
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5158,6 +5158,7 @@ Released 2018-09-13
51585158
[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec
51595159
[`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute
51605160
[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
5161+
[`empty_docs`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_docs
51615162
[`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
51625163
[`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
51635164
[`empty_enum_variants_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum_variants_with_brackets

clippy_lints/src/declared_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
139139
crate::disallowed_types::DISALLOWED_TYPES_INFO,
140140
crate::doc::DOC_LINK_WITH_QUOTES_INFO,
141141
crate::doc::DOC_MARKDOWN_INFO,
142+
crate::doc::EMPTY_DOCS_INFO,
142143
crate::doc::MISSING_ERRORS_DOC_INFO,
143144
crate::doc::MISSING_PANICS_DOC_INFO,
144145
crate::doc::MISSING_SAFETY_DOC_INFO,

clippy_lints/src/doc/mod.rs

+62-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use rustc_resolve::rustdoc::{
2323
};
2424
use rustc_session::impl_lint_pass;
2525
use rustc_span::edition::Edition;
26-
use rustc_span::{sym, Span};
26+
use rustc_span::{sym, Span, DUMMY_SP};
2727
use std::ops::Range;
2828
use url::Url;
2929

@@ -338,6 +338,29 @@ declare_clippy_lint! {
338338
"suspicious usage of (outer) doc comments"
339339
}
340340

341+
declare_clippy_lint! {
342+
/// ### What it does
343+
/// Detects documentation that is empty.
344+
/// ### Why is this bad?
345+
/// It is unlikely that there is any reason to have empty documentation for an item
346+
/// ### Example
347+
/// ```rust
348+
/// ///
349+
/// fn returns_true() -> bool {
350+
/// true
351+
/// }
352+
/// Use instead:
353+
/// ```rust
354+
/// fn returns_true() -> bool {
355+
/// true
356+
/// }
357+
/// ```
358+
#[clippy::version = "1.78.0"]
359+
pub EMPTY_DOCS,
360+
suspicious,
361+
"docstrings exist but documentation is empty"
362+
}
363+
341364
#[derive(Clone)]
342365
pub struct Documentation {
343366
valid_idents: FxHashSet<String>,
@@ -364,7 +387,8 @@ impl_lint_pass!(Documentation => [
364387
NEEDLESS_DOCTEST_MAIN,
365388
TEST_ATTR_IN_DOCTEST,
366389
UNNECESSARY_SAFETY_DOC,
367-
SUSPICIOUS_DOC_COMMENTS
390+
SUSPICIOUS_DOC_COMMENTS,
391+
EMPTY_DOCS,
368392
]);
369393

370394
impl<'tcx> LateLintPass<'tcx> for Documentation {
@@ -378,6 +402,20 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
378402
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
379403
return;
380404
};
405+
406+
if let Some(span) = get_empty_doc_combined_span(attrs, item.span)
407+
&& headers.empty
408+
{
409+
span_lint_and_help(
410+
cx,
411+
EMPTY_DOCS,
412+
span,
413+
"empty doc comment",
414+
None,
415+
"consider removing or filling it",
416+
);
417+
}
418+
381419
match item.kind {
382420
hir::ItemKind::Fn(ref sig, _, body_id) => {
383421
if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
@@ -477,6 +515,7 @@ struct DocHeaders {
477515
safety: bool,
478516
errors: bool,
479517
panics: bool,
518+
empty: bool,
480519
}
481520

482521
/// Does some pre-processing on raw, desugared `#[doc]` attributes such as parsing them and
@@ -509,7 +548,10 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
509548
doc.pop();
510549

511550
if doc.is_empty() {
512-
return Some(DocHeaders::default());
551+
return Some(DocHeaders {
552+
empty: true,
553+
..DocHeaders::default()
554+
});
513555
}
514556

515557
let mut cb = fake_broken_link_callback;
@@ -717,3 +759,20 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
717759
self.cx.tcx.hir()
718760
}
719761
}
762+
763+
fn get_empty_doc_combined_span(attrs: &[Attribute], item_span: Span) -> Option<Span> {
764+
let mut attrs_span = DUMMY_SP;
765+
if attrs.len() > 0 {
766+
attrs_span = attrs
767+
.iter()
768+
.map(|attr| attr.span)
769+
.fold(attrs[0].span, |acc, next| acc.to(next));
770+
}
771+
772+
match (!item_span.is_dummy(), !attrs_span.is_dummy()) {
773+
(true, true) => Some(item_span.shrink_to_lo().to(attrs_span)),
774+
(true, false) => Some(item_span),
775+
(false, true) => Some(attrs_span),
776+
(false, false) => None,
777+
}
778+
}

tests/ui/empty_docs.rs

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#![allow(unused)]
2+
#![warn(clippy::empty_docs)]
3+
4+
/// this is a struct
5+
struct Bananas {
6+
/// count
7+
count: usize,
8+
}
9+
10+
///
11+
enum Warn {
12+
///
13+
A,
14+
///
15+
B,
16+
}
17+
18+
enum WarnForB {
19+
/// it's ok
20+
A,
21+
///
22+
B,
23+
}
24+
25+
#[doc = ""]
26+
#[doc = ""]
27+
fn warn_about_this() {}
28+
29+
#[doc = "a fine function"]
30+
fn this_is_fine() {}
31+
32+
fn warn_about_this_as_well() {
33+
//!
34+
}
35+
36+
fn this_is_ok() {
37+
//!
38+
//! inside the function
39+
}
40+
41+
fn warn() {
42+
/*! inside the function */
43+
}

tests/ui/empty_docs.stderr

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: empty doc comment
2+
--> tests/ui/empty_docs.rs:10:1
3+
|
4+
LL | / ///
5+
LL | | enum Warn {
6+
| |_
7+
|
8+
= help: consider removing or filling it
9+
= note: `-D clippy::empty-docs` implied by `-D warnings`
10+
= help: to override `-D warnings` add `#[allow(clippy::empty_docs)]`
11+
12+
error: empty doc comment
13+
--> tests/ui/empty_docs.rs:18:1
14+
|
15+
LL | / enum WarnForB {
16+
LL | | /// it's ok
17+
LL | | A,
18+
LL | | ///
19+
LL | | B,
20+
LL | | }
21+
| |_^
22+
|
23+
= help: consider removing or filling it
24+
25+
error: empty doc comment
26+
--> tests/ui/empty_docs.rs:32:1
27+
|
28+
LL | / fn warn_about_this_as_well() {
29+
LL | | //!
30+
| |_______^
31+
|
32+
= help: consider removing or filling it
33+
34+
error: aborting due to 3 previous errors
35+

0 commit comments

Comments
 (0)