diff options
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index e35c46a5e..c8ce07179 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -38,6 +38,13 @@ pub(crate) fn block(p: &mut Parser) { | |||
38 | m.complete(p, BLOCK); | 38 | m.complete(p, BLOCK); |
39 | } | 39 | } |
40 | 40 | ||
41 | fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool { | ||
42 | match kind { | ||
43 | BIN_EXPR | RANGE_EXPR | IF_EXPR => false, | ||
44 | _ => true, | ||
45 | } | ||
46 | } | ||
47 | |||
41 | pub(crate) fn expr_block_contents(p: &mut Parser) { | 48 | pub(crate) fn expr_block_contents(p: &mut Parser) { |
42 | // This is checked by a validator | 49 | // This is checked by a validator |
43 | attributes::inner_attributes(p); | 50 | attributes::inner_attributes(p); |
@@ -62,6 +69,7 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
62 | // #[C] #[D] {} | 69 | // #[C] #[D] {} |
63 | // #[D] return (); | 70 | // #[D] return (); |
64 | // } | 71 | // } |
72 | let has_attrs = p.at(POUND); | ||
65 | attributes::outer_attributes(p); | 73 | attributes::outer_attributes(p); |
66 | if p.at(LET_KW) { | 74 | if p.at(LET_KW) { |
67 | let_stmt(p, m); | 75 | let_stmt(p, m); |
@@ -74,18 +82,17 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
74 | }; | 82 | }; |
75 | 83 | ||
76 | let (cm, blocklike) = expr_stmt(p); | 84 | let (cm, blocklike) = expr_stmt(p); |
77 | let cm = match cm { | 85 | |
78 | None => { | 86 | if let Some(cm) = &cm { |
79 | if p.at(R_CURLY) { | 87 | if has_attrs && !is_expr_stmt_attr_allowed(cm.kind()) { |
80 | m.abandon(p); | 88 | // test_err attr_on_expr_not_allowed |
81 | } else { | 89 | // fn foo() { |
82 | p.expect(SEMI); | 90 | // #[A] 1 + 2; |
83 | m.complete(p, EXPR_STMT); | 91 | // #[B] if true {}; |
84 | } | 92 | // } |
85 | continue; | 93 | p.error(format!("attributes are not allowed on {:?}", cm.kind())); |
86 | } | 94 | } |
87 | Some(cm) => cm, | 95 | } |
88 | }; | ||
89 | 96 | ||
90 | if p.at(R_CURLY) { | 97 | if p.at(R_CURLY) { |
91 | // test attr_on_last_expr_in_block | 98 | // test attr_on_last_expr_in_block |
@@ -93,7 +100,11 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
93 | // { #[A] bar!()? } | 100 | // { #[A] bar!()? } |
94 | // #[B] &() | 101 | // #[B] &() |
95 | // } | 102 | // } |
96 | m.contract_child(p, cm); | 103 | if let Some(cm) = cm { |
104 | m.contract_child(p, cm); | ||
105 | } else { | ||
106 | m.abandon(p); | ||
107 | } | ||
97 | } else { | 108 | } else { |
98 | // test no_semi_after_block | 109 | // test no_semi_after_block |
99 | // fn foo() { | 110 | // fn foo() { |