685: Support attributes on let statements r=matklad a=DJMcNab

Fix #677.

Co-authored-by: DJMcNab <36049421+djmcnab@users.noreply.github.com>
This commit is contained in:
bors[bot]
2019-01-27 09:04:02 +00:00
4 changed files with 125 additions and 36 deletions

View File

@@ -45,7 +45,6 @@ pub(crate) fn block(p: &mut Parser) {
while !p.at(EOF) && !p.at(R_CURLY) { while !p.at(EOF) && !p.at(R_CURLY) {
match p.current() { match p.current() {
LET_KW => let_stmt(p),
// test nocontentexpr // test nocontentexpr
// fn foo(){ // fn foo(){
// ;;;some_expr();;;;{;;;};;;;Ok(()) // ;;;some_expr();;;;{;;;};;;;Ok(())
@@ -55,41 +54,54 @@ pub(crate) fn block(p: &mut Parser) {
// test block_items // test block_items
// fn a() { fn b() {} } // fn a() { fn b() {} }
let m = p.start(); let m = p.start();
match items::maybe_item(p, items::ItemFlavor::Mod) { let has_attrs = p.at(POUND);
items::MaybeItem::Item(kind) => { attributes::outer_attributes(p);
m.complete(p, kind); if p.at(LET_KW) {
} let_stmt(p, m);
items::MaybeItem::Modifiers => { } else {
m.abandon(p); match items::maybe_item(p, items::ItemFlavor::Mod) {
p.error("expected an item"); items::MaybeItem::Item(kind) => {
} m.complete(p, kind);
// test pub_expr }
// fn foo() { pub 92; } //FIXME items::MaybeItem::Modifiers => {
items::MaybeItem::None => {
let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
if p.at(R_CURLY) {
m.abandon(p); m.abandon(p);
} else { p.error("expected an item");
// test no_semi_after_block }
// fn foo() { // test pub_expr
// if true {} // fn foo() { pub 92; } //FIXME
// loop {} items::MaybeItem::None => {
// match () {} if has_attrs {
// while true {} m.abandon(p);
// for _ in () {} p.error(
// {} "expected a let statement or an item after attributes in block",
// {} );
// macro_rules! test {
// () => {}
// }
// test!{}
// }
if is_blocklike {
p.eat(SEMI);
} else { } else {
p.expect(SEMI); let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
if p.at(R_CURLY) {
m.abandon(p);
} else {
// test no_semi_after_block
// fn foo() {
// if true {}
// loop {}
// match () {}
// while true {}
// for _ in () {}
// {}
// {}
// macro_rules! test {
// () => {}
// }
// test!{}
// }
if is_blocklike {
p.eat(SEMI);
} else {
p.expect(SEMI);
}
m.complete(p, EXPR_STMT);
}
} }
m.complete(p, EXPR_STMT);
} }
} }
} }
@@ -106,9 +118,8 @@ pub(crate) fn block(p: &mut Parser) {
// let c = 92; // let c = 92;
// let d: i32 = 92; // let d: i32 = 92;
// } // }
fn let_stmt(p: &mut Parser) { fn let_stmt(p: &mut Parser, m: Marker) {
assert!(p.at(LET_KW)); assert!(p.at(LET_KW));
let m = p.start();
p.bump(); p.bump();
patterns::pattern(p); patterns::pattern(p);
if p.at(COLON) { if p.at(COLON) {

View File

@@ -36,6 +36,7 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![
pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
let m = p.start(); let m = p.start();
attributes::outer_attributes(p);
match maybe_item(p, flavor) { match maybe_item(p, flavor) {
MaybeItem::Item(kind) => { MaybeItem::Item(kind) => {
m.complete(p, kind); m.complete(p, kind);
@@ -79,7 +80,6 @@ pub(super) enum MaybeItem {
} }
pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
attributes::outer_attributes(p);
opt_visibility(p); opt_visibility(p);
if let Some(kind) = items_without_modifiers(p) { if let Some(kind) = items_without_modifiers(p) {
return MaybeItem::Item(kind); return MaybeItem::Item(kind);

View File

@@ -0,0 +1,5 @@
// https://github.com/rust-analyzer/rust-analyzer/issues/677
fn main() {
#[cfg(feature = "backtrace")]
let exit_code = panic::catch_unwind(move || main());
}

View File

@@ -0,0 +1,73 @@
SOURCE_FILE@[0; 166)
FN_DEF@[0; 165)
COMMENT@[0; 60)
WHITESPACE@[60; 61)
FN_KW@[61; 63)
WHITESPACE@[63; 64)
NAME@[64; 68)
IDENT@[64; 68) "main"
PARAM_LIST@[68; 70)
L_PAREN@[68; 69)
R_PAREN@[69; 70)
WHITESPACE@[70; 71)
BLOCK@[71; 165)
L_CURLY@[71; 72)
WHITESPACE@[72; 77)
LET_STMT@[77; 163)
ATTR@[77; 106)
POUND@[77; 78)
TOKEN_TREE@[78; 106)
L_BRACK@[78; 79)
IDENT@[79; 82) "cfg"
TOKEN_TREE@[82; 105)
L_PAREN@[82; 83)
IDENT@[83; 90) "feature"
WHITESPACE@[90; 91)
EQ@[91; 92)
WHITESPACE@[92; 93)
STRING@[93; 104)
R_PAREN@[104; 105)
R_BRACK@[105; 106)
WHITESPACE@[106; 111)
LET_KW@[111; 114)
WHITESPACE@[114; 115)
BIND_PAT@[115; 124)
NAME@[115; 124)
IDENT@[115; 124) "exit_code"
WHITESPACE@[124; 125)
EQ@[125; 126)
WHITESPACE@[126; 127)
CALL_EXPR@[127; 162)
PATH_EXPR@[127; 146)
PATH@[127; 146)
PATH@[127; 132)
PATH_SEGMENT@[127; 132)
NAME_REF@[127; 132)
IDENT@[127; 132) "panic"
COLONCOLON@[132; 134)
PATH_SEGMENT@[134; 146)
NAME_REF@[134; 146)
IDENT@[134; 146) "catch_unwind"
ARG_LIST@[146; 162)
L_PAREN@[146; 147)
LAMBDA_EXPR@[147; 161)
MOVE_KW@[147; 151)
WHITESPACE@[151; 152)
PARAM_LIST@[152; 154)
PIPE@[152; 153)
PIPE@[153; 154)
WHITESPACE@[154; 155)
CALL_EXPR@[155; 161)
PATH_EXPR@[155; 159)
PATH@[155; 159)
PATH_SEGMENT@[155; 159)
NAME_REF@[155; 159)
IDENT@[155; 159) "main"
ARG_LIST@[159; 161)
L_PAREN@[159; 160)
R_PAREN@[160; 161)
R_PAREN@[161; 162)
SEMI@[162; 163)
WHITESPACE@[163; 164)
R_CURLY@[164; 165)
WHITESPACE@[165; 166)