aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs35
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
41fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool {
42 match kind {
43 BIN_EXPR | RANGE_EXPR | IF_EXPR => false,
44 _ => true,
45 }
46}
47
41pub(crate) fn expr_block_contents(p: &mut Parser) { 48pub(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() {