Skip to content

Commit 1cebf98

Browse files
Make a lint instead
1 parent b68a03b commit 1cebf98

File tree

8 files changed

+71
-91
lines changed

8 files changed

+71
-91
lines changed

src/librustc/hir/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,13 @@ impl Decl_ {
892892
DeclItem(_) => &[]
893893
}
894894
}
895+
896+
pub fn is_local(&self) -> bool {
897+
match *self {
898+
Decl_::DeclLocal(_) => true,
899+
_ => false,
900+
}
901+
}
895902
}
896903

897904
/// represents one arm of a 'match'

src/librustc_lint/builtin.rs

+40
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,46 @@ impl EarlyLintPass for IllegalFloatLiteralPattern {
722722
}
723723
}
724724

725+
declare_lint! {
726+
pub UNUSED_DOC_COMMENT,
727+
Warn,
728+
"detects doc comments that aren't used by rustdoc"
729+
}
730+
731+
#[derive(Copy, Clone)]
732+
pub struct UnusedDocComment;
733+
734+
impl LintPass for UnusedDocComment {
735+
fn get_lints(&self) -> LintArray {
736+
lint_array![UNUSED_DOC_COMMENT]
737+
}
738+
}
739+
740+
impl UnusedDocComment {
741+
fn warn_if_doc<'a, 'tcx,
742+
I: Iterator<Item=&'a ast::Attribute>,
743+
C: LintContext<'tcx>>(&self, mut attrs: I, cx: &C) {
744+
if let Some(attr) = attrs.find(|a| a.is_value_str() && a.check_name("doc")) {
745+
cx.struct_span_lint(UNUSED_DOC_COMMENT, attr.span, "doc comment not used by rustdoc")
746+
.emit();
747+
}
748+
}
749+
}
750+
751+
impl EarlyLintPass for UnusedDocComment {
752+
fn check_local(&mut self, cx: &EarlyContext, decl: &ast::Local) {
753+
self.warn_if_doc(decl.attrs.iter(), cx);
754+
}
755+
756+
fn check_arm(&mut self, cx: &EarlyContext, arm: &ast::Arm) {
757+
self.warn_if_doc(arm.attrs.iter(), cx);
758+
}
759+
760+
fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
761+
self.warn_if_doc(expr.attrs.iter(), cx);
762+
}
763+
}
764+
725765
declare_lint! {
726766
pub UNCONDITIONAL_RECURSION,
727767
Warn,

src/librustc_lint/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
111111
UnusedImportBraces,
112112
AnonymousParameters,
113113
IllegalFloatLiteralPattern,
114+
UnusedDocComment,
114115
);
115116

116117
add_early_builtin_with_new!(sess,

src/libsyntax/ast.rs

+7
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,13 @@ impl Stmt {
718718
};
719719
self
720720
}
721+
722+
pub fn is_item(&self) -> bool {
723+
match self.node {
724+
StmtKind::Local(_) => true,
725+
_ => false,
726+
}
727+
}
721728
}
722729

