aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/params.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar/params.rs')
-rw-r--r--crates/ra_parser/src/grammar/params.rs111
1 files changed, 66 insertions, 45 deletions
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index c10b53316..897092a67 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -7,54 +7,59 @@ use super::*;
7// fn b(x: i32) {} 7// fn b(x: i32) {}
8// fn c(x: i32, ) {} 8// fn c(x: i32, ) {}
9// fn d(x: i32, y: ()) {} 9// fn d(x: i32, y: ()) {}
10pub(super) fn param_list(p: &mut Parser) { 10pub(super) fn param_list_fn(p: &mut Parser) {
11 list_(p, Flavor::Normal) 11 list_(p, Flavor::Function)
12} 12}
13 13
14// test param_list_opt_patterns 14// test param_list_opt_patterns
15// fn foo<F: FnMut(&mut Foo<'a>)>(){} 15// fn foo<F: FnMut(&mut Foo<'a>)>(){}
16pub(super) fn param_list_opt_patterns(p: &mut Parser) { 16pub(super) fn param_list_impl_fn(p: &mut Parser) {
17 list_(p, Flavor::OptionalPattern) 17 list_(p, Flavor::ImplFn)
18} 18}
19 19
20pub(super) fn param_list_opt_types(p: &mut Parser) { 20pub(super) fn param_list_fn_ptr(p: &mut Parser) {
21 list_(p, Flavor::OptionalType) 21 list_(p, Flavor::FnPointer)
22} 22}
23 23
24#[derive(Clone, Copy, Eq, PartialEq)] 24pub(super) fn param_list_closure(p: &mut Parser) {
25enum Flavor { 25 list_(p, Flavor::Closure)
26 OptionalType,
27 OptionalPattern,
28 Normal,
29} 26}
30 27
31impl Flavor { 28#[derive(Debug, Clone, Copy)]
32 fn type_required(self) -> bool { 29enum Flavor {
33 match self { 30 Function, // Includes trait fn params; omitted param idents are not supported
34 Flavor::OptionalType => false, 31 ImplFn,
35 _ => true, 32 FnPointer,
36 } 33 Closure
37 }
38} 34}
39 35
40fn list_(p: &mut Parser, flavor: Flavor) { 36fn list_(p: &mut Parser, flavor: Flavor) {
41 let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) }; 37 use Flavor::*;
42 assert!(p.at(bra)); 38
39 let (bra, ket) = match flavor {
40 Closure => (T![|], T![|]),
41 Function | ImplFn | FnPointer => (T!['('], T![')'])
42 };
43
43 let m = p.start(); 44 let m = p.start();
44 p.bump(bra); 45 p.bump(bra);
45 if flavor.type_required() { 46
47 if let Function = flavor {
46 // test self_param_outer_attr 48 // test self_param_outer_attr
47 // fn f(#[must_use] self) {} 49 // fn f(#[must_use] self) {}
48 attributes::outer_attributes(p); 50 attributes::outer_attributes(p);
49 opt_self_param(p); 51 opt_self_param(p);
50 } 52 }
53
51 while !p.at(EOF) && !p.at(ket) { 54 while !p.at(EOF) && !p.at(ket) {
52 // test param_outer_arg 55 // test param_outer_arg
53 // fn f(#[attr1] pat: Type) {} 56 // fn f(#[attr1] pat: Type) {}
54 attributes::outer_attributes(p); 57 attributes::outer_attributes(p);
55 58
56 if flavor.type_required() && p.at(T![...]) { 59 if let Function | FnPointer = flavor {
57 break; 60 if p.at(T![...]) {
61 break;
62 }
58 } 63 }
59 64
60 if !p.at_ts(VALUE_PARAMETER_FIRST) { 65 if !p.at_ts(VALUE_PARAMETER_FIRST) {
@@ -68,7 +73,7 @@ fn list_(p: &mut Parser, flavor: Flavor) {
68 } 73 }
69 // test param_list_vararg 74 // test param_list_vararg
70 // extern "C" { fn printf(format: *const i8, ...) -> i32; } 75 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
71 if flavor.type_required() { 76 if let Function | FnPointer = flavor {
72 p.eat(T![...]); 77 p.eat(T![...]);
73 } 78 }
74 p.expect(ket); 79 p.expect(ket);
@@ -80,36 +85,52 @@ const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYP
80fn value_parameter(p: &mut Parser, flavor: Flavor) { 85fn value_parameter(p: &mut Parser, flavor: Flavor) {
81 let m = p.start(); 86 let m = p.start();
82 match flavor { 87 match flavor {
83 Flavor::OptionalType | Flavor::Normal => { 88 // test trait_fn_placeholder_parameter
89 // trait Foo {
90 // fn bar(_: u64, mut x: i32);
91 // }
92
93 // test trait_fn_patterns
94 // trait T {
95 // fn f1((a, b): (usize, usize)) {}
96 // fn f2(S { a, b }: S) {}
97 // fn f3(NewType(a): NewType) {}
98 // fn f4(&&a: &&usize) {}
99 // }
100
101 // test fn_patterns
102 // impl U {
103 // fn f1((a, b): (usize, usize)) {}
104 // fn f2(S { a, b }: S) {}
105 // fn f3(NewType(a): NewType) {}
106 // fn f4(&&a: &&usize) {}
107 // }
108 Flavor::Function => {
84 patterns::pattern(p); 109 patterns::pattern(p);
85 if p.at(T![:]) && !p.at(T![::]) || flavor.type_required() { 110 types::ascription(p);
86 types::ascription(p)
87 }
88 } 111 }
89 // test value_parameters_no_patterns 112 // test value_parameters_no_patterns
90 // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>; 113 // type F = Box<Fn(i32, &i32, &i32, ())>;
91 Flavor::OptionalPattern => { 114 Flavor::ImplFn => {
92 let la0 = p.current(); 115 types::type_(p);
93 let la1 = p.nth(1); 116 }
94 let la2 = p.nth(2); 117 // test fn_pointer_param_ident_path
95 let la3 = p.nth(3); 118 // type Foo = fn(Bar::Baz);
96 119 // type Qux = fn(baz: Bar::Baz);
97 // test trait_fn_placeholder_parameter 120 Flavor::FnPointer => {
98 // trait Foo { 121 if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
99 // fn bar(_: u64, mut x: i32);
100 // }
101 if (la0 == IDENT || la0 == T![_]) && la1 == T![:] && !p.nth_at(1, T![::])
102 || la0 == T![mut] && la1 == IDENT && la2 == T![:]
103 || la0 == T![&]
104 && (la1 == IDENT && la2 == T![:] && !p.nth_at(2, T![::])
105 || la1 == T![mut] && la2 == IDENT && la3 == T![:] && !p.nth_at(3, T![::]))
106 {
107 patterns::pattern(p); 122 patterns::pattern(p);
108 types::ascription(p); 123 types::ascription(p);
109 } else { 124 } else {
110 types::type_(p); 125 types::type_(p);
111 } 126 }
112 } 127 }
128 Flavor::Closure => {
129 patterns::pattern(p);
130 if p.at(T![:]) && !p.at(T![::]) {
131 types::ascription(p);
132 }
133 }
113 } 134 }
114 m.complete(p, PARAM); 135 m.complete(p, PARAM);
115} 136}