From 018d4d265fb40ea4301da5dc339bff962a6faa57 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 23 Jan 2019 13:44:43 -0500 Subject: [PATCH] improve unused doc comment diagnostic reporting Report all unused attributes on a given doc comment instead of just the first one, and extend the span of sugared doc comments to encompass the whole comment. --- src/librustc_lint/builtin.rs | 41 +++++++++++++++++++++++------- src/test/ui/useless_comment.rs | 8 +++++- src/test/ui/useless_comment.stderr | 24 +++++++++++++---- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index aafae28b49e..284bfcd4014 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -802,27 +802,50 @@ fn get_lints(&self) -> LintArray { } impl UnusedDocComment { - fn warn_if_doc<'a, 'tcx, - I: Iterator, - C: LintContext<'tcx>>(&self, mut attrs: I, cx: &C) { - if let Some(attr) = attrs.find(|a| a.is_value_str() && a.check_name("doc")) { - cx.struct_span_lint(UNUSED_DOC_COMMENTS, attr.span, "doc comment not used by rustdoc") - .emit(); + fn warn_if_doc(&self, cx: &EarlyContext, attrs: &[ast::Attribute]) { + let mut attrs = attrs.into_iter().peekable(); + + // Accumulate a single span for sugared doc comments. + let mut sugared_span: Option = None; + + while let Some(attr) = attrs.next() { + if attr.is_sugared_doc { + sugared_span = Some( + sugared_span.map_or_else( + || attr.span, + |span| span.with_hi(attr.span.hi()), + ), + ); + } + + if attrs.peek().map(|next_attr| next_attr.is_sugared_doc).unwrap_or_default() { + continue; + } + + let span = sugared_span.take().unwrap_or_else(|| attr.span); + + if attr.name() == "doc" { + cx.struct_span_lint( + UNUSED_DOC_COMMENTS, + span, + "doc comment not used by rustdoc", + ).emit(); + } } } } impl EarlyLintPass for UnusedDocComment { fn check_local(&mut self, cx: &EarlyContext<'_>, decl: &ast::Local) { - self.warn_if_doc(decl.attrs.iter(), cx); + self.warn_if_doc(cx, &decl.attrs); } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { - self.warn_if_doc(arm.attrs.iter(), cx); + self.warn_if_doc(cx, &arm.attrs); } fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { - self.warn_if_doc(expr.attrs.iter(), cx); + self.warn_if_doc(cx, &expr.attrs); } } diff --git a/src/test/ui/useless_comment.rs b/src/test/ui/useless_comment.rs index 531eec007fc..e8a0e3c10d2 100644 --- a/src/test/ui/useless_comment.rs +++ b/src/test/ui/useless_comment.rs @@ -4,7 +4,9 @@ fn foo() { /// a //~ ERROR doc comment not used by rustdoc let x = 12; - /// b //~ doc comment not used by rustdoc + /// multi-line //~ doc comment not used by rustdoc + /// doc comment + /// that is unused match x { /// c //~ ERROR doc comment not used by rustdoc 1 => {}, @@ -13,6 +15,10 @@ fn foo() { /// foo //~ ERROR doc comment not used by rustdoc unsafe {} + + #[doc = "foo"] //~ ERROR doc comment not used by rustdoc + #[doc = "bar"] //~ ERROR doc comment not used by rustdoc + 3; } fn main() { diff --git a/src/test/ui/useless_comment.stderr b/src/test/ui/useless_comment.stderr index cc818f6ce7c..a284c08f47a 100644 --- a/src/test/ui/useless_comment.stderr +++ b/src/test/ui/useless_comment.stderr @@ -13,20 +13,34 @@ LL | #![deny(unused_doc_comments)] error: doc comment not used by rustdoc --> $DIR/useless_comment.rs:7:5 | -LL | /// b //~ doc comment not used by rustdoc - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / /// multi-line //~ doc comment not used by rustdoc +LL | | /// doc comment +LL | | /// that is unused + | |______________________^ error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:9:9 + --> $DIR/useless_comment.rs:11:9 | LL | /// c //~ ERROR doc comment not used by rustdoc | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:14:5 + --> $DIR/useless_comment.rs:16:5 | LL | /// foo //~ ERROR doc comment not used by rustdoc | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: doc comment not used by rustdoc + --> $DIR/useless_comment.rs:19:5 + | +LL | #[doc = "foo"] //~ ERROR doc comment not used by rustdoc + | ^^^^^^^^^^^^^^ + +error: doc comment not used by rustdoc + --> $DIR/useless_comment.rs:20:5 + | +LL | #[doc = "bar"] //~ ERROR doc comment not used by rustdoc + | ^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors