diff options
-rw-r--r-- | crates/ra_parser/src/grammar.rs | 14 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 10 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/items.rs | 2 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/paths.rs | 2 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/type_args.rs | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 25 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation/field_expr.rs | 13 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.txt | 7 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.txt | 6 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.txt | 6 |
10 files changed, 52 insertions, 37 deletions
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index 2ee121ccd..beedac457 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -273,8 +273,8 @@ fn name(p: &mut Parser) { | |||
273 | name_r(p, TokenSet::empty()) | 273 | name_r(p, TokenSet::empty()) |
274 | } | 274 | } |
275 | 275 | ||
276 | fn name_ref(p: &mut Parser, allow_numeric_names: bool) { | 276 | fn name_ref(p: &mut Parser) { |
277 | if p.at(IDENT) || (allow_numeric_names && p.at(INT_NUMBER)) { | 277 | if p.at(IDENT) { |
278 | let m = p.start(); | 278 | let m = p.start(); |
279 | p.bump(); | 279 | p.bump(); |
280 | m.complete(p, NAME_REF); | 280 | m.complete(p, NAME_REF); |
@@ -287,6 +287,16 @@ fn name_ref(p: &mut Parser, allow_numeric_names: bool) { | |||
287 | } | 287 | } |
288 | } | 288 | } |
289 | 289 | ||
290 | fn name_ref_or_index(p: &mut Parser) { | ||
291 | if p.at(IDENT) || p.at(INT_NUMBER) { | ||
292 | let m = p.start(); | ||
293 | p.bump(); | ||
294 | m.complete(p, NAME_REF); | ||
295 | } else { | ||
296 | p.err_and_bump("expected identifier"); | ||
297 | } | ||
298 | } | ||
299 | |||
290 | fn error_block(p: &mut Parser, message: &str) { | 300 | fn error_block(p: &mut Parser, message: &str) { |
291 | assert!(p.at(T!['{'])); | 301 | assert!(p.at(T!['{'])); |
292 | let m = p.start(); | 302 | let m = p.start(); |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 9f9e9cb0e..9fd3a235d 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -458,7 +458,7 @@ fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
458 | assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::])); | 458 | assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::])); |
459 | let m = lhs.precede(p); | 459 | let m = lhs.precede(p); |
460 | p.bump(); | 460 | p.bump(); |
461 | name_ref(p, false); | 461 | name_ref(p); |
462 | type_args::opt_type_arg_list(p, true); | 462 | type_args::opt_type_arg_list(p, true); |
463 | if p.at(T!['(']) { | 463 | if p.at(T!['(']) { |
464 | arg_list(p); | 464 | arg_list(p); |
@@ -484,10 +484,8 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
484 | assert!(p.at(T![.])); | 484 | assert!(p.at(T![.])); |
485 | let m = lhs.precede(p); | 485 | let m = lhs.precede(p); |
486 | p.bump(); | 486 | p.bump(); |
487 | if p.at(IDENT) { | 487 | if p.at(IDENT) || p.at(INT_NUMBER) { |
488 | name_ref(p, false) | 488 | name_ref_or_index(p) |
489 | } else if p.at(INT_NUMBER) { | ||
490 | p.bump(); | ||
491 | } else if p.at(FLOAT_NUMBER) { | 489 | } else if p.at(FLOAT_NUMBER) { |
492 | // FIXME: How to recover and instead parse INT + T![.]? | 490 | // FIXME: How to recover and instead parse INT + T![.]? |
493 | p.bump(); | 491 | p.bump(); |
@@ -587,7 +585,7 @@ pub(crate) fn named_field_list(p: &mut Parser) { | |||
587 | IDENT | INT_NUMBER | T![#] => { | 585 | IDENT | INT_NUMBER | T![#] => { |
588 | let m = p.start(); | 586 | let m = p.start(); |
589 | attributes::outer_attributes(p); | 587 | attributes::outer_attributes(p); |
590 | name_ref(p, true); | 588 | name_ref_or_index(p); |
591 | if p.eat(T![:]) { | 589 | if p.eat(T![:]) { |
592 | expr(p); | 590 | expr(p); |
593 | } | 591 | } |
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index b0081f396..543af7c4b 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs | |||
@@ -279,7 +279,7 @@ fn extern_crate_item(p: &mut Parser, m: Marker) { | |||
279 | p.bump(); | 279 | p.bump(); |
280 | assert!(p.at(T![crate])); | 280 | assert!(p.at(T![crate])); |
281 | p.bump(); | 281 | p.bump(); |
282 | name_ref(p, false); | 282 | name_ref(p); |
283 | opt_alias(p); | 283 | opt_alias(p); |
284 | p.expect(T![;]); | 284 | p.expect(T![;]); |
285 | m.complete(p, EXTERN_CRATE_ITEM); | 285 | m.complete(p, EXTERN_CRATE_ITEM); |
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs index 2c8f0f7e8..3537b0da1 100644 --- a/crates/ra_parser/src/grammar/paths.rs +++ b/crates/ra_parser/src/grammar/paths.rs | |||
@@ -71,7 +71,7 @@ fn path_segment(p: &mut Parser, mode: Mode, first: bool) { | |||
71 | } | 71 | } |
72 | match p.current() { | 72 | match p.current() { |
73 | IDENT => { | 73 | IDENT => { |
74 | name_ref(p, false); | 74 | name_ref(p); |
75 | opt_path_type_args(p, mode); | 75 | opt_path_type_args(p, mode); |
76 | } | 76 | } |
77 | // test crate_path | 77 | // test crate_path |
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs index f1d999dea..3db08b280 100644 --- a/crates/ra_parser/src/grammar/type_args.rs +++ b/crates/ra_parser/src/grammar/type_args.rs | |||
@@ -38,12 +38,12 @@ fn type_arg(p: &mut Parser) { | |||
38 | // test associated_type_bounds | 38 | // test associated_type_bounds |
39 | // fn print_all<T: Iterator<Item: Display>>(printables: T) {} | 39 | // fn print_all<T: Iterator<Item: Display>>(printables: T) {} |
40 | IDENT if p.nth(1) == T![:] => { | 40 | IDENT if p.nth(1) == T![:] => { |
41 | name_ref(p, false); | 41 | name_ref(p); |
42 | type_params::bounds(p); | 42 | type_params::bounds(p); |
43 | m.complete(p, ASSOC_TYPE_ARG); | 43 | m.complete(p, ASSOC_TYPE_ARG); |
44 | } | 44 | } |
45 | IDENT if p.nth(1) == T![=] => { | 45 | IDENT if p.nth(1) == T![=] => { |
46 | name_ref(p, false); | 46 | name_ref(p); |
47 | p.bump(); | 47 | p.bump(); |
48 | types::type_(p); | 48 | types::type_(p); |
49 | m.complete(p, ASSOC_TYPE_ARG); | 49 | m.complete(p, ASSOC_TYPE_ARG); |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 1f904434e..2bb3c0a03 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -1,13 +1,12 @@ | |||
1 | mod block; | 1 | mod block; |
2 | mod field_expr; | ||
3 | 2 | ||
4 | use ra_rustc_lexer::unescape; | 3 | use ra_rustc_lexer::unescape; |
5 | 4 | ||
6 | use crate::{ | 5 | use crate::{ |
7 | algo::visit::{visitor_ctx, VisitorCtx}, | 6 | algo::visit::{visitor_ctx, VisitorCtx}, |
8 | ast, SyntaxError, SyntaxErrorKind, | 7 | ast, AstNode, SyntaxError, SyntaxErrorKind, |
9 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, STRING}, | 8 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, INT_NUMBER, STRING}, |
10 | SyntaxNode, TextUnit, T, | 9 | SyntaxNode, SyntaxToken, TextUnit, T, |
11 | }; | 10 | }; |
12 | 11 | ||
13 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | 12 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
@@ -101,7 +100,8 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | |||
101 | let _ = visitor_ctx(&mut errors) | 100 | let _ = visitor_ctx(&mut errors) |
102 | .visit::<ast::Literal, _>(validate_literal) | 101 | .visit::<ast::Literal, _>(validate_literal) |
103 | .visit::<ast::Block, _>(block::validate_block_node) | 102 | .visit::<ast::Block, _>(block::validate_block_node) |
104 | .visit::<ast::FieldExpr, _>(field_expr::validate_field_expr_node) | 103 | .visit::<ast::FieldExpr, _>(|it, errors| validate_numeric_name(it.name_ref(), errors)) |
104 | .visit::<ast::NamedField, _>(|it, errors| validate_numeric_name(it.name_ref(), errors)) | ||
105 | .accept(&node); | 105 | .accept(&node); |
106 | } | 106 | } |
107 | errors | 107 | errors |
@@ -189,3 +189,18 @@ pub(crate) fn validate_block_structure(root: &SyntaxNode) { | |||
189 | } | 189 | } |
190 | } | 190 | } |
191 | } | 191 | } |
192 | |||
193 | fn validate_numeric_name(name_ref: Option<ast::NameRef>, errors: &mut Vec<SyntaxError>) { | ||
194 | if let Some(int_token) = int_token(name_ref) { | ||
195 | if int_token.text().chars().any(|c| !c.is_digit(10)) { | ||
196 | errors.push(SyntaxError::new( | ||
197 | SyntaxErrorKind::InvalidTupleIndexFormat, | ||
198 | int_token.text_range(), | ||
199 | )); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | fn int_token(name_ref: Option<ast::NameRef>) -> Option<SyntaxToken> { | ||
204 | name_ref?.syntax().first_child_or_token()?.into_token().filter(|it| it.kind() == INT_NUMBER) | ||
205 | } | ||
206 | } | ||
diff --git a/crates/ra_syntax/src/validation/field_expr.rs b/crates/ra_syntax/src/validation/field_expr.rs deleted file mode 100644 index 004f199fd..000000000 --- a/crates/ra_syntax/src/validation/field_expr.rs +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | use crate::{ | ||
2 | ast::{self, FieldKind}, | ||
3 | SyntaxError, | ||
4 | SyntaxErrorKind::*, | ||
5 | }; | ||
6 | |||
7 | pub(crate) fn validate_field_expr_node(node: ast::FieldExpr, errors: &mut Vec<SyntaxError>) { | ||
8 | if let Some(FieldKind::Index(idx)) = node.field_access() { | ||
9 | if idx.text().chars().any(|c| c < '0' || c > '9') { | ||
10 | errors.push(SyntaxError::new(InvalidTupleIndexFormat, idx.text_range())); | ||
11 | } | ||
12 | } | ||
13 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.txt b/crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.txt index a21b29c80..465e79e7b 100644 --- a/crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.txt +++ b/crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.txt | |||
@@ -30,7 +30,8 @@ SOURCE_FILE@[0; 47) | |||
30 | NAME_REF@[25; 26) | 30 | NAME_REF@[25; 26) |
31 | IDENT@[25; 26) "x" | 31 | IDENT@[25; 26) "x" |
32 | DOT@[26; 27) "." | 32 | DOT@[26; 27) "." |
33 | INT_NUMBER@[27; 31) "1i32" | 33 | NAME_REF@[27; 31) |
34 | INT_NUMBER@[27; 31) "1i32" | ||
34 | SEMI@[31; 32) ";" | 35 | SEMI@[31; 32) ";" |
35 | WHITESPACE@[32; 37) "\n " | 36 | WHITESPACE@[32; 37) "\n " |
36 | EXPR_STMT@[37; 44) | 37 | EXPR_STMT@[37; 44) |
@@ -41,11 +42,11 @@ SOURCE_FILE@[0; 47) | |||
41 | NAME_REF@[37; 38) | 42 | NAME_REF@[37; 38) |
42 | IDENT@[37; 38) "x" | 43 | IDENT@[37; 38) "x" |
43 | DOT@[38; 39) "." | 44 | DOT@[38; 39) "." |
44 | INT_NUMBER@[39; 43) "0x01" | 45 | NAME_REF@[39; 43) |
46 | INT_NUMBER@[39; 43) "0x01" | ||
45 | SEMI@[43; 44) ";" | 47 | SEMI@[43; 44) ";" |
46 | WHITESPACE@[44; 45) "\n" | 48 | WHITESPACE@[44; 45) "\n" |
47 | R_CURLY@[45; 46) "}" | 49 | R_CURLY@[45; 46) "}" |
48 | WHITESPACE@[46; 47) "\n" | 50 | WHITESPACE@[46; 47) "\n" |
49 | error [17; 19): Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix | ||
50 | error [27; 31): Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix | 51 | error [27; 31): Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix |
51 | error [39; 43): Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix | 52 | error [39; 43): Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.txt index 78054ec5a..1d2cf2761 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.txt | |||
@@ -32,7 +32,8 @@ SOURCE_FILE@[0; 48) | |||
32 | NAME_REF@[26; 27) | 32 | NAME_REF@[26; 27) |
33 | IDENT@[26; 27) "x" | 33 | IDENT@[26; 27) "x" |
34 | DOT@[27; 28) "." | 34 | DOT@[27; 28) "." |
35 | INT_NUMBER@[28; 29) "0" | 35 | NAME_REF@[28; 29) |
36 | INT_NUMBER@[28; 29) "0" | ||
36 | DOT@[29; 30) "." | 37 | DOT@[29; 30) "." |
37 | NAME_REF@[30; 33) | 38 | NAME_REF@[30; 33) |
38 | IDENT@[30; 33) "bar" | 39 | IDENT@[30; 33) "bar" |
@@ -47,7 +48,8 @@ SOURCE_FILE@[0; 48) | |||
47 | NAME_REF@[39; 40) | 48 | NAME_REF@[39; 40) |
48 | IDENT@[39; 40) "x" | 49 | IDENT@[39; 40) "x" |
49 | DOT@[40; 41) "." | 50 | DOT@[40; 41) "." |
50 | INT_NUMBER@[41; 42) "0" | 51 | NAME_REF@[41; 42) |
52 | INT_NUMBER@[41; 42) "0" | ||
51 | ARG_LIST@[42; 44) | 53 | ARG_LIST@[42; 44) |
52 | L_PAREN@[42; 43) "(" | 54 | L_PAREN@[42; 43) "(" |
53 | R_PAREN@[43; 44) ")" | 55 | R_PAREN@[43; 44) ")" |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.txt index 99bd76ace..7adb662de 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.txt | |||
@@ -31,7 +31,8 @@ SOURCE_FILE@[0; 67) | |||
31 | NAME_REF@[28; 29) | 31 | NAME_REF@[28; 29) |
32 | IDENT@[28; 29) "x" | 32 | IDENT@[28; 29) "x" |
33 | DOT@[29; 30) "." | 33 | DOT@[29; 30) "." |
34 | INT_NUMBER@[30; 31) "0" | 34 | NAME_REF@[30; 31) |
35 | INT_NUMBER@[30; 31) "0" | ||
35 | DOT@[31; 32) "." | 36 | DOT@[31; 32) "." |
36 | AWAIT_KW@[32; 37) "await" | 37 | AWAIT_KW@[32; 37) "await" |
37 | SEMI@[37; 38) ";" | 38 | SEMI@[37; 38) ";" |
@@ -48,7 +49,8 @@ SOURCE_FILE@[0; 67) | |||
48 | NAME_REF@[43; 44) | 49 | NAME_REF@[43; 44) |
49 | IDENT@[43; 44) "x" | 50 | IDENT@[43; 44) "x" |
50 | DOT@[44; 45) "." | 51 | DOT@[44; 45) "." |
51 | INT_NUMBER@[45; 46) "0" | 52 | NAME_REF@[45; 46) |
53 | INT_NUMBER@[45; 46) "0" | ||
52 | ARG_LIST@[46; 48) | 54 | ARG_LIST@[46; 48) |
53 | L_PAREN@[46; 47) "(" | 55 | L_PAREN@[46; 47) "(" |
54 | R_PAREN@[47; 48) ")" | 56 | R_PAREN@[47; 48) ")" |