aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-03-18 09:32:28 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-03-18 09:32:28 +0000
commit1cd18f9237b6ac48ca8461307f2a4eaf273ee394 (patch)
tree7971e3753c74b98e0e5b4120adb8706a86d99e3e
parent7c117567ab55046a9303fc7a6676a50008ad4f33 (diff)
parent76075c74103b3204ebc1bde54a330629d9e00811 (diff)
Merge #991
991: Use Marker argument for item parsers r=matklad a=pcpthm Before doing this for expressions, I found that the pattern (Marker argument) should be applied to the item parsers because visiblity and modifiers are parsed in a separate function. Fixed some parser bugs: - Fix pub_expr: `pub 42;` was allowed. - Fix incorrect parsing of crate::path: incorrectly parsed as `crate` as a visibility. Co-authored-by: pcpthm <[email protected]>
-rw-r--r--crates/ra_parser/src/grammar.rs12
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs2
-rw-r--r--crates/ra_parser/src/grammar/items.rs93
-rw-r--r--crates/ra_parser/src/grammar/items/consts.rs11
-rw-r--r--crates/ra_parser/src/grammar/items/nominal.rs11
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs3
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0003_C++_semicolon.txt6
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0008_pub_expr.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0008_pub_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.txt)10
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.rs2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.txt46
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0125_crate_keyword_path.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0125_crate_keyword_path.txt31
14 files changed, 149 insertions, 81 deletions
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index c9941fe93..e428faffb 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -86,7 +86,7 @@ impl BlockLike {
86 } 86 }
87} 87}
88 88
89fn opt_visibility(p: &mut Parser) { 89fn opt_visibility(p: &mut Parser) -> bool {
90 match p.current() { 90 match p.current() {
91 PUB_KW => { 91 PUB_KW => {
92 let m = p.start(); 92 let m = p.start();
@@ -116,13 +116,19 @@ fn opt_visibility(p: &mut Parser) {
116 } 116 }
117 // test crate_keyword_vis 117 // test crate_keyword_vis
118 // crate fn main() { } 118 // crate fn main() { }
119 CRATE_KW => { 119 // struct S { crate field: u32 }
120 // struct T(crate u32);
121 //
122 // test crate_keyword_path
123 // fn foo() { crate::foo(); }
124 CRATE_KW if p.nth(1) != COLONCOLON => {
120 let m = p.start(); 125 let m = p.start();
121 p.bump(); 126 p.bump();
122 m.complete(p, VISIBILITY); 127 m.complete(p, VISIBILITY);
123 } 128 }
124 _ => (), 129 _ => return false,
125 } 130 }
131 true
126} 132}
127 133
128fn opt_alias(p: &mut Parser) { 134fn opt_alias(p: &mut Parser) {
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index ccbc905ab..83812e938 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -67,8 +67,6 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
67 Err(m) => m, 67 Err(m) => m,
68 }; 68 };
69 69
70 // test pub_expr
71 // fn foo() { pub 92; } //FIXME
72 if has_attrs { 70 if has_attrs {
73 m.abandon(p); 71 m.abandon(p);
74 p.error("expected a let statement or an item after attributes in block"); 72 p.error("expected a let statement or an item after attributes in block");
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 94b93a02b..c24e6d1e0 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -67,11 +67,14 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF
67} 67}
68 68
69pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> { 69pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> {
70 opt_visibility(p); 70 // test_err pub_expr
71 if let Some(kind) = items_without_modifiers(p) { 71 // fn foo() { pub 92; }
72 m.complete(p, kind); 72 let has_visibility = opt_visibility(p);
73 return Ok(()); 73
74 } 74 let m = match items_without_modifiers(p, m) {
75 Ok(()) => return Ok(()),
76 Err(m) => m,
77 };
75 78
76 let mut has_mods = false; 79 let mut has_mods = false;
77 80
@@ -152,10 +155,14 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
152 m.complete(p, IMPL_BLOCK); 155 m.complete(p, IMPL_BLOCK);
153 } 156 }
154 _ => { 157 _ => {
155 if !has_mods { 158 if !has_visibility && !has_mods {
156 return Err(m); 159 return Err(m);
157 } else { 160 } else {
158 p.error("expected fn, trait or impl"); 161 if has_mods {
162 p.error("expected fn, trait or impl");
163 } else {
164 p.error("expected an item");
165 }
159 m.complete(p, ERROR); 166 m.complete(p, ERROR);
160 } 167 }
161 } 168 }
@@ -163,23 +170,14 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
163 Ok(()) 170 Ok(())
164} 171}
165 172
166fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { 173fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
167 let la = p.nth(1); 174 let la = p.nth(1);
168 let kind = match p.current() { 175 match p.current() {
169 // test extern_crate 176 // test extern_crate
170 // extern crate foo; 177 // extern crate foo;
171 EXTERN_KW if la == CRATE_KW => { 178 EXTERN_KW if la == CRATE_KW => extern_crate_item(p, m),
172 extern_crate_item(p); 179 TYPE_KW => type_def(p, m),
173 EXTERN_CRATE_ITEM 180 MOD_KW => mod_item(p, m),
174 }
175 TYPE_KW => {
176 type_def(p);
177 TYPE_ALIAS_DEF
178 }
179 MOD_KW => {
180 mod_item(p);
181 MODULE
182 }
183 STRUCT_KW => { 181 STRUCT_KW => {
184 // test struct_items 182 // test struct_items
185 // struct Foo; 183 // struct Foo;
@@ -190,14 +188,7 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
190 // a: i32, 188 // a: i32,
191 // b: f32, 189 // b: f32,
192 // } 190 // }
193 nominal::struct_def(p, STRUCT_KW); 191 nominal::struct_def(p, m, STRUCT_KW);
194 if p.at(SEMI) {
195 p.err_and_bump(
196 "expected item, found `;`\n\
197 consider removing this semicolon",
198 );
199 }
200 STRUCT_DEF
201 } 192 }
202 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { 193 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
203 // test union_items 194 // test union_items
@@ -206,25 +197,12 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
206 // a: i32, 197 // a: i32,
207 // b: f32, 198 // b: f32,
208 // } 199 // }
209 nominal::struct_def(p, UNION_KW); 200 nominal::struct_def(p, m, UNION_KW);
210 STRUCT_DEF
211 }
212 ENUM_KW => {
213 nominal::enum_def(p);
214 ENUM_DEF
215 }
216 USE_KW => {
217 use_item::use_item(p);
218 USE_ITEM
219 }
220 CONST_KW if (la == IDENT || la == MUT_KW) => {
221 consts::const_def(p);
222 CONST_DEF
223 }
224 STATIC_KW => {
225 consts::static_def(p);
226 STATIC_DEF
227 } 201 }
202 ENUM_KW => nominal::enum_def(p, m),
203 USE_KW => use_item::use_item(p, m),
204 CONST_KW if (la == IDENT || la == MUT_KW) => consts::const_def(p, m),
205 STATIC_KW => consts::static_def(p, m),
228 // test extern_block 206 // test extern_block
229 // extern {} 207 // extern {}
230 EXTERN_KW 208 EXTERN_KW
@@ -232,14 +210,20 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
232 { 210 {
233 abi(p); 211 abi(p);
234 extern_item_list(p); 212 extern_item_list(p);
235 EXTERN_BLOCK 213 m.complete(p, EXTERN_BLOCK);
236 } 214 }
237 _ => return None, 215 _ => return Err(m),
238 }; 216 };
239 Some(kind) 217 if p.at(SEMI) {
218 p.err_and_bump(
219 "expected item, found `;`\n\
220 consider removing this semicolon",
221 );
222 }
223 Ok(())
240} 224}
241 225
242fn extern_crate_item(p: &mut Parser) { 226fn extern_crate_item(p: &mut Parser, m: Marker) {
243 assert!(p.at(EXTERN_KW)); 227 assert!(p.at(EXTERN_KW));
244 p.bump(); 228 p.bump();
245 assert!(p.at(CRATE_KW)); 229 assert!(p.at(CRATE_KW));
@@ -247,6 +231,7 @@ fn extern_crate_item(p: &mut Parser) {
247 name_ref(p); 231 name_ref(p);
248 opt_alias(p); 232 opt_alias(p);
249 p.expect(SEMI); 233 p.expect(SEMI);
234 m.complete(p, EXTERN_CRATE_ITEM);
250} 235}
251 236
252pub(crate) fn extern_item_list(p: &mut Parser) { 237pub(crate) fn extern_item_list(p: &mut Parser) {
@@ -295,7 +280,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
295 280
296// test type_item 281// test type_item
297// type Foo = Bar; 282// type Foo = Bar;
298fn type_def(p: &mut Parser) { 283fn type_def(p: &mut Parser, m: Marker) {
299 assert!(p.at(TYPE_KW)); 284 assert!(p.at(TYPE_KW));
300 p.bump(); 285 p.bump();
301 286
@@ -317,9 +302,10 @@ fn type_def(p: &mut Parser) {
317 types::type_(p); 302 types::type_(p);
318 } 303 }
319 p.expect(SEMI); 304 p.expect(SEMI);
305 m.complete(p, TYPE_ALIAS_DEF);
320} 306}
321 307
322pub(crate) fn mod_item(p: &mut Parser) { 308pub(crate) fn mod_item(p: &mut Parser, m: Marker) {
323 assert!(p.at(MOD_KW)); 309 assert!(p.at(MOD_KW));
324 p.bump(); 310 p.bump();
325 311
@@ -329,6 +315,7 @@ pub(crate) fn mod_item(p: &mut Parser) {
329 } else if !p.eat(SEMI) { 315 } else if !p.eat(SEMI) {
330 p.error("expected `;` or `{`"); 316 p.error("expected `;` or `{`");
331 } 317 }
318 m.complete(p, MODULE);
332} 319}
333 320
334pub(crate) fn mod_item_list(p: &mut Parser) { 321pub(crate) fn mod_item_list(p: &mut Parser) {
diff --git a/crates/ra_parser/src/grammar/items/consts.rs b/crates/ra_parser/src/grammar/items/consts.rs
index 5a5852f83..e6e6011c6 100644
--- a/crates/ra_parser/src/grammar/items/consts.rs
+++ b/crates/ra_parser/src/grammar/items/consts.rs
@@ -1,14 +1,14 @@
1use super::*; 1use super::*;
2 2
3pub(super) fn static_def(p: &mut Parser) { 3pub(super) fn static_def(p: &mut Parser, m: Marker) {
4 const_or_static(p, STATIC_KW) 4 const_or_static(p, m, STATIC_KW, STATIC_DEF)
5} 5}
6 6
7pub(super) fn const_def(p: &mut Parser) { 7pub(super) fn const_def(p: &mut Parser, m: Marker) {
8 const_or_static(p, CONST_KW) 8 const_or_static(p, m, CONST_KW, CONST_DEF)
9} 9}
10 10
11fn const_or_static(p: &mut Parser, kw: SyntaxKind) { 11fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
12 assert!(p.at(kw)); 12 assert!(p.at(kw));
13 p.bump(); 13 p.bump();
14 p.eat(MUT_KW); // TODO: validator to forbid const mut 14 p.eat(MUT_KW); // TODO: validator to forbid const mut
@@ -18,4 +18,5 @@ fn const_or_static(p: &mut Parser, kw: SyntaxKind) {
18 expressions::expr(p); 18 expressions::expr(p);
19 } 19 }
20 p.expect(SEMI); 20 p.expect(SEMI);
21 m.complete(p, def);
21} 22}
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/nominal.rs
index ff9b38f9c..a3579eebd 100644
--- a/crates/ra_parser/src/grammar/items/nominal.rs
+++ b/crates/ra_parser/src/grammar/items/nominal.rs
@@ -1,6 +1,6 @@
1use super::*; 1use super::*;
2 2
3pub(super) fn struct_def(p: &mut Parser, kind: SyntaxKind) { 3pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
4 assert!(p.at(STRUCT_KW) || p.at_contextual_kw("union")); 4 assert!(p.at(STRUCT_KW) || p.at_contextual_kw("union"));
5 p.bump_remap(kind); 5 p.bump_remap(kind);
6 6
@@ -12,19 +12,16 @@ pub(super) fn struct_def(p: &mut Parser, kind: SyntaxKind) {
12 match p.current() { 12 match p.current() {
13 SEMI => { 13 SEMI => {
14 p.bump(); 14 p.bump();
15 return;
16 } 15 }
17 L_CURLY => named_field_def_list(p), 16 L_CURLY => named_field_def_list(p),
18 _ => { 17 _ => {
19 //TODO: special case `(` error message 18 //TODO: special case `(` error message
20 p.error("expected `;` or `{`"); 19 p.error("expected `;` or `{`");
21 return;
22 } 20 }
23 } 21 }
24 } 22 }
25 SEMI if kind == STRUCT_KW => { 23 SEMI if kind == STRUCT_KW => {
26 p.bump(); 24 p.bump();
27 return;
28 } 25 }
29 L_CURLY => named_field_def_list(p), 26 L_CURLY => named_field_def_list(p),
30 L_PAREN if kind == STRUCT_KW => { 27 L_PAREN if kind == STRUCT_KW => {
@@ -37,16 +34,15 @@ pub(super) fn struct_def(p: &mut Parser, kind: SyntaxKind) {
37 } 34 }
38 _ if kind == STRUCT_KW => { 35 _ if kind == STRUCT_KW => {
39 p.error("expected `;`, `{`, or `(`"); 36 p.error("expected `;`, `{`, or `(`");
40 return;
41 } 37 }
42 _ => { 38 _ => {
43 p.error("expected `{`"); 39 p.error("expected `{`");
44 return;
45 } 40 }
46 } 41 }
42 m.complete(p, STRUCT_DEF);
47} 43}
48 44
49pub(super) fn enum_def(p: &mut Parser) { 45pub(super) fn enum_def(p: &mut Parser, m: Marker) {
50 assert!(p.at(ENUM_KW)); 46 assert!(p.at(ENUM_KW));
51 p.bump(); 47 p.bump();
52 name_r(p, ITEM_RECOVERY_SET); 48 name_r(p, ITEM_RECOVERY_SET);
@@ -57,6 +53,7 @@ pub(super) fn enum_def(p: &mut Parser) {
57 } else { 53 } else {
58 p.error("expected `{`") 54 p.error("expected `{`")
59 } 55 }
56 m.complete(p, ENUM_DEF);
60} 57}
61 58
62pub(crate) fn enum_variant_list(p: &mut Parser) { 59pub(crate) fn enum_variant_list(p: &mut Parser) {
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
index b36612726..ea2f94604 100644
--- a/crates/ra_parser/src/grammar/items/use_item.rs
+++ b/crates/ra_parser/src/grammar/items/use_item.rs
@@ -1,10 +1,11 @@
1use super::*; 1use super::*;
2 2
3pub(super) fn use_item(p: &mut Parser) { 3pub(super) fn use_item(p: &mut Parser, m: Marker) {
4 assert!(p.at(USE_KW)); 4 assert!(p.at(USE_KW));
5 p.bump(); 5 p.bump();
6 use_tree(p); 6 use_tree(p);
7 p.expect(SEMI); 7 p.expect(SEMI);
8 m.complete(p, USE_ITEM);
8} 9}
9 10
10/// Parse a use 'tree', such as `some::path` in `use some::path;` 11/// Parse a use 'tree', such as `some::path` in `use some::path;`
diff --git a/crates/ra_syntax/tests/data/parser/err/0003_C++_semicolon.txt b/crates/ra_syntax/tests/data/parser/err/0003_C++_semicolon.txt
index e9400d03b..b87fe46bd 100644
--- a/crates/ra_syntax/tests/data/parser/err/0003_C++_semicolon.txt
+++ b/crates/ra_syntax/tests/data/parser/err/0003_C++_semicolon.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 40) 1SOURCE_FILE@[0; 40)
2 STRUCT_DEF@[0; 40) 2 STRUCT_DEF@[0; 39)
3 STRUCT_KW@[0; 6) 3 STRUCT_KW@[0; 6)
4 WHITESPACE@[6; 7) 4 WHITESPACE@[6; 7)
5 NAME@[7; 8) 5 NAME@[7; 8)
@@ -35,5 +35,5 @@ SOURCE_FILE@[0; 40)
35 R_CURLY@[38; 39) 35 R_CURLY@[38; 39)
36 err: `expected item, found `;` 36 err: `expected item, found `;`
37consider removing this semicolon` 37consider removing this semicolon`
38 ERROR@[39; 40) 38 ERROR@[39; 40)
39 SEMI@[39; 40) 39 SEMI@[39; 40)
diff --git a/crates/ra_syntax/tests/data/parser/inline/err/0008_pub_expr.rs b/crates/ra_syntax/tests/data/parser/inline/err/0008_pub_expr.rs
new file mode 100644
index 000000000..2976f6862
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0008_pub_expr.rs
@@ -0,0 +1 @@
fn foo() { pub 92; }
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.txt b/crates/ra_syntax/tests/data/parser/inline/err/0008_pub_expr.txt
index de20eee7a..e65d9c9e1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0008_pub_expr.txt
@@ -1,4 +1,4 @@
1SOURCE_FILE@[0; 29) 1SOURCE_FILE@[0; 21)
2 FN_DEF@[0; 20) 2 FN_DEF@[0; 20)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
@@ -11,15 +11,15 @@ SOURCE_FILE@[0; 29)
11 BLOCK@[9; 20) 11 BLOCK@[9; 20)
12 L_CURLY@[9; 10) 12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 11) 13 WHITESPACE@[10; 11)
14 EXPR_STMT@[11; 18) 14 ERROR@[11; 14)
15 VISIBILITY@[11; 14) 15 VISIBILITY@[11; 14)
16 PUB_KW@[11; 14) 16 PUB_KW@[11; 14)
17 WHITESPACE@[14; 15) 17 err: `expected an item`
18 WHITESPACE@[14; 15)
19 EXPR_STMT@[15; 18)
18 LITERAL@[15; 17) 20 LITERAL@[15; 17)
19 INT_NUMBER@[15; 17) "92" 21 INT_NUMBER@[15; 17) "92"
20 SEMI@[17; 18) 22 SEMI@[17; 18)
21 WHITESPACE@[18; 19) 23 WHITESPACE@[18; 19)
22 R_CURLY@[19; 20) 24 R_CURLY@[19; 20)
23 WHITESPACE@[20; 21) 25 WHITESPACE@[20; 21)
24 COMMENT@[21; 28)
25 WHITESPACE@[28; 29)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.rs
deleted file mode 100644
index d9d99d2d3..000000000
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.rs
+++ /dev/null
@@ -1 +0,0 @@
1fn foo() { pub 92; } //FIXME
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.rs
index 660d927cf..e2b5f2161 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.rs
@@ -1 +1,3 @@
1crate fn main() { } 1crate fn main() { }
2struct S { crate field: u32 }
3struct T(crate u32);
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.txt
index ff5add838..695734d54 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.txt
@@ -1,4 +1,4 @@
1SOURCE_FILE@[0; 20) 1SOURCE_FILE@[0; 71)
2 FN_DEF@[0; 19) 2 FN_DEF@[0; 19)
3 VISIBILITY@[0; 5) 3 VISIBILITY@[0; 5)
4 CRATE_KW@[0; 5) 4 CRATE_KW@[0; 5)
@@ -16,3 +16,47 @@ SOURCE_FILE@[0; 20)
16 WHITESPACE@[17; 18) 16 WHITESPACE@[17; 18)
17 R_CURLY@[18; 19) 17 R_CURLY@[18; 19)
18 WHITESPACE@[19; 20) 18 WHITESPACE@[19; 20)
19 STRUCT_DEF@[20; 49)
20 STRUCT_KW@[20; 26)
21 WHITESPACE@[26; 27)
22 NAME@[27; 28)
23 IDENT@[27; 28) "S"
24 WHITESPACE@[28; 29)
25 NAMED_FIELD_DEF_LIST@[29; 49)
26 L_CURLY@[29; 30)
27 WHITESPACE@[30; 31)
28 NAMED_FIELD_DEF@[31; 47)
29 VISIBILITY@[31; 36)
30 CRATE_KW@[31; 36)
31 WHITESPACE@[36; 37)
32 NAME@[37; 42)
33 IDENT@[37; 42) "field"
34 COLON@[42; 43)
35 WHITESPACE@[43; 44)
36 PATH_TYPE@[44; 47)
37 PATH@[44; 47)
38 PATH_SEGMENT@[44; 47)
39 NAME_REF@[44; 47)
40 IDENT@[44; 47) "u32"
41 WHITESPACE@[47; 48)
42 R_CURLY@[48; 49)
43 WHITESPACE@[49; 50)
44 STRUCT_DEF@[50; 70)
45 STRUCT_KW@[50; 56)
46 WHITESPACE@[56; 57)
47 NAME@[57; 58)
48 IDENT@[57; 58) "T"
49 POS_FIELD_DEF_LIST@[58; 69)
50 L_PAREN@[58; 59)
51 POS_FIELD_DEF@[59; 68)
52 VISIBILITY@[59; 64)
53 CRATE_KW@[59; 64)
54 WHITESPACE@[64; 65)
55 PATH_TYPE@[65; 68)
56 PATH@[65; 68)
57 PATH_SEGMENT@[65; 68)
58 NAME_REF@[65; 68)
59 IDENT@[65; 68) "u32"
60 R_PAREN@[68; 69)
61 SEMI@[69; 70)
62 WHITESPACE@[70; 71)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0125_crate_keyword_path.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0125_crate_keyword_path.rs
new file mode 100644
index 000000000..0f454d121
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0125_crate_keyword_path.rs
@@ -0,0 +1 @@
fn foo() { crate::foo(); }
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0125_crate_keyword_path.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0125_crate_keyword_path.txt
new file mode 100644
index 000000000..7c637b079
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0125_crate_keyword_path.txt
@@ -0,0 +1,31 @@
1SOURCE_FILE@[0; 27)
2 FN_DEF@[0; 26)
3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3)
5 NAME@[3; 6)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 8)
8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9)
11 BLOCK@[9; 26)
12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 11)
14 EXPR_STMT@[11; 24)
15 CALL_EXPR@[11; 23)
16 PATH_EXPR@[11; 21)
17 PATH@[11; 21)
18 PATH@[11; 16)
19 PATH_SEGMENT@[11; 16)
20 CRATE_KW@[11; 16)
21 COLONCOLON@[16; 18)
22 PATH_SEGMENT@[18; 21)
23 NAME_REF@[18; 21)
24 IDENT@[18; 21) "foo"
25 ARG_LIST@[21; 23)
26 L_PAREN@[21; 22)
27 R_PAREN@[22; 23)
28 SEMI@[23; 24)
29 WHITESPACE@[24; 25)
30 R_CURLY@[25; 26)
31 WHITESPACE@[26; 27)