aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_syntax/src/grammar/mod.rs5
-rw-r--r--crates/ra_syntax/src/grammar/type_params.rs97
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.rs4
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.txt58
4 files changed, 129 insertions, 35 deletions
diff --git a/crates/ra_syntax/src/grammar/mod.rs b/crates/ra_syntax/src/grammar/mod.rs
index c87564073..95c437983 100644
--- a/crates/ra_syntax/src/grammar/mod.rs
+++ b/crates/ra_syntax/src/grammar/mod.rs
@@ -21,6 +21,11 @@
21//! After adding a new inline-test, run `cargo collect-tests` to extract 21//! After adding a new inline-test, run `cargo collect-tests` to extract
22//! it as a standalone text-fixture into `tests/data/parser/inline`, and 22//! it as a standalone text-fixture into `tests/data/parser/inline`, and
23//! run `cargo test` once to create the "gold" value. 23//! run `cargo test` once to create the "gold" value.
24//!
25//! Coding convention: rules like `where_clause` always produce either a
26//! node or an error, rules like `opt_where_clause` may produce nothing.
27//! Non-opt rules typically start with `assert!(p.at(FIRST_TOKEN))`, the
28//! caller is responsible for branching on the first token.
24mod attributes; 29mod attributes;
25mod expressions; 30mod expressions;
26mod items; 31mod items;
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs
index 79f5036b4..735c728e5 100644
--- a/crates/ra_syntax/src/grammar/type_params.rs
+++ b/crates/ra_syntax/src/grammar/type_params.rs
@@ -4,6 +4,11 @@ pub(super) fn opt_type_param_list(p: &mut Parser) {
4 if !p.at(L_ANGLE) { 4 if !p.at(L_ANGLE) {
5 return; 5 return;
6 } 6 }
7 type_param_list(p);
8}
9
10fn type_param_list(p: &mut Parser) {
11 assert!(p.at(L_ANGLE));
7 let m = p.start(); 12 let m = p.start();
8 p.bump(); 13 p.bump();
9 14
@@ -19,32 +24,32 @@ pub(super) fn opt_type_param_list(p: &mut Parser) {
19 } 24 }
20 p.expect(R_ANGLE); 25 p.expect(R_ANGLE);
21 m.complete(p, TYPE_PARAM_LIST); 26 m.complete(p, TYPE_PARAM_LIST);
27}
22 28
23 fn lifetime_param(p: &mut Parser) { 29fn lifetime_param(p: &mut Parser) {
24 assert!(p.at(LIFETIME)); 30 assert!(p.at(LIFETIME));
25 let m = p.start(); 31 let m = p.start();
26 p.bump(); 32 p.bump();
27 if p.at(COLON) { 33 if p.at(COLON) {
28 lifetime_bounds(p); 34 lifetime_bounds(p);
29 }
30 m.complete(p, LIFETIME_PARAM);
31 } 35 }
36 m.complete(p, LIFETIME_PARAM);
37}
32 38
33 fn type_param(p: &mut Parser) { 39fn type_param(p: &mut Parser) {
34 assert!(p.at(IDENT)); 40 assert!(p.at(IDENT));
35 let m = p.start(); 41 let m = p.start();
36 name(p); 42 name(p);
37 if p.at(COLON) { 43 if p.at(COLON) {
38 bounds(p); 44 bounds(p);
39 } 45 }
40 // test type_param_default 46 // test type_param_default
41 // struct S<T = i32>; 47 // struct S<T = i32>;
42 if p.at(EQ) { 48 if p.at(EQ) {
43 p.bump(); 49 p.bump();
44 types::type_(p) 50 types::type_(p)
45 }
46 m.complete(p, TYPE_PARAM);
47 } 51 }
52 m.complete(p, TYPE_PARAM);
48} 53}
49 54
50// test type_param_bounds 55// test type_param_bounds
@@ -99,7 +104,7 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
99 let m = p.start(); 104 let m = p.start();
100 p.bump(); 105 p.bump();
101 loop { 106 loop {
102 if !(paths::is_path_start(p) || p.current() == LIFETIME) { 107 if !(paths::is_path_start(p) || p.current() == LIFETIME || p.current() == FOR_KW) {
103 break; 108 break;
104 } 109 }
105 where_predicate(p); 110 where_predicate(p);
@@ -112,19 +117,41 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
112 117
113fn where_predicate(p: &mut Parser) { 118fn where_predicate(p: &mut Parser) {
114 let m = p.start(); 119 let m = p.start();
115 if p.at(LIFETIME) { 120 match p.current() {
116 p.eat(LIFETIME); 121 LIFETIME => {
117 if p.at(COLON) { 122 p.bump();
118 lifetime_bounds(p) 123 if p.at(COLON) {
119 } else { 124 lifetime_bounds(p);
120 p.error("expected colon") 125 } else {
126 p.error("expected colon");
127 }
128 }
129 // test where_pred_for
130 // fn test<F>()
131 // where
132 // for<'a> F: Fn(&'a str)
133 // { }
134 FOR_KW => {
135 p.bump();
136 if p.at(L_ANGLE) {
137 type_param_list(p);
138 types::path_type(p);
139 if p.at(COLON) {
140 bounds(p);
141 } else {
142 p.error("expected colon");
143 }
144 } else {
145 p.error("expected `<`");
146 }
121 } 147 }
122 } else { 148 _ => {
123 types::path_type(p); 149 types::path_type(p);
124 if p.at(COLON) { 150 if p.at(COLON) {
125 bounds(p); 151 bounds(p);
126 } else { 152 } else {
127 p.error("expected colon") 153 p.error("expected colon");
154 }
128 } 155 }
129 } 156 }
130 m.complete(p, WHERE_PRED); 157 m.complete(p, WHERE_PRED);
diff --git a/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.rs b/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.rs
new file mode 100644
index 000000000..b448c6178
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.rs
@@ -0,0 +1,4 @@
1fn test<F>()
2where
3 for<'a> F: Fn(&'a str)
4{ }
diff --git a/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.txt b/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.txt
new file mode 100644
index 000000000..08aacc77a
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.txt
@@ -0,0 +1,58 @@
1ROOT@[0; 49)
2 FN_DEF@[0; 48)
3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3)
5 NAME@[3; 7)
6 IDENT@[3; 7) "test"
7 TYPE_PARAM_LIST@[7; 10)
8 L_ANGLE@[7; 8)
9 TYPE_PARAM@[8; 9)
10 NAME@[8; 9)
11 IDENT@[8; 9) "F"
12 R_ANGLE@[9; 10)
13 PARAM_LIST@[10; 12)
14 L_PAREN@[10; 11)
15 R_PAREN@[11; 12)
16 WHITESPACE@[12; 13)
17 WHERE_CLAUSE@[13; 44)
18 WHERE_KW@[13; 18)
19 WHITESPACE@[18; 22)
20 WHERE_PRED@[22; 44)
21 FOR_KW@[22; 25)
22 TYPE_PARAM_LIST@[25; 29)
23 L_ANGLE@[25; 26)
24 LIFETIME_PARAM@[26; 28)
25 LIFETIME@[26; 28) "'a"
26 R_ANGLE@[28; 29)
27 WHITESPACE@[29; 30)
28 PATH_TYPE@[30; 31)
29 PATH@[30; 31)
30 PATH_SEGMENT@[30; 31)
31 NAME_REF@[30; 31)
32 IDENT@[30; 31) "F"
33 COLON@[31; 32)
34 WHITESPACE@[32; 33)
35 PATH_TYPE@[33; 44)
36 PATH@[33; 44)
37 PATH_SEGMENT@[33; 44)
38 NAME_REF@[33; 35)
39 IDENT@[33; 35) "Fn"
40 PARAM_LIST@[35; 44)
41 L_PAREN@[35; 36)
42 PARAM@[36; 43)
43 REFERENCE_TYPE@[36; 43)
44 AMP@[36; 37)
45 LIFETIME@[37; 39) "'a"
46 WHITESPACE@[39; 40)
47 PATH_TYPE@[40; 43)
48 PATH@[40; 43)
49 PATH_SEGMENT@[40; 43)
50 NAME_REF@[40; 43)
51 IDENT@[40; 43) "str"
52 R_PAREN@[43; 44)
53 WHITESPACE@[44; 45)
54 BLOCK@[45; 48)
55 L_CURLY@[45; 46)
56 WHITESPACE@[46; 47)
57 R_CURLY@[47; 48)
58 WHITESPACE@[48; 49)