}
}
+declare_lint! {
+ pub UNUSED_DOC_COMMENT,
+ Warn,
+ "detects doc comments that aren't used by rustdoc"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedDocComment;
+
+impl LintPass for UnusedDocComment {
+ fn get_lints(&self) -> LintArray {
+ lint_array![UNUSED_DOC_COMMENT]
+ }
+}
+
+impl UnusedDocComment {
+ fn warn_if_doc<'a, 'tcx,
+ I: Iterator<Item=&'a ast::Attribute>,
+ 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_COMMENT, attr.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);
+ }
+
+ fn check_arm(&mut self, cx: &EarlyContext, arm: &ast::Arm) {
+ self.warn_if_doc(arm.attrs.iter(), cx);
+ }
+
+ fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
+ self.warn_if_doc(expr.attrs.iter(), cx);
+ }
+}
+
declare_lint! {
pub UNCONDITIONAL_RECURSION,
Warn,
expr.map(|mut expr| {
attrs.extend::<Vec<_>>(expr.attrs.into());
expr.attrs = attrs;
- if if let Some(ref doc) = expr.attrs.iter().find(|x| x.is_sugared_doc) {
- self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
- true
- } else { false } {
- return expr;
- }
match expr.node {
ExprKind::If(..) | ExprKind::IfLet(..) => {
if !expr.attrs.is_empty() {
// `else` token already eaten
pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
- if self.prev_token_kind == PrevTokenKind::DocComment {
- return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
- }
if self.eat_keyword(keywords::If) {
return self.parse_if_expr(ThinVec::new());
} else {
span_lo: Span,
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
- if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
- self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
- }
let pat = self.parse_pat()?;
self.expect_keyword(keywords::In)?;
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
span_lo: Span,
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
- if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
- self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
- }
if self.token.is_keyword(keywords::Let) {
return self.parse_while_let_expr(opt_ident, span_lo, attrs);
}
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
span_lo: Span,
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
- if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
- self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
- }
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
let span = span_lo.to(body.span);
pub fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>>
{
- if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
- self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
- }
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
Ok(self.mk_expr(span_lo.to(body.span), ExprKind::Catch(body), attrs))
// `match` token already eaten
fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
- if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
- self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
- }
let match_span = self.prev_span;
let lo = self.prev_span;
let discriminant = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL,
maybe_whole!(self, NtArm, |x| x);
let attrs = self.parse_outer_attributes()?;
- if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
- self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
- }
let pats = self.parse_pats()?;
let guard = if self.eat_keyword(keywords::If) {
Some(self.parse_expr()?)
/// Parse a local variable declaration
fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
- if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
- self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
- }
let lo = self.span;
let pat = self.parse_pat()?;
stmts.push(stmt);
} else if self.token == token::Eof {
break;
- } else if let token::DocComment(_) = self.token {
- return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
} else {
// Found only `;` or `}`.
continue;