aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs72
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs13
-rw-r--r--crates/ra_syntax/src/grammar/patterns.rs8
-rw-r--r--crates/ra_syntax/src/parser_api.rs2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0069_match_arm.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt194
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.rs4
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.txt56
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs6
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt86
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0029_range_forms.rs5
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0029_range_forms.txt86
-rw-r--r--crates/ra_syntax/tests/test.rs47
13 files changed, 418 insertions, 162 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index a9449c7bf..4f8c46ab3 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -64,6 +64,20 @@ pub(crate) fn block(p: &mut Parser) {
64 if p.at(R_CURLY) { 64 if p.at(R_CURLY) {
65 m.abandon(p); 65 m.abandon(p);
66 } else { 66 } else {
67 // test no_semi_after_block
68 // fn foo() {
69 // if true {}
70 // loop {}
71 // match () {}
72 // while true {}
73 // for _ in () {}
74 // {}
75 // {}
76 // macro_rules! test {
77 // () => {}
78 // }
79 // test!{}
80 // }
67 if is_blocklike { 81 if is_blocklike {
68 p.eat(SEMI); 82 p.eat(SEMI);
69 } else { 83 } else {
@@ -143,7 +157,7 @@ fn current_op(p: &Parser) -> (u8, Op) {
143 157
144 let bp = match p.current() { 158 let bp = match p.current() {
145 EQ => 1, 159 EQ => 1,
146 DOTDOT => 2, 160 DOTDOT | DOTDOTEQ => 2,
147 EQEQ | NEQ | L_ANGLE | R_ANGLE => 5, 161 EQEQ | NEQ | L_ANGLE | R_ANGLE => 5,
148 PIPE => 6, 162 PIPE => 6,
149 CARET => 7, 163 CARET => 7,
@@ -158,13 +172,13 @@ fn current_op(p: &Parser) -> (u8, Op) {
158// Parses expression with binding power of at least bp. 172// Parses expression with binding power of at least bp.
159fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { 173fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
160 let mut lhs = match lhs(p, r) { 174 let mut lhs = match lhs(p, r) {
161 Some(lhs) => { 175 Some((lhs, blocklike)) => {
162 // test stmt_bin_expr_ambiguity 176 // test stmt_bin_expr_ambiguity
163 // fn foo() { 177 // fn foo() {
164 // let _ = {1} & 2; 178 // let _ = {1} & 2;
165 // {1} &2; 179 // {1} &2;
166 // } 180 // }
167 if r.prefer_stmt && is_block(lhs.kind()) { 181 if r.prefer_stmt && blocklike.is_block() {
168 return BlockLike::Block; 182 return BlockLike::Block;
169 } 183 }
170 lhs 184 lhs
@@ -173,7 +187,7 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
173 }; 187 };
174 188
175 loop { 189 loop {
176 let is_range = p.current() == DOTDOT; 190 let is_range = p.current() == DOTDOT || p.current() == DOTDOTEQ;
177 let (op_bp, op) = current_op(p); 191 let (op_bp, op) = current_op(p);
178 if op_bp < bp { 192 if op_bp < bp {
179 break; 193 break;
@@ -191,29 +205,12 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
191 BlockLike::NotBlock 205 BlockLike::NotBlock
192} 206}
193 207
194// test no_semi_after_block
195// fn foo() {
196// if true {}
197// loop {}
198// match () {}
199// while true {}
200// for _ in () {}
201// {}
202// {}
203// }
204fn is_block(kind: SyntaxKind) -> bool {
205 match kind {
206 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true,
207 _ => false,
208 }
209}
210
211const LHS_FIRST: TokenSet = token_set_union![ 208const LHS_FIRST: TokenSet = token_set_union![
212 token_set![AMP, STAR, EXCL, DOTDOT, MINUS], 209 token_set![AMP, STAR, EXCL, DOTDOT, MINUS],
213 atom::ATOM_EXPR_FIRST, 210 atom::ATOM_EXPR_FIRST,
214]; 211];
215 212
216fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { 213fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
217 let m; 214 let m;
218 let kind = match p.current() { 215 let kind = match p.current() {
219 // test ref_expr 216 // test ref_expr
@@ -246,19 +243,28 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> {
246 if p.at_ts(EXPR_FIRST) { 243 if p.at_ts(EXPR_FIRST) {
247 expr_bp(p, r, 2); 244 expr_bp(p, r, 2);
248 } 245 }
249 return Some(m.complete(p, RANGE_EXPR)); 246 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
250 } 247 }
251 _ => { 248 _ => {
252 let lhs = atom::atom_expr(p, r)?; 249 let (lhs, blocklike) = atom::atom_expr(p, r)?;
253 return Some(postfix_expr(p, r, lhs)); 250 return Some((
251 postfix_expr(p, lhs, !(r.prefer_stmt && blocklike.is_block())),
252 blocklike,
253 ));
254 } 254 }
255 }; 255 };
256 expr_bp(p, r, 255); 256 expr_bp(p, r, 255);
257 Some(m.complete(p, kind)) 257 Some((m.complete(p, kind), BlockLike::NotBlock))
258} 258}
259 259
260fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { 260fn postfix_expr(
261 let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); 261 p: &mut Parser,
262 mut lhs: CompletedMarker,
263 // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
264 // E.g. `while true {break}();` is parsed as
265 // `while true {break}; ();`
266 mut allow_calls: bool,
267) -> CompletedMarker {
262 loop { 268 loop {
263 lhs = match p.current() { 269 lhs = match p.current() {
264 // test stmt_postfix_expr_ambiguity 270 // test stmt_postfix_expr_ambiguity
@@ -406,20 +412,20 @@ fn arg_list(p: &mut Parser) {
406// let _ = ::a::<b>; 412// let _ = ::a::<b>;
407// let _ = format!(); 413// let _ = format!();
408// } 414// }
409fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { 415fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
410 assert!(paths::is_path_start(p) || p.at(L_ANGLE)); 416 assert!(paths::is_path_start(p) || p.at(L_ANGLE));
411 let m = p.start(); 417 let m = p.start();
412 paths::expr_path(p); 418 paths::expr_path(p);
413 match p.current() { 419 match p.current() {
414 L_CURLY if !r.forbid_structs => { 420 L_CURLY if !r.forbid_structs => {
415 named_field_list(p); 421 named_field_list(p);
416 m.complete(p, STRUCT_LIT) 422 (m.complete(p, STRUCT_LIT), BlockLike::Block)
417 } 423 }
418 EXCL => { 424 EXCL => {
419 items::macro_call_after_excl(p); 425 let block_like = items::macro_call_after_excl(p);
420 m.complete(p, MACRO_CALL) 426 return (m.complete(p, MACRO_CALL), block_like);
421 } 427 }
422 _ => m.complete(p, PATH_EXPR), 428 _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
423 } 429 }
424} 430}
425 431
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
index 04087fd60..cd7d62aff 100644
--- a/crates/ra_syntax/src/grammar/expressions/atom.rs
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -61,9 +61,9 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![
61 61
62const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; 62const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW];
63 63
64pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { 64pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
65 if let Some(m) = literal(p) { 65 if let Some(m) = literal(p) {
66 return Some(m); 66 return Some((m, BlockLike::NotBlock));
67 } 67 }
68 if paths::is_path_start(p) || p.at(L_ANGLE) { 68 if paths::is_path_start(p) || p.at(L_ANGLE) {
69 return Some(path_expr(p, r)); 69 return Some(path_expr(p, r));
@@ -114,7 +114,11 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMark
114 return None; 114 return None;
115 } 115 }
116 }; 116 };
117 Some(done) 117 let blocklike = match done.kind() {
118 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block,
119 _ => BlockLike::NotBlock,
120 };
121 Some((done, blocklike))
118} 122}
119 123
120// test tuple_expr 124// test tuple_expr
@@ -349,6 +353,7 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
349// fn foo() { 353// fn foo() {
350// match () { 354// match () {
351// _ => (), 355// _ => (),
356// _ if Test>{field: 0} => (),
352// X | Y if Z => (), 357// X | Y if Z => (),
353// | X | Y if Z => (), 358// | X | Y if Z => (),
354// | X => (), 359// | X => (),
@@ -362,7 +367,7 @@ fn match_arm(p: &mut Parser) -> BlockLike {
362 patterns::pattern(p); 367 patterns::pattern(p);
363 } 368 }
364 if p.eat(IF_KW) { 369 if p.eat(IF_KW) {
365 expr_no_struct(p); 370 expr(p);
366 } 371 }
367 p.expect(FAT_ARROW); 372 p.expect(FAT_ARROW);
368 let ret = expr_stmt(p); 373 let ret = expr_stmt(p);
diff --git a/crates/ra_syntax/src/grammar/patterns.rs b/crates/ra_syntax/src/grammar/patterns.rs
index 10fa0e0be..64cdf0b1b 100644
--- a/crates/ra_syntax/src/grammar/patterns.rs
+++ b/crates/ra_syntax/src/grammar/patterns.rs
@@ -14,9 +14,13 @@ pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
14 if let Some(lhs) = atom_pat(p, recovery_set) { 14 if let Some(lhs) = atom_pat(p, recovery_set) {
15 // test range_pat 15 // test range_pat
16 // fn main() { 16 // fn main() {
17 // match 92 { 0 ... 100 => () } 17 // match 92 {
18 // 0 ... 100 => (),
19 // 101 ..= 200 => (),
20 // 200 .. 301=> (),
21 // }
18 // } 22 // }
19 if p.at(DOTDOTDOT) { 23 if p.at(DOTDOTDOT) || p.at(DOTDOTEQ) || p.at(DOTDOT) {
20 let m = lhs.precede(p); 24 let m = lhs.precede(p);
21 p.bump(); 25 p.bump();
22 atom_pat(p, recovery_set); 26 atom_pat(p, recovery_set);
diff --git a/crates/ra_syntax/src/parser_api.rs b/crates/ra_syntax/src/parser_api.rs
index c37c30e34..02421def1 100644
--- a/crates/ra_syntax/src/parser_api.rs
+++ b/crates/ra_syntax/src/parser_api.rs
@@ -36,7 +36,7 @@ impl<'t> Parser<'t> {
36 self.current() == kind 36 self.current() == kind
37 } 37 }
38 38
39 /// Checks if the current token is `kind`. 39 /// Checks if the current token is in `kinds`.
40 pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool { 40 pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool {
41 kinds.contains(self.current()) 41 kinds.contains(self.current())
42 } 42 }
diff --git a/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.rs b/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.rs
index b23a12500..3380fa4ca 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.rs
@@ -1,6 +1,7 @@
1fn foo() { 1fn foo() {
2 match () { 2 match () {
3 _ => (), 3 _ => (),
4 _ if Test>{field: 0} => (),
4 X | Y if Z => (), 5 X | Y if Z => (),
5 | X | Y if Z => (), 6 | X | Y if Z => (),
6 | X => (), 7 | X => (),
diff --git a/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt b/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt
index 044faec04..e5647765c 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 125) 1SOURCE_FILE@[0; 161)
2 FN_DEF@[0; 124) 2 FN_DEF@[0; 160)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,18 +8,18 @@ SOURCE_FILE@[0; 125)
8 L_PAREN@[6; 7) 8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8) 9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9) 10 WHITESPACE@[8; 9)
11 BLOCK@[9; 124) 11 BLOCK@[9; 160)
12 L_CURLY@[9; 10) 12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 15) 13 WHITESPACE@[10; 15)
14 EXPR_STMT@[15; 122) 14 EXPR_STMT@[15; 158)
15 MATCH_EXPR@[15; 121) 15 MATCH_EXPR@[15; 157)
16 MATCH_KW@[15; 20) 16 MATCH_KW@[15; 20)
17 WHITESPACE@[20; 21) 17 WHITESPACE@[20; 21)
18 TUPLE_EXPR@[21; 23) 18 TUPLE_EXPR@[21; 23)
19 L_PAREN@[21; 22) 19 L_PAREN@[21; 22)
20 R_PAREN@[22; 23) 20 R_PAREN@[22; 23)
21 WHITESPACE@[23; 24) 21 WHITESPACE@[23; 24)
22 MATCH_ARM_LIST@[24; 121) 22 MATCH_ARM_LIST@[24; 157)
23 L_CURLY@[24; 25) 23 L_CURLY@[24; 25)
24 WHITESPACE@[25; 34) 24 WHITESPACE@[25; 34)
25 MATCH_ARM@[34; 41) 25 MATCH_ARM@[34; 41)
@@ -33,76 +33,116 @@ SOURCE_FILE@[0; 125)
33 R_PAREN@[40; 41) 33 R_PAREN@[40; 41)
34 COMMA@[41; 42) 34 COMMA@[41; 42)
35 WHITESPACE@[42; 51) 35 WHITESPACE@[42; 51)
36 MATCH_ARM@[51; 67) 36 MATCH_ARM@[51; 77)
37 BIND_PAT@[51; 52) 37 PLACEHOLDER_PAT@[51; 52)
38 NAME@[51; 52) 38 UNDERSCORE@[51; 52)
39 IDENT@[51; 52) "X"
40 WHITESPACE@[52; 53) 39 WHITESPACE@[52; 53)
41 PIPE@[53; 54) 40 IF_KW@[53; 55)
42 WHITESPACE@[54; 55) 41 WHITESPACE@[55; 56)
43 BIND_PAT@[55; 56) 42 BIN_EXPR@[56; 71)
44 NAME@[55; 56) 43 PATH_EXPR@[56; 60)
45 IDENT@[55; 56) "Y" 44 PATH@[56; 60)
46 WHITESPACE@[56; 57) 45 PATH_SEGMENT@[56; 60)
47 IF_KW@[57; 59) 46 NAME_REF@[56; 60)
48 WHITESPACE@[59; 60) 47 IDENT@[56; 60) "Test"
49 PATH_EXPR@[60; 61) 48 R_ANGLE@[60; 61)
50 PATH@[60; 61) 49 BLOCK_EXPR@[61; 71)
51 PATH_SEGMENT@[60; 61) 50 BLOCK@[61; 71)
52 NAME_REF@[60; 61) 51 L_CURLY@[61; 62)
53 IDENT@[60; 61) "Z" 52 EXPR_STMT@[62; 67)
54 WHITESPACE@[61; 62) 53 PATH_EXPR@[62; 67)
55 FAT_ARROW@[62; 64) 54 PATH@[62; 67)
56 WHITESPACE@[64; 65) 55 PATH_SEGMENT@[62; 67)
57 TUPLE_EXPR@[65; 67) 56 NAME_REF@[62; 67)
58 L_PAREN@[65; 66) 57 IDENT@[62; 67) "field"
59 R_PAREN@[66; 67) 58 err: `expected SEMI`
60 COMMA@[67; 68) 59 err: `expected expression`
61 WHITESPACE@[68; 77) 60 EXPR_STMT@[67; 68)
62 MATCH_ARM@[77; 95) 61 ERROR@[67; 68)
63 PIPE@[77; 78) 62 COLON@[67; 68)
64 WHITESPACE@[78; 79) 63 err: `expected SEMI`
65 BIND_PAT@[79; 80) 64 WHITESPACE@[68; 69)
66 NAME@[79; 80) 65 LITERAL@[69; 70)
67 IDENT@[79; 80) "X" 66 INT_NUMBER@[69; 70) "0"
68 WHITESPACE@[80; 81) 67 R_CURLY@[70; 71)
69 PIPE@[81; 82) 68 WHITESPACE@[71; 72)
70 WHITESPACE@[82; 83) 69 FAT_ARROW@[72; 74)
71 BIND_PAT@[83; 84) 70 WHITESPACE@[74; 75)
72 NAME@[83; 84) 71 TUPLE_EXPR@[75; 77)
73 IDENT@[83; 84) "Y" 72 L_PAREN@[75; 76)
74 WHITESPACE@[84; 85) 73 R_PAREN@[76; 77)
75 IF_KW@[85; 87) 74 COMMA@[77; 78)
76 WHITESPACE@[87; 88) 75 WHITESPACE@[78; 87)
77 PATH_EXPR@[88; 89) 76 MATCH_ARM@[87; 103)
78 PATH@[88; 89) 77 BIND_PAT@[87; 88)
79 PATH_SEGMENT@[88; 89) 78 NAME@[87; 88)
80 NAME_REF@[88; 89) 79 IDENT@[87; 88) "X"
81 IDENT@[88; 89) "Z" 80 WHITESPACE@[88; 89)
82 WHITESPACE@[89; 90) 81 PIPE@[89; 90)
83 FAT_ARROW@[90; 92) 82 WHITESPACE@[90; 91)
83 BIND_PAT@[91; 92)
84 NAME@[91; 92)
85 IDENT@[91; 92) "Y"
84 WHITESPACE@[92; 93) 86 WHITESPACE@[92; 93)
85 TUPLE_EXPR@[93; 95) 87 IF_KW@[93; 95)
86 L_PAREN@[93; 94) 88 WHITESPACE@[95; 96)
87 R_PAREN@[94; 95) 89 PATH_EXPR@[96; 97)
88 COMMA@[95; 96) 90 PATH@[96; 97)
89 WHITESPACE@[96; 105) 91 PATH_SEGMENT@[96; 97)
90 MATCH_ARM@[105; 114) 92 NAME_REF@[96; 97)
91 PIPE@[105; 106) 93 IDENT@[96; 97) "Z"
92 WHITESPACE@[106; 107) 94 WHITESPACE@[97; 98)
93 BIND_PAT@[107; 108) 95 FAT_ARROW@[98; 100)
94 NAME@[107; 108) 96 WHITESPACE@[100; 101)
95 IDENT@[107; 108) "X" 97 TUPLE_EXPR@[101; 103)
96 WHITESPACE@[108; 109) 98 L_PAREN@[101; 102)
97 FAT_ARROW@[109; 111) 99 R_PAREN@[102; 103)
98 WHITESPACE@[111; 112) 100 COMMA@[103; 104)
99 TUPLE_EXPR@[112; 114) 101 WHITESPACE@[104; 113)
100 L_PAREN@[112; 113) 102 MATCH_ARM@[113; 131)
101 R_PAREN@[113; 114) 103 PIPE@[113; 114)
102 COMMA@[114; 115) 104 WHITESPACE@[114; 115)
103 WHITESPACE@[115; 120) 105 BIND_PAT@[115; 116)
104 R_CURLY@[120; 121) 106 NAME@[115; 116)
105 SEMI@[121; 122) 107 IDENT@[115; 116) "X"
106 WHITESPACE@[122; 123) 108 WHITESPACE@[116; 117)
107 R_CURLY@[123; 124) 109 PIPE@[117; 118)
108 WHITESPACE@[124; 125) 110 WHITESPACE@[118; 119)
111 BIND_PAT@[119; 120)
112 NAME@[119; 120)
113 IDENT@[119; 120) "Y"
114 WHITESPACE@[120; 121)
115 IF_KW@[121; 123)
116 WHITESPACE@[123; 124)
117 PATH_EXPR@[124; 125)
118 PATH@[124; 125)
119 PATH_SEGMENT@[124; 125)
120 NAME_REF@[124; 125)
121 IDENT@[124; 125) "Z"
122 WHITESPACE@[125; 126)
123 FAT_ARROW@[126; 128)
124 WHITESPACE@[128; 129)
125 TUPLE_EXPR@[129; 131)
126 L_PAREN@[129; 130)
127 R_PAREN@[130; 131)
128 COMMA@[131; 132)
129 WHITESPACE@[132; 141)
130 MATCH_ARM@[141; 150)
131 PIPE@[141; 142)
132 WHITESPACE@[142; 143)
133 BIND_PAT@[143; 144)
134 NAME@[143; 144)
135 IDENT@[143; 144) "X"
136 WHITESPACE@[144; 145)
137 FAT_ARROW@[145; 147)
138 WHITESPACE@[147; 148)
139 TUPLE_EXPR@[148; 150)
140 L_PAREN@[148; 149)
141 R_PAREN@[149; 150)
142 COMMA@[150; 151)
143 WHITESPACE@[151; 156)
144 R_CURLY@[156; 157)
145 SEMI@[157; 158)
146 WHITESPACE@[158; 159)
147 R_CURLY@[159; 160)
148 WHITESPACE@[160; 161)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.rs b/crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.rs
index d769da43d..4919665cb 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.rs
@@ -6,4 +6,8 @@ fn foo() {
6 for _ in () {} 6 for _ in () {}
7 {} 7 {}
8 {} 8 {}
9 macro_rules! test {
10 () => {}
11 }
12 test!{}
9} 13}
diff --git a/crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.txt b/crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.txt
index 69f0a48ce..63b230091 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 107) 1SOURCE_FILE@[0; 167)
2 FN_DEF@[0; 106) 2 FN_DEF@[0; 166)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 107)
8 L_PAREN@[6; 7) 8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8) 9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9) 10 WHITESPACE@[8; 9)
11 BLOCK@[9; 106) 11 BLOCK@[9; 166)
12 L_CURLY@[9; 10) 12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 15) 13 WHITESPACE@[10; 15)
14 EXPR_STMT@[15; 25) 14 EXPR_STMT@[15; 25)
@@ -78,10 +78,46 @@ SOURCE_FILE@[0; 107)
78 L_CURLY@[95; 96) 78 L_CURLY@[95; 96)
79 R_CURLY@[96; 97) 79 R_CURLY@[96; 97)
80 WHITESPACE@[97; 102) 80 WHITESPACE@[97; 102)
81 BLOCK_EXPR@[102; 104) 81 EXPR_STMT@[102; 104)
82 BLOCK@[102; 104) 82 BLOCK_EXPR@[102; 104)
83 L_CURLY@[102; 103) 83 BLOCK@[102; 104)
84 R_CURLY@[103; 104) 84 L_CURLY@[102; 103)
85 WHITESPACE@[104; 105) 85 R_CURLY@[103; 104)
86 R_CURLY@[105; 106) 86 WHITESPACE@[104; 109)
87 WHITESPACE@[106; 107) 87 EXPR_STMT@[109; 152)
88 MACRO_CALL@[109; 152)
89 PATH@[109; 120)
90 PATH_SEGMENT@[109; 120)
91 NAME_REF@[109; 120)
92 IDENT@[109; 120) "macro_rules"
93 EXCL@[120; 121)
94 WHITESPACE@[121; 122)
95 IDENT@[122; 126) "test"
96 WHITESPACE@[126; 127)
97 TOKEN_TREE@[127; 152)
98 L_CURLY@[127; 128)
99 WHITESPACE@[128; 138)
100 TOKEN_TREE@[138; 140)
101 L_PAREN@[138; 139)
102 R_PAREN@[139; 140)
103 WHITESPACE@[140; 141)
104 FAT_ARROW@[141; 143)
105 WHITESPACE@[143; 144)
106 TOKEN_TREE@[144; 146)
107 L_CURLY@[144; 145)
108 R_CURLY@[145; 146)
109 WHITESPACE@[146; 151)
110 R_CURLY@[151; 152)
111 WHITESPACE@[152; 157)
112 MACRO_CALL@[157; 164)
113 PATH@[157; 161)
114 PATH_SEGMENT@[157; 161)
115 NAME_REF@[157; 161)
116 IDENT@[157; 161) "test"
117 EXCL@[161; 162)
118 TOKEN_TREE@[162; 164)
119 L_CURLY@[162; 163)
120 R_CURLY@[163; 164)
121 WHITESPACE@[164; 165)
122 R_CURLY@[165; 166)
123 WHITESPACE@[166; 167)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs
index 657467e75..c12ab6fce 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs
@@ -1,3 +1,7 @@
1fn main() { 1fn main() {
2 match 92 { 0 ... 100 => () } 2 match 92 {
3 0 ... 100 => (),
4 101 ..= 200 => (),
5 200 .. 301=> (),
6 }
3} 7}
diff --git a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt
index 12ccc1314..d47f38903 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 47) 1SOURCE_FILE@[0; 112)
2 FN_DEF@[0; 46) 2 FN_DEF@[0; 111)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
5 NAME@[3; 7) 5 NAME@[3; 7)
@@ -8,35 +8,69 @@ SOURCE_FILE@[0; 47)
8 L_PAREN@[7; 8) 8 L_PAREN@[7; 8)
9 R_PAREN@[8; 9) 9 R_PAREN@[8; 9)
10 WHITESPACE@[9; 10) 10 WHITESPACE@[9; 10)
11 BLOCK@[10; 46) 11 BLOCK@[10; 111)
12 L_CURLY@[10; 11) 12 L_CURLY@[10; 11)
13 WHITESPACE@[11; 16) 13 WHITESPACE@[11; 16)
14 MATCH_EXPR@[16; 44) 14 MATCH_EXPR@[16; 109)
15 MATCH_KW@[16; 21) 15 MATCH_KW@[16; 21)
16 WHITESPACE@[21; 22) 16 WHITESPACE@[21; 22)
17 LITERAL@[22; 24) 17 LITERAL@[22; 24)
18 INT_NUMBER@[22; 24) "92" 18 INT_NUMBER@[22; 24) "92"
19 WHITESPACE@[24; 25) 19 WHITESPACE@[24; 25)
20 MATCH_ARM_LIST@[25; 44) 20 MATCH_ARM_LIST@[25; 109)
21 L_CURLY@[25; 26) 21 L_CURLY@[25; 26)
22 WHITESPACE@[26; 27) 22 WHITESPACE@[26; 35)
23 MATCH_ARM@[27; 42) 23 MATCH_ARM@[35; 50)
24 RANGE_PAT@[27; 36) 24 RANGE_PAT@[35; 44)
25 LITERAL@[27; 28) 25 LITERAL@[35; 36)
26 INT_NUMBER@[27; 28) "0" 26 INT_NUMBER@[35; 36) "0"
27 WHITESPACE@[28; 29) 27 WHITESPACE@[36; 37)
28 DOTDOTDOT@[29; 32) 28 DOTDOTDOT@[37; 40)
29 WHITESPACE@[32; 33) 29 WHITESPACE@[40; 41)
30 LITERAL@[33; 36) 30 LITERAL@[41; 44)
31 INT_NUMBER@[33; 36) "100" 31 INT_NUMBER@[41; 44) "100"
32 WHITESPACE@[36; 37) 32 WHITESPACE@[44; 45)
33 FAT_ARROW@[37; 39) 33 FAT_ARROW@[45; 47)
34 WHITESPACE@[39; 40) 34 WHITESPACE@[47; 48)
35 TUPLE_EXPR@[40; 42) 35 TUPLE_EXPR@[48; 50)
36 L_PAREN@[40; 41) 36 L_PAREN@[48; 49)
37 R_PAREN@[41; 42) 37 R_PAREN@[49; 50)
38 WHITESPACE@[42; 43) 38 COMMA@[50; 51)
39 R_CURLY@[43; 44) 39 WHITESPACE@[51; 60)
40 WHITESPACE@[44; 45) 40 MATCH_ARM@[60; 77)
41 R_CURLY@[45; 46) 41 RANGE_PAT@[60; 71)
42 WHITESPACE@[46; 47) 42 LITERAL@[60; 63)
43 INT_NUMBER@[60; 63) "101"
44 WHITESPACE@[63; 64)
45 DOTDOTEQ@[64; 67)
46 WHITESPACE@[67; 68)
47 LITERAL@[68; 71)
48 INT_NUMBER@[68; 71) "200"
49 WHITESPACE@[71; 72)
50 FAT_ARROW@[72; 74)
51 WHITESPACE@[74; 75)
52 TUPLE_EXPR@[75; 77)
53 L_PAREN@[75; 76)
54 R_PAREN@[76; 77)
55 COMMA@[77; 78)
56 WHITESPACE@[78; 87)
57 MATCH_ARM@[87; 102)
58 RANGE_PAT@[87; 97)
59 LITERAL@[87; 90)
60 INT_NUMBER@[87; 90) "200"
61 WHITESPACE@[90; 91)
62 DOTDOT@[91; 93)
63 WHITESPACE@[93; 94)
64 LITERAL@[94; 97)
65 INT_NUMBER@[94; 97) "301"
66 FAT_ARROW@[97; 99)
67 WHITESPACE@[99; 100)
68 TUPLE_EXPR@[100; 102)
69 L_PAREN@[100; 101)
70 R_PAREN@[101; 102)
71 COMMA@[102; 103)
72 WHITESPACE@[103; 108)
73 R_CURLY@[108; 109)
74 WHITESPACE@[109; 110)
75 R_CURLY@[110; 111)
76 WHITESPACE@[111; 112)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0029_range_forms.rs b/crates/ra_syntax/tests/data/parser/ok/0029_range_forms.rs
index 03f4ae7b2..f9ff444d4 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0029_range_forms.rs
+++ b/crates/ra_syntax/tests/data/parser/ok/0029_range_forms.rs
@@ -3,4 +3,9 @@ fn foo() {
3 ..z = 2; 3 ..z = 2;
4 x = false..1 == 1; 4 x = false..1 == 1;
5 let x = 1..; 5 let x = 1..;
6
7 ..=1 + 1;
8 ..=z = 2;
9 x = false..=1 == 1;
10 let x = 1..;
6} 11}
diff --git a/crates/ra_syntax/tests/data/parser/ok/0029_range_forms.txt b/crates/ra_syntax/tests/data/parser/ok/0029_range_forms.txt
index 2e7703c21..e3706bfbd 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0029_range_forms.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0029_range_forms.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 79) 1SOURCE_FILE@[0; 153)
2 FN_DEF@[0; 78) 2 FN_DEF@[0; 152)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 79)
8 L_PAREN@[6; 7) 8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8) 9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9) 10 WHITESPACE@[8; 9)
11 BLOCK@[9; 78) 11 BLOCK@[9; 152)
12 L_CURLY@[9; 10) 12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 15) 13 WHITESPACE@[10; 15)
14 EXPR_STMT@[15; 23) 14 EXPR_STMT@[15; 23)
@@ -78,6 +78,80 @@ SOURCE_FILE@[0; 79)
78 INT_NUMBER@[72; 73) "1" 78 INT_NUMBER@[72; 73) "1"
79 DOTDOT@[73; 75) 79 DOTDOT@[73; 75)
80 SEMI@[75; 76) 80 SEMI@[75; 76)
81 WHITESPACE@[76; 77) 81 WHITESPACE@[76; 86)
82 R_CURLY@[77; 78) 82 err: `expected expression`
83 WHITESPACE@[78; 79) 83 EXPR_STMT@[86; 89)
84 ERROR@[86; 89)
85 DOTDOTEQ@[86; 89)
86 err: `expected SEMI`
87 EXPR_STMT@[89; 95)
88 BIN_EXPR@[89; 94)
89 LITERAL@[89; 90)
90 INT_NUMBER@[89; 90) "1"
91 WHITESPACE@[90; 91)
92 PLUS@[91; 92)
93 WHITESPACE@[92; 93)
94 LITERAL@[93; 94)
95 INT_NUMBER@[93; 94) "1"
96 SEMI@[94; 95)
97 WHITESPACE@[95; 100)
98 err: `expected expression`
99 EXPR_STMT@[100; 103)
100 ERROR@[100; 103)
101 DOTDOTEQ@[100; 103)
102 err: `expected SEMI`
103 EXPR_STMT@[103; 109)
104 BIN_EXPR@[103; 108)
105 PATH_EXPR@[103; 104)
106 PATH@[103; 104)
107 PATH_SEGMENT@[103; 104)
108 NAME_REF@[103; 104)
109 IDENT@[103; 104) "z"
110 WHITESPACE@[104; 105)
111 EQ@[105; 106)
112 WHITESPACE@[106; 107)
113 LITERAL@[107; 108)
114 INT_NUMBER@[107; 108) "2"
115 SEMI@[108; 109)
116 WHITESPACE@[109; 114)
117 EXPR_STMT@[114; 133)
118 BIN_EXPR@[114; 132)
119 PATH_EXPR@[114; 115)
120 PATH@[114; 115)
121 PATH_SEGMENT@[114; 115)
122 NAME_REF@[114; 115)
123 IDENT@[114; 115) "x"
124 WHITESPACE@[115; 116)
125 EQ@[116; 117)
126 WHITESPACE@[117; 118)
127 RANGE_EXPR@[118; 132)
128 LITERAL@[118; 123)
129 FALSE_KW@[118; 123)
130 DOTDOTEQ@[123; 126)
131 BIN_EXPR@[126; 132)
132 LITERAL@[126; 127)
133 INT_NUMBER@[126; 127) "1"
134 WHITESPACE@[127; 128)
135 EQEQ@[128; 130)
136 WHITESPACE@[130; 131)
137 LITERAL@[131; 132)
138 INT_NUMBER@[131; 132) "1"
139 SEMI@[132; 133)
140 WHITESPACE@[133; 138)
141 LET_STMT@[138; 150)
142 LET_KW@[138; 141)
143 WHITESPACE@[141; 142)
144 BIND_PAT@[142; 143)
145 NAME@[142; 143)
146 IDENT@[142; 143) "x"
147 WHITESPACE@[143; 144)
148 EQ@[144; 145)
149 WHITESPACE@[145; 146)
150 RANGE_EXPR@[146; 149)
151 LITERAL@[146; 147)
152 INT_NUMBER@[146; 147) "1"
153 DOTDOT@[147; 149)
154 SEMI@[149; 150)
155 WHITESPACE@[150; 151)
156 R_CURLY@[151; 152)
157 WHITESPACE@[152; 153)
diff --git a/crates/ra_syntax/tests/test.rs b/crates/ra_syntax/tests/test.rs
index 67acc9020..c17b6ffa6 100644
--- a/crates/ra_syntax/tests/test.rs
+++ b/crates/ra_syntax/tests/test.rs
@@ -6,7 +6,7 @@ extern crate walkdir;
6use std::{ 6use std::{
7 fmt::Write, 7 fmt::Write,
8 fs, 8 fs,
9 path::{Path, PathBuf}, 9 path::{Path, PathBuf, Component},
10}; 10};
11 11
12use ra_syntax::{ 12use ra_syntax::{
@@ -37,6 +37,47 @@ fn parser_fuzz_tests() {
37 } 37 }
38} 38}
39 39
40/// Test that Rust-analyzer can parse and validate the rust-analyser
41/// TODO: Use this as a benchmark
42#[test]
43fn self_hosting_parsing() {
44 use std::ffi::OsStr;
45 let empty_vec = vec![];
46 let dir = project_dir().join("crates");
47 let mut count = 0;
48 for entry in walkdir::WalkDir::new(dir)
49 .into_iter()
50 .filter_entry(|entry| {
51 !entry
52 .path()
53 .components()
54 // TODO: this more neatly
55 .any(|component| {
56 // Get all files which are not in the crates/ra_syntax/tests/data folder
57 component == Component::Normal(OsStr::new("data"))
58 })
59 })
60 .map(|e| e.unwrap())
61 .filter(|entry| {
62 // Get all `.rs ` files
63 !entry.path().is_dir() && (entry.path().extension() == Some(OsStr::new("rs")))
64 })
65 {
66 count += 1;
67 let text = read_text(entry.path());
68 let node = SourceFileNode::parse(&text);
69 let errors = node.errors();
70 assert_eq!(
71 errors, empty_vec,
72 "There should be no errors in the file {:?}",
73 entry
74 );
75 }
76 assert!(
77 count > 30,
78 "self_hosting_parsing found too few files - is it running in the right directory?"
79 )
80}
40/// Read file and normalize newlines. 81/// Read file and normalize newlines.
41/// 82///
42/// `rustc` seems to always normalize `\r\n` newlines to `\n`: 83/// `rustc` seems to always normalize `\r\n` newlines to `\n`:
@@ -49,7 +90,9 @@ fn parser_fuzz_tests() {
49/// 90///
50/// so this should always be correct. 91/// so this should always be correct.
51fn read_text(path: &Path) -> String { 92fn read_text(path: &Path) -> String {
52 fs::read_to_string(path).unwrap().replace("\r\n", "\n") 93 fs::read_to_string(path)
94 .expect(&format!("File at {:?} should be valid", path))
95 .replace("\r\n", "\n")
53} 96}
54 97
55pub fn dir_tests<F>(paths: &[&str], f: F) 98pub fn dir_tests<F>(paths: &[&str], f: F)