723730
impl fmt::Debug for Stmt {

src/libsyntax/parse/parser.rs

-32
Original file line numberDiff line numberDiff line change
@@ -2420,12 +2420,6 @@ impl<'a> Parser<'a> {
24202420
expr.map(|mut expr| {
24212421
attrs.extend::<Vec<_>>(expr.attrs.into());
24222422
expr.attrs = attrs;
2423-
if if let Some(ref doc) = expr.attrs.iter().find(|x| x.is_sugared_doc) {
2424-
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
2425-
true
2426-
} else { false } {
2427-
return expr;
2428-
}
24292423
match expr.node {
24302424
ExprKind::If(..) | ExprKind::IfLet(..) => {
24312425
if !expr.attrs.is_empty() {
@@ -3110,9 +3104,6 @@ impl<'a> Parser<'a> {
31103104

31113105
// `else` token already eaten
31123106
pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
3113-
if self.prev_token_kind == PrevTokenKind::DocComment {
3114-
return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
3115-
}
31163107
if self.eat_keyword(keywords::If) {
31173108
return self.parse_if_expr(ThinVec::new());
31183109
} else {
@@ -3126,9 +3117,6 @@ impl<'a> Parser<'a> {
31263117
span_lo: Span,
31273118
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
31283119
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
3129-
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3130-
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3131-
}
31323120

31333121
let pat = self.parse_pat()?;
31343122
self.expect_keyword(keywords::In)?;
@@ -3144,9 +3132,6 @@ impl<'a> Parser<'a> {
31443132
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
31453133
span_lo: Span,
31463134
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3147-
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3148-
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3149-
}
31503135
if self.token.is_keyword(keywords::Let) {
31513136
return self.parse_while_let_expr(opt_ident, span_lo, attrs);
31523137
}
@@ -3175,9 +3160,6 @@ impl<'a> Parser<'a> {
31753160
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
31763161
span_lo: Span,
31773162
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3178-
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3179-
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3180-
}
31813163
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
31823164
attrs.extend(iattrs);
31833165
let span = span_lo.to(body.span);
@@ -3188,19 +3170,13 @@ impl<'a> Parser<'a> {
31883170
pub fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
31893171
-> PResult<'a, P<Expr>>
31903172
{
3191-
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3192-
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3193-
}
31943173
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
31953174
attrs.extend(iattrs);
31963175
Ok(self.mk_expr(span_lo.to(body.span), ExprKind::Catch(body), attrs))
31973176
}
31983177

31993178
// `match` token already eaten
32003179
fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3201-
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3202-
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3203-
}
32043180
let match_span = self.prev_span;
32053181
let lo = self.prev_span;
32063182
let discriminant = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL,
@@ -3238,9 +3214,6 @@ impl<'a> Parser<'a> {
32383214
maybe_whole!(self, NtArm, |x| x);
32393215

32403216
let attrs = self.parse_outer_attributes()?;
3241-
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3242-
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3243-
}
32443217
let pats = self.parse_pats()?;
32453218
let guard = if self.eat_keyword(keywords::If) {
32463219
Some(self.parse_expr()?)
@@ -3695,9 +3668,6 @@ impl<'a> Parser<'a> {
36953668

36963669
/// Parse a local variable declaration
36973670
fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
3698-
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3699-
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3700-
}
37013671
let lo = self.span;
37023672
let pat = self.parse_pat()?;
37033673

@@ -4187,8 +4157,6 @@ impl<'a> Parser<'a> {
41874157
stmts.push(stmt);
41884158
} else if self.token == token::Eof {
41894159
break;
4190-
} else if let token::DocComment(_) = self.token {
4191-
return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
41924160
} else {
41934161
// Found only `;` or `}`.
41944162
continue;

src/test/compile-fail/useless_comment.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,23 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
fn foo3() -> i32 {
12-
let mut x = 12;
13-
/// z //~ ERROR E0585
14-
while x < 1 {
15-
/// x //~ ERROR E0585
16-
//~^ ERROR attributes on non-item statements and expressions are experimental
17-
x += 1;
11+
#![deny(unused_doc_comment)]
12+
13+
fn foo() {
14+
/// a //~ ERROR unused doc comment
15+
let x = 12;
16+
17+
/// b //~ ERROR unused doc comment
18+
match x {
19+
/// c //~ ERROR unused doc comment
20+
1 => {},
21+
_ => {}
1822
}
19-
/// d //~ ERROR E0585
20-
return x;
23+
24+
/// foo //~ ERROR unused doc comment
25+
unsafe {}
2126
}
2227

2328
fn main() {
24-
/// e //~ ERROR E0585
25-
foo3();
26-
}
29+
foo();
30+
}

src/test/compile-fail/useless_comment2.rs

-25
This file was deleted.

src/test/compile-fail/useless_comment3.rs

-22
This file was deleted.

0 commit comments

Comments
 (0)