diff options
author | Ryan Cumming <[email protected]> | 2019-06-30 08:59:26 +0100 |
---|---|---|
committer | Ryan Cumming <[email protected]> | 2019-06-30 09:36:54 +0100 |
commit | b01496538c938d6a0c904512a38e4325cc960334 (patch) | |
tree | a6588dc1af1094aadac540bfe90acced3fb08fea | |
parent | 27df89f47d5f0a6e8e62d517d98dda854efabc34 (diff) |
Support attributes on array members
Array members are allow to have attributes such as `#[cfg]`.
This is a bit tricky as we don't know if the first expression is an
initializer or a member until we encounter a `;`. This reuses a trick
from `stmt` where we remember if we saw an attribute and then raise an
error if the first expression ends up being an initializer.
This isn't perfect as the error isn't correctly located on the attribute
or initializer; it ends up immediately after the `;`.
7 files changed, 205 insertions, 0 deletions
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 41be283d0..5e51d667e 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -170,8 +170,28 @@ fn array_expr(p: &mut Parser) -> CompletedMarker { | |||
170 | if p.eat(T![']']) { | 170 | if p.eat(T![']']) { |
171 | return m.complete(p, ARRAY_EXPR); | 171 | return m.complete(p, ARRAY_EXPR); |
172 | } | 172 | } |
173 | |||
174 | // test first_array_member_attributes | ||
175 | // pub const A: &[i64] = &[ | ||
176 | // #[cfg(test)] | ||
177 | // 1, | ||
178 | // 2, | ||
179 | // ]; | ||
180 | let first_member_has_attrs = p.at(T![#]); | ||
181 | attributes::outer_attributes(p); | ||
182 | |||
173 | expr(p); | 183 | expr(p); |
174 | if p.eat(T![;]) { | 184 | if p.eat(T![;]) { |
185 | if first_member_has_attrs { | ||
186 | // test_err array_length_attributes | ||
187 | // pub const A: &[i64] = &[ | ||
188 | // #[cfg(test)] | ||
189 | // 1; | ||
190 | // 2, | ||
191 | // ]; | ||
192 | p.error("removing an expression is not supported in this position"); | ||
193 | } | ||
194 | |||
175 | expr(p); | 195 | expr(p); |
176 | p.expect(T![']']); | 196 | p.expect(T![']']); |
177 | return m.complete(p, ARRAY_EXPR); | 197 | return m.complete(p, ARRAY_EXPR); |
@@ -181,6 +201,14 @@ fn array_expr(p: &mut Parser) -> CompletedMarker { | |||
181 | if p.at(T![']']) { | 201 | if p.at(T![']']) { |
182 | break; | 202 | break; |
183 | } | 203 | } |
204 | |||
205 | // test subsequent_array_member_attributes | ||
206 | // pub const A: &[i64] = &[ | ||
207 | // 1, | ||
208 | // #[cfg(test)] | ||
209 | // 2, | ||
210 | // ]; | ||
211 | attributes::outer_attributes(p); | ||
184 | if !p.at_ts(EXPR_FIRST) { | 212 | if !p.at_ts(EXPR_FIRST) { |
185 | p.error("expected expression"); | 213 | p.error("expected expression"); |
186 | break; | 214 | break; |
diff --git a/crates/ra_syntax/tests/data/parser/inline/err/0015_array_length_attributes.rs b/crates/ra_syntax/tests/data/parser/inline/err/0015_array_length_attributes.rs new file mode 100644 index 000000000..ba630981d --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/err/0015_array_length_attributes.rs | |||
@@ -0,0 +1,5 @@ | |||
1 | pub const A: &[i64] = &[ | ||
2 | #[cfg(test)] | ||
3 | 1; | ||
4 | 2, | ||
5 | ]; | ||
diff --git a/crates/ra_syntax/tests/data/parser/inline/err/0015_array_length_attributes.txt b/crates/ra_syntax/tests/data/parser/inline/err/0015_array_length_attributes.txt new file mode 100644 index 000000000..5f0e3f22c --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/err/0015_array_length_attributes.txt | |||
@@ -0,0 +1,60 @@ | |||
1 | SOURCE_FILE@[0; 53) | ||
2 | CONST_DEF@[0; 48) | ||
3 | VISIBILITY@[0; 3) | ||
4 | PUB_KW@[0; 3) "pub" | ||
5 | WHITESPACE@[3; 4) " " | ||
6 | CONST_KW@[4; 9) "const" | ||
7 | WHITESPACE@[9; 10) " " | ||
8 | NAME@[10; 11) | ||
9 | IDENT@[10; 11) "A" | ||
10 | COLON@[11; 12) ":" | ||
11 | WHITESPACE@[12; 13) " " | ||
12 | REFERENCE_TYPE@[13; 19) | ||
13 | AMP@[13; 14) "&" | ||
14 | SLICE_TYPE@[14; 19) | ||
15 | L_BRACK@[14; 15) "[" | ||
16 | PATH_TYPE@[15; 18) | ||
17 | PATH@[15; 18) | ||
18 | PATH_SEGMENT@[15; 18) | ||
19 | NAME_REF@[15; 18) | ||
20 | IDENT@[15; 18) "i64" | ||
21 | R_BRACK@[18; 19) "]" | ||
22 | WHITESPACE@[19; 20) " " | ||
23 | EQ@[20; 21) "=" | ||
24 | WHITESPACE@[21; 22) " " | ||
25 | REF_EXPR@[22; 48) | ||
26 | AMP@[22; 23) "&" | ||
27 | ARRAY_EXPR@[23; 48) | ||
28 | L_BRACK@[23; 24) "[" | ||
29 | WHITESPACE@[24; 27) "\n " | ||
30 | ATTR@[27; 39) | ||
31 | POUND@[27; 28) "#" | ||
32 | TOKEN_TREE@[28; 39) | ||
33 | L_BRACK@[28; 29) "[" | ||
34 | IDENT@[29; 32) "cfg" | ||
35 | TOKEN_TREE@[32; 38) | ||
36 | L_PAREN@[32; 33) "(" | ||
37 | IDENT@[33; 37) "test" | ||
38 | R_PAREN@[37; 38) ")" | ||
39 | R_BRACK@[38; 39) "]" | ||
40 | WHITESPACE@[39; 42) "\n " | ||
41 | LITERAL@[42; 43) | ||
42 | INT_NUMBER@[42; 43) "1" | ||
43 | SEMI@[43; 44) ";" | ||
44 | WHITESPACE@[44; 47) "\n " | ||
45 | LITERAL@[47; 48) | ||
46 | INT_NUMBER@[47; 48) "2" | ||
47 | ERROR@[48; 49) | ||
48 | COMMA@[48; 49) "," | ||
49 | WHITESPACE@[49; 50) "\n" | ||
50 | ERROR@[50; 51) | ||
51 | R_BRACK@[50; 51) "]" | ||
52 | ERROR@[51; 52) | ||
53 | SEMI@[51; 52) ";" | ||
54 | WHITESPACE@[52; 53) "\n" | ||
55 | error 44: removing an expression is not supported in this position | ||
56 | error 48: expected R_BRACK | ||
57 | error 48: expected SEMI | ||
58 | error 48: expected an item | ||
59 | error 50: expected an item | ||
60 | error 51: expected an item | ||
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0135_first_array_member_attributes.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0135_first_array_member_attributes.rs new file mode 100644 index 000000000..f59e13771 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0135_first_array_member_attributes.rs | |||
@@ -0,0 +1,5 @@ | |||
1 | pub const A: &[i64] = &[ | ||
2 | #[cfg(test)] | ||
3 | 1, | ||
4 | 2, | ||
5 | ]; | ||
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0135_first_array_member_attributes.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0135_first_array_member_attributes.txt new file mode 100644 index 000000000..eac4f6f30 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0135_first_array_member_attributes.txt | |||
@@ -0,0 +1,51 @@ | |||
1 | SOURCE_FILE@[0; 56) | ||
2 | CONST_DEF@[0; 55) | ||
3 | VISIBILITY@[0; 3) | ||
4 | PUB_KW@[0; 3) "pub" | ||
5 | WHITESPACE@[3; 4) " " | ||
6 | CONST_KW@[4; 9) "const" | ||
7 | WHITESPACE@[9; 10) " " | ||
8 | NAME@[10; 11) | ||
9 | IDENT@[10; 11) "A" | ||
10 | COLON@[11; 12) ":" | ||
11 | WHITESPACE@[12; 13) " " | ||
12 | REFERENCE_TYPE@[13; 19) | ||
13 | AMP@[13; 14) "&" | ||
14 | SLICE_TYPE@[14; 19) | ||
15 | L_BRACK@[14; 15) "[" | ||
16 | PATH_TYPE@[15; 18) | ||
17 | PATH@[15; 18) | ||
18 | PATH_SEGMENT@[15; 18) | ||
19 | NAME_REF@[15; 18) | ||
20 | IDENT@[15; 18) "i64" | ||
21 | R_BRACK@[18; 19) "]" | ||
22 | WHITESPACE@[19; 20) " " | ||
23 | EQ@[20; 21) "=" | ||
24 | WHITESPACE@[21; 22) " " | ||
25 | REF_EXPR@[22; 54) | ||
26 | AMP@[22; 23) "&" | ||
27 | ARRAY_EXPR@[23; 54) | ||
28 | L_BRACK@[23; 24) "[" | ||
29 | WHITESPACE@[24; 28) "\n " | ||
30 | ATTR@[28; 40) | ||
31 | POUND@[28; 29) "#" | ||
32 | TOKEN_TREE@[29; 40) | ||
33 | L_BRACK@[29; 30) "[" | ||
34 | IDENT@[30; 33) "cfg" | ||
35 | TOKEN_TREE@[33; 39) | ||
36 | L_PAREN@[33; 34) "(" | ||
37 | IDENT@[34; 38) "test" | ||
38 | R_PAREN@[38; 39) ")" | ||
39 | R_BRACK@[39; 40) "]" | ||
40 | WHITESPACE@[40; 44) "\n " | ||
41 | LITERAL@[44; 45) | ||
42 | INT_NUMBER@[44; 45) "1" | ||
43 | COMMA@[45; 46) "," | ||
44 | WHITESPACE@[46; 50) "\n " | ||
45 | LITERAL@[50; 51) | ||
46 | INT_NUMBER@[50; 51) "2" | ||
47 | COMMA@[51; 52) "," | ||
48 | WHITESPACE@[52; 53) "\n" | ||
49 | R_BRACK@[53; 54) "]" | ||
50 | SEMI@[54; 55) ";" | ||
51 | WHITESPACE@[55; 56) "\n" | ||
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0136_subsequent_array_member_attributes.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0136_subsequent_array_member_attributes.rs new file mode 100644 index 000000000..1324acb3f --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0136_subsequent_array_member_attributes.rs | |||
@@ -0,0 +1,5 @@ | |||
1 | pub const A: &[i64] = &[ | ||
2 | 1, | ||
3 | #[cfg(test)] | ||
4 | 2, | ||
5 | ]; | ||
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0136_subsequent_array_member_attributes.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0136_subsequent_array_member_attributes.txt new file mode 100644 index 000000000..6fa1b42d9 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0136_subsequent_array_member_attributes.txt | |||
@@ -0,0 +1,51 @@ | |||
1 | SOURCE_FILE@[0; 56) | ||
2 | CONST_DEF@[0; 55) | ||
3 | VISIBILITY@[0; 3) | ||
4 | PUB_KW@[0; 3) "pub" | ||
5 | WHITESPACE@[3; 4) " " | ||
6 | CONST_KW@[4; 9) "const" | ||
7 | WHITESPACE@[9; 10) " " | ||
8 | NAME@[10; 11) | ||
9 | IDENT@[10; 11) "A" | ||
10 | COLON@[11; 12) ":" | ||
11 | WHITESPACE@[12; 13) " " | ||
12 | REFERENCE_TYPE@[13; 19) | ||
13 | AMP@[13; 14) "&" | ||
14 | SLICE_TYPE@[14; 19) | ||
15 | L_BRACK@[14; 15) "[" | ||
16 | PATH_TYPE@[15; 18) | ||
17 | PATH@[15; 18) | ||
18 | PATH_SEGMENT@[15; 18) | ||
19 | NAME_REF@[15; 18) | ||
20 | IDENT@[15; 18) "i64" | ||
21 | R_BRACK@[18; 19) "]" | ||
22 | WHITESPACE@[19; 20) " " | ||
23 | EQ@[20; 21) "=" | ||
24 | WHITESPACE@[21; 22) " " | ||
25 | REF_EXPR@[22; 54) | ||
26 | AMP@[22; 23) "&" | ||
27 | ARRAY_EXPR@[23; 54) | ||
28 | L_BRACK@[23; 24) "[" | ||
29 | WHITESPACE@[24; 28) "\n " | ||
30 | LITERAL@[28; 29) | ||
31 | INT_NUMBER@[28; 29) "1" | ||
32 | COMMA@[29; 30) "," | ||
33 | WHITESPACE@[30; 34) "\n " | ||
34 | ATTR@[34; 46) | ||
35 | POUND@[34; 35) "#" | ||
36 | TOKEN_TREE@[35; 46) | ||
37 | L_BRACK@[35; 36) "[" | ||
38 | IDENT@[36; 39) "cfg" | ||
39 | TOKEN_TREE@[39; 45) | ||
40 | L_PAREN@[39; 40) "(" | ||
41 | IDENT@[40; 44) "test" | ||
42 | R_PAREN@[44; 45) ")" | ||
43 | R_BRACK@[45; 46) "]" | ||
44 | WHITESPACE@[46; 50) "\n " | ||
45 | LITERAL@[50; 51) | ||
46 | INT_NUMBER@[50; 51) "2" | ||
47 | COMMA@[51; 52) "," | ||
48 | WHITESPACE@[52; 53) "\n" | ||
49 | R_BRACK@[53; 54) "]" | ||
50 | SEMI@[54; 55) ";" | ||
51 | WHITESPACE@[55; 56) "\n" | ||