auto merge of #17218 : iliekturtles/rust/2789-invalid-doc-comment, r=huonw

Display an explicit message about items missing after sugared doc
comment attributes. References #2789.

 * I tried looking through `parser.rs` for an appropriate location for `expected_item_err` and ended up putting it just above the first use. Is there a better location?
 * Did I add enough test cases? Too many? Should I add more cases for the original error message?
This commit is contained in:
bors 2014-09-20 23:15:48 +00:00
commit 9c39b6c564
8 changed files with 120 additions and 11 deletions

View file

@ -3480,22 +3480,32 @@ impl<'a> Parser<'a> {
})
}
/// Get an expected item after attributes error message.
fn expected_item_err(attrs: &[Attribute]) -> &'static str {
match attrs.last() {
Some(&Attribute { node: ast::Attribute_ { is_sugared_doc: true, .. }, .. }) => {
"expected item after doc comment"
}
_ => "expected item after attributes",
}
}
/// Parse a statement. may include decl.
/// Precondition: any attributes are parsed already
pub fn parse_stmt(&mut self, item_attrs: Vec<Attribute>) -> P<Stmt> {
maybe_whole!(self, NtStmt);
fn check_expected_item(p: &mut Parser, found_attrs: bool) {
fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) {
// If we have attributes then we should have an item
if found_attrs {
if !attrs.is_empty() {
let last_span = p.last_span;
p.span_err(last_span, "expected item after attributes");
p.span_err(last_span, Parser::expected_item_err(attrs));
}
}
let lo = self.span.lo;
if self.is_keyword(keywords::Let) {
check_expected_item(self, !item_attrs.is_empty());
check_expected_item(self, item_attrs.as_slice());
self.expect_keyword(keywords::Let);
let decl = self.parse_let();
P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
@ -3504,7 +3514,7 @@ impl<'a> Parser<'a> {
&& self.look_ahead(1, |t| *t == token::NOT) {
// it's a macro invocation:
check_expected_item(self, !item_attrs.is_empty());
check_expected_item(self, item_attrs.as_slice());
// Potential trouble: if we allow macros with paths instead of
// idents, we'd need to look ahead past the whole path here...
@ -3561,6 +3571,7 @@ impl<'a> Parser<'a> {
} else {
let found_attrs = !item_attrs.is_empty();
let item_err = Parser::expected_item_err(item_attrs.as_slice());
match self.parse_item_or_view_item(item_attrs, false) {
IoviItem(i) => {
let hi = i.span.hi;
@ -3575,7 +3586,10 @@ impl<'a> Parser<'a> {
self.fatal("foreign items are not allowed here");
}
IoviNone(_) => {
check_expected_item(self, found_attrs);
if found_attrs {
let last_span = self.last_span;
self.span_err(last_span, item_err);
}
// Remainder are line-expr stmts.
let e = self.parse_expr_res(RestrictionStmtExpr);
@ -3653,7 +3667,8 @@ impl<'a> Parser<'a> {
token::SEMI => {
if !attributes_box.is_empty() {
let last_span = self.last_span;
self.span_err(last_span, "expected item after attributes");
self.span_err(last_span,
Parser::expected_item_err(attributes_box.as_slice()));
attributes_box = Vec::new();
}
self.bump(); // empty
@ -3739,7 +3754,8 @@ impl<'a> Parser<'a> {
if !attributes_box.is_empty() {
let last_span = self.last_span;
self.span_err(last_span, "expected item after attributes");
self.span_err(last_span,
Parser::expected_item_err(attributes_box.as_slice()));
}
let hi = self.span.hi;
@ -4685,7 +4701,8 @@ impl<'a> Parser<'a> {
if first && attrs_remaining_len > 0u {
// We parsed attributes for the first item but didn't find it
let last_span = self.last_span;
self.span_err(last_span, "expected item after attributes");
self.span_err(last_span,
Parser::expected_item_err(attrs_remaining.as_slice()));
}
ast::Mod {
@ -4922,7 +4939,7 @@ impl<'a> Parser<'a> {
if !attrs_remaining.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
"expected item after attributes");
Parser::expected_item_err(attrs_remaining.as_slice()));
}
assert!(self.token == token::RBRACE);
ast::ForeignMod {

View file

@ -0,0 +1,11 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(Show)] //~ERROR expected item after attributes

View file

@ -0,0 +1,12 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// hi
#[deriving(Show)] //~ERROR expected item after attributes

View file

@ -0,0 +1,11 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// hi //~ERROR expected item after doc comment

View file

@ -0,0 +1,14 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern {
/// hi
}
//~^^ ERROR expected item after doc comment

View file

@ -0,0 +1,15 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
/// hi
println!("hi");
//~^^ ERROR expected item after doc comment
}

View file

@ -0,0 +1,14 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
println!("Hi"); /// hi
//~^ ERROR expected item after doc comment
}

View file

@ -0,0 +1,15 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
/// hi
;
//~^^ ERROR expected item after doc comment
}