diff options
5 files changed, 60 insertions, 36 deletions
diff --git a/crates/ra_parser/src/grammar/attributes.rs b/crates/ra_parser/src/grammar/attributes.rs index f3158ade3..eeae37aef 100644 --- a/crates/ra_parser/src/grammar/attributes.rs +++ b/crates/ra_parser/src/grammar/attributes.rs | |||
@@ -8,6 +8,28 @@ pub(super) fn inner_attributes(p: &mut Parser) { | |||
8 | } | 8 | } |
9 | } | 9 | } |
10 | 10 | ||
11 | pub(super) fn with_outer_attributes( | ||
12 | p: &mut Parser, | ||
13 | f: impl Fn(&mut Parser) -> Option<CompletedMarker>, | ||
14 | ) -> bool { | ||
15 | let am = p.start(); | ||
16 | let has_attrs = p.at(T![#]); | ||
17 | attributes::outer_attributes(p); | ||
18 | let cm = f(p); | ||
19 | let success = cm.is_some(); | ||
20 | |||
21 | match (has_attrs, cm) { | ||
22 | (true, Some(cm)) => { | ||
23 | let kind = cm.kind(); | ||
24 | cm.undo_completion(p).abandon(p); | ||
25 | am.complete(p, kind); | ||
26 | } | ||
27 | _ => am.abandon(p), | ||
28 | } | ||
29 | |||
30 | success | ||
31 | } | ||
32 | |||
11 | pub(super) fn outer_attributes(p: &mut Parser) { | 33 | pub(super) fn outer_attributes(p: &mut Parser) { |
12 | while p.at(T![#]) { | 34 | while p.at(T![#]) { |
13 | attribute(p, false) | 35 | attribute(p, false) |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 81d4f75f9..d733499d1 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -14,9 +14,9 @@ pub(super) enum StmtWithSemi { | |||
14 | 14 | ||
15 | const EXPR_FIRST: TokenSet = LHS_FIRST; | 15 | const EXPR_FIRST: TokenSet = LHS_FIRST; |
16 | 16 | ||
17 | pub(super) fn expr(p: &mut Parser) -> BlockLike { | 17 | pub(super) fn expr(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) { |
18 | let r = Restrictions { forbid_structs: false, prefer_stmt: false }; | 18 | let r = Restrictions { forbid_structs: false, prefer_stmt: false }; |
19 | expr_bp(p, r, 1).1 | 19 | expr_bp(p, r, 1) |
20 | } | 20 | } |
21 | 21 | ||
22 | pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) { | 22 | pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) { |
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 4ac1d6334..700994e80 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -192,9 +192,8 @@ fn array_expr(p: &mut Parser) -> CompletedMarker { | |||
192 | // 1, | 192 | // 1, |
193 | // 2, | 193 | // 2, |
194 | // ]; | 194 | // ]; |
195 | attributes::outer_attributes(p); | 195 | attributes::with_outer_attributes(p, |p| expr(p).0); |
196 | 196 | ||
197 | expr(p); | ||
198 | if p.eat(T![;]) { | 197 | if p.eat(T![;]) { |
199 | expr(p); | 198 | expr(p); |
200 | p.expect(T![']']); | 199 | p.expect(T![']']); |
@@ -212,12 +211,15 @@ fn array_expr(p: &mut Parser) -> CompletedMarker { | |||
212 | // #[cfg(test)] | 211 | // #[cfg(test)] |
213 | // 2, | 212 | // 2, |
214 | // ]; | 213 | // ]; |
215 | attributes::outer_attributes(p); | 214 | if !attributes::with_outer_attributes(p, |p| { |
216 | if !p.at_ts(EXPR_FIRST) { | 215 | if !p.at_ts(EXPR_FIRST) { |
217 | p.error("expected expression"); | 216 | p.error("expected expression"); |
217 | return None; | ||
218 | } | ||
219 | expr(p).0 | ||
220 | }) { | ||
218 | break; | 221 | break; |
219 | } | 222 | } |
220 | expr(p); | ||
221 | } | 223 | } |
222 | p.expect(T![']']); | 224 | p.expect(T![']']); |
223 | m.complete(p, ARRAY_EXPR) | 225 | m.complete(p, ARRAY_EXPR) |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt b/crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt index 8f2e91bdf..2e3a13005 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt | |||
@@ -27,20 +27,20 @@ SOURCE_FILE@[0; 56) | |||
27 | ARRAY_EXPR@[23; 54) | 27 | ARRAY_EXPR@[23; 54) |
28 | L_BRACK@[23; 24) "[" | 28 | L_BRACK@[23; 24) "[" |
29 | WHITESPACE@[24; 28) "\n " | 29 | WHITESPACE@[24; 28) "\n " |
30 | ATTR@[28; 40) | 30 | LITERAL@[28; 45) |
31 | POUND@[28; 29) "#" | 31 | ATTR@[28; 40) |
32 | L_BRACK@[29; 30) "[" | 32 | POUND@[28; 29) "#" |
33 | PATH@[30; 33) | 33 | L_BRACK@[29; 30) "[" |
34 | PATH_SEGMENT@[30; 33) | 34 | PATH@[30; 33) |
35 | NAME_REF@[30; 33) | 35 | PATH_SEGMENT@[30; 33) |
36 | IDENT@[30; 33) "cfg" | 36 | NAME_REF@[30; 33) |
37 | TOKEN_TREE@[33; 39) | 37 | IDENT@[30; 33) "cfg" |
38 | L_PAREN@[33; 34) "(" | 38 | TOKEN_TREE@[33; 39) |
39 | IDENT@[34; 38) "test" | 39 | L_PAREN@[33; 34) "(" |
40 | R_PAREN@[38; 39) ")" | 40 | IDENT@[34; 38) "test" |
41 | R_BRACK@[39; 40) "]" | 41 | R_PAREN@[38; 39) ")" |
42 | WHITESPACE@[40; 44) "\n " | 42 | R_BRACK@[39; 40) "]" |
43 | LITERAL@[44; 45) | 43 | WHITESPACE@[40; 44) "\n " |
44 | INT_NUMBER@[44; 45) "1" | 44 | INT_NUMBER@[44; 45) "1" |
45 | COMMA@[45; 46) "," | 45 | COMMA@[45; 46) "," |
46 | WHITESPACE@[46; 50) "\n " | 46 | WHITESPACE@[46; 50) "\n " |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt b/crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt index 41914eb8e..1bb8a0afc 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt | |||
@@ -31,20 +31,20 @@ SOURCE_FILE@[0; 56) | |||
31 | INT_NUMBER@[28; 29) "1" | 31 | INT_NUMBER@[28; 29) "1" |
32 | COMMA@[29; 30) "," | 32 | COMMA@[29; 30) "," |
33 | WHITESPACE@[30; 34) "\n " | 33 | WHITESPACE@[30; 34) "\n " |
34 | ATTR@[34; 46) | 34 | LITERAL@[34; 51) |
35 | POUND@[34; 35) "#" | 35 | ATTR@[34; 46) |
36 | L_BRACK@[35; 36) "[" | 36 | POUND@[34; 35) "#" |
37 | PATH@[36; 39) | 37 | L_BRACK@[35; 36) "[" |
38 | PATH_SEGMENT@[36; 39) | 38 | PATH@[36; 39) |
39 | NAME_REF@[36; 39) | 39 | PATH_SEGMENT@[36; 39) |
40 | IDENT@[36; 39) "cfg" | 40 | NAME_REF@[36; 39) |
41 | TOKEN_TREE@[39; 45) | 41 | IDENT@[36; 39) "cfg" |
42 | L_PAREN@[39; 40) "(" | 42 | TOKEN_TREE@[39; 45) |
43 | IDENT@[40; 44) "test" | 43 | L_PAREN@[39; 40) "(" |
44 | R_PAREN@[44; 45) ")" | 44 | IDENT@[40; 44) "test" |
45 | R_BRACK@[45; 46) "]" | 45 | R_PAREN@[44; 45) ")" |
46 | WHITESPACE@[46; 50) "\n " | 46 | R_BRACK@[45; 46) "]" |
47 | LITERAL@[50; 51) | 47 | WHITESPACE@[46; 50) "\n " |
48 | INT_NUMBER@[50; 51) "2" | 48 | INT_NUMBER@[50; 51) "2" |
49 | COMMA@[51; 52) "," | 49 | COMMA@[51; 52) "," |
50 | WHITESPACE@[52; 53) "\n" | 50 | WHITESPACE@[52; 53) "\n" |