Merge #685
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:
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
5
crates/ra_syntax/tests/data/parser/ok/0044_let_attrs.rs
Normal file
5
crates/ra_syntax/tests/data/parser/ok/0044_let_attrs.rs
Normal 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());
|
||||||
|
}
|
||||||
73
crates/ra_syntax/tests/data/parser/ok/0044_let_attrs.txt
Normal file
73
crates/ra_syntax/tests/data/parser/ok/0044_let_attrs.txt
Normal 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)
|
||||||
Reference in New Issue
Block a user