aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assists/apply_demorgan.rs14
-rw-r--r--crates/ra_assists/src/assists/early_return.rs11
-rw-r--r--crates/ra_assists/src/assists/invert_if.rs33
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs13
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs2
-rw-r--r--crates/ra_parser/src/grammar/items.rs9
-rw-r--r--crates/ra_parser/src/grammar/params.rs120
-rw-r--r--crates/ra_parser/src/grammar/paths.rs4
-rw-r--r--crates/ra_parser/src/grammar/types.rs2
-rw-r--r--crates/ra_syntax/src/ast/make.rs35
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.txt115
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.txt61
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0152_fn_patterns.rs6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0152_fn_patterns.txt164
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0153_trait_fn_patterns.rs6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0153_trait_fn_patterns.txt161
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.txt58
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rs3
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.txt70
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0030_traits.rs4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0030_traits.txt154
24 files changed, 757 insertions, 294 deletions
diff --git a/crates/ra_assists/src/assists/apply_demorgan.rs b/crates/ra_assists/src/assists/apply_demorgan.rs
index dac6280ad..ba08a8223 100644
--- a/crates/ra_assists/src/assists/apply_demorgan.rs
+++ b/crates/ra_assists/src/assists/apply_demorgan.rs
@@ -31,12 +31,14 @@ pub(crate) fn apply_demorgan(ctx: AssistCtx) -> Option<Assist> {
31 if !cursor_in_range { 31 if !cursor_in_range {
32 return None; 32 return None;
33 } 33 }
34
34 let lhs = expr.lhs()?; 35 let lhs = expr.lhs()?;
35 let lhs_range = lhs.syntax().text_range(); 36 let lhs_range = lhs.syntax().text_range();
37 let not_lhs = invert_boolean_expression(lhs);
38
36 let rhs = expr.rhs()?; 39 let rhs = expr.rhs()?;
37 let rhs_range = rhs.syntax().text_range(); 40 let rhs_range = rhs.syntax().text_range();
38 let not_lhs = invert_boolean_expression(&lhs)?; 41 let not_rhs = invert_boolean_expression(rhs);
39 let not_rhs = invert_boolean_expression(&rhs)?;
40 42
41 ctx.add_assist(AssistId("apply_demorgan"), "Apply De Morgan's law", |edit| { 43 ctx.add_assist(AssistId("apply_demorgan"), "Apply De Morgan's law", |edit| {
42 edit.target(op_range); 44 edit.target(op_range);
@@ -77,12 +79,12 @@ mod tests {
77 } 79 }
78 80
79 #[test] 81 #[test]
80 fn demorgan_doesnt_apply_with_cursor_not_on_op() { 82 fn demorgan_general_case() {
81 check_assist_not_applicable(apply_demorgan, "fn f() { <|> !x || !x }") 83 check_assist(apply_demorgan, "fn f() { x ||<|> x }", "fn f() { !(!x &&<|> !x) }")
82 } 84 }
83 85
84 #[test] 86 #[test]
85 fn demorgan_doesnt_apply_when_operands_arent_negated_already() { 87 fn demorgan_doesnt_apply_with_cursor_not_on_op() {
86 check_assist_not_applicable(apply_demorgan, "fn f() { x ||<|> x }") 88 check_assist_not_applicable(apply_demorgan, "fn f() { <|> !x || !x }")
87 } 89 }
88} 90}
diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs
index 3169be2b9..8f30dc586 100644
--- a/crates/ra_assists/src/assists/early_return.rs
+++ b/crates/ra_assists/src/assists/early_return.rs
@@ -10,6 +10,7 @@ use ra_syntax::{
10 10
11use crate::{ 11use crate::{
12 assist_ctx::{Assist, AssistCtx}, 12 assist_ctx::{Assist, AssistCtx},
13 assists::invert_if::invert_boolean_expression,
13 AssistId, 14 AssistId,
14}; 15};
15 16
@@ -99,9 +100,13 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
99 let new_block = match if_let_pat { 100 let new_block = match if_let_pat {
100 None => { 101 None => {
101 // If. 102 // If.
102 let early_expression = &(early_expression.syntax().to_string() + ";"); 103 let new_expr = {
103 let new_expr = if_indent_level 104 let then_branch =
104 .increase_indent(make::if_expression(cond_expr, early_expression)); 105 make::block_expr(once(make::expr_stmt(early_expression).into()), None);
106 let cond = invert_boolean_expression(cond_expr);
107 let e = make::expr_if(cond, then_branch);
108 if_indent_level.increase_indent(e)
109 };
105 replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) 110 replace(new_expr.syntax(), &then_block, &parent_block, &if_expr)
106 } 111 }
107 Some((path, bound_ident)) => { 112 Some((path, bound_ident)) => {
diff --git a/crates/ra_assists/src/assists/invert_if.rs b/crates/ra_assists/src/assists/invert_if.rs
index 694c3642c..983392f21 100644
--- a/crates/ra_assists/src/assists/invert_if.rs
+++ b/crates/ra_assists/src/assists/invert_if.rs
@@ -1,4 +1,4 @@
1use ra_syntax::ast::{self, AstNode}; 1use ra_syntax::ast::{self, make, AstNode};
2use ra_syntax::T; 2use ra_syntax::T;
3 3
4use crate::{Assist, AssistCtx, AssistId}; 4use crate::{Assist, AssistCtx, AssistId};
@@ -35,8 +35,8 @@ pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
35 let then_node = expr.then_branch()?.syntax().clone(); 35 let then_node = expr.then_branch()?.syntax().clone();
36 36
37 if let ast::ElseBranch::Block(else_block) = expr.else_branch()? { 37 if let ast::ElseBranch::Block(else_block) = expr.else_branch()? {
38 let flip_cond = invert_boolean_expression(&cond)?;
39 let cond_range = cond.syntax().text_range(); 38 let cond_range = cond.syntax().text_range();
39 let flip_cond = invert_boolean_expression(cond);
40 let else_node = else_block.syntax(); 40 let else_node = else_block.syntax();
41 let else_range = else_node.text_range(); 41 let else_range = else_node.text_range();
42 let then_range = then_node.text_range(); 42 let then_range = then_node.text_range();
@@ -51,16 +51,23 @@ pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
51 None 51 None
52} 52}
53 53
54pub(crate) fn invert_boolean_expression(expr: &ast::Expr) -> Option<ast::Expr> { 54pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr {
55 if let Some(expr) = invert_special_case(&expr) {
56 return expr;
57 }
58 make::expr_prefix(T![!], expr)
59}
60
61pub(crate) fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
55 match expr { 62 match expr {
56 ast::Expr::BinExpr(bin) => match bin.op_kind()? { 63 ast::Expr::BinExpr(bin) => match bin.op_kind()? {
57 ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()), 64 ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()),
65 ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()),
58 _ => None, 66 _ => None,
59 }, 67 },
60 ast::Expr::PrefixExpr(pe) => match pe.op_kind()? { 68 ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(),
61 ast::PrefixOp::Not => pe.expr(), 69 // FIXME:
62 _ => None, 70 // ast::Expr::Literal(true | false )
63 },
64 _ => None, 71 _ => None,
65 } 72 }
66} 73}
@@ -90,12 +97,16 @@ mod tests {
90 } 97 }
91 98
92 #[test] 99 #[test]
93 fn invert_if_doesnt_apply_with_cursor_not_on_if() { 100 fn invert_if_general_case() {
94 check_assist_not_applicable(invert_if, "fn f() { if !<|>cond { 3 * 2 } else { 1 } }") 101 check_assist(
102 invert_if,
103 "fn f() { i<|>f cond { 3 * 2 } else { 1 } }",
104 "fn f() { i<|>f !cond { 1 } else { 3 * 2 } }",
105 )
95 } 106 }
96 107
97 #[test] 108 #[test]
98 fn invert_if_doesnt_apply_without_negated() { 109 fn invert_if_doesnt_apply_with_cursor_not_on_if() {
99 check_assist_not_applicable(invert_if, "fn f() { i<|>f cond { 3 * 2 } else { 1 } }") 110 check_assist_not_applicable(invert_if, "fn f() { if !<|>cond { 3 * 2 } else { 1 } }")
100 } 111 }
101} 112}
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 12961ba37..ceff82fda 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -635,12 +635,13 @@ fn on_check_task(
635 635
636 CheckTask::AddDiagnostic { url, diagnostic, fixes } => { 636 CheckTask::AddDiagnostic { url, diagnostic, fixes } => {
637 let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?; 637 let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?;
638 let file_id = world_state 638 let file_id = match world_state.vfs.read().path2file(&path) {
639 .vfs 639 Some(file) => FileId(file.0),
640 .read() 640 None => {
641 .path2file(&path) 641 log::error!("File with cargo diagnostic not found in VFS: {}", path.display());
642 .map(|it| FileId(it.0)) 642 return Ok(());
643 .ok_or_else(|| format!("unknown file: {}", path.to_string_lossy()))?; 643 }
644 };
644 645
645 task_sender 646 task_sender
646 .send(Task::Diagnostic(DiagnosticTask::AddCheck(file_id, diagnostic, fixes)))?; 647 .send(Task::Diagnostic(DiagnosticTask::AddCheck(file_id, diagnostic, fixes)))?;
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 2cc321473..f154077a8 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -229,7 +229,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
229 let m = p.start(); 229 let m = p.start();
230 p.eat(T![async]); 230 p.eat(T![async]);
231 p.eat(T![move]); 231 p.eat(T![move]);
232 params::param_list_opt_types(p); 232 params::param_list_closure(p);
233 if opt_fn_ret_type(p) { 233 if opt_fn_ret_type(p) {
234 if !p.at(T!['{']) { 234 if !p.at(T!['{']) {
235 p.error("expected `{`"); 235 p.error("expected `{`");
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index a88206fa8..54284c933 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -164,7 +164,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
164 // unsafe async fn foo() {} 164 // unsafe async fn foo() {}
165 // unsafe const fn bar() {} 165 // unsafe const fn bar() {}
166 T![fn] => { 166 T![fn] => {
167 fn_def(p, flavor); 167 fn_def(p);
168 m.complete(p, FN_DEF); 168 m.complete(p, FN_DEF);
169 } 169 }
170 170
@@ -301,7 +301,7 @@ pub(crate) fn extern_item_list(p: &mut Parser) {
301 m.complete(p, EXTERN_ITEM_LIST); 301 m.complete(p, EXTERN_ITEM_LIST);
302} 302}
303 303
304fn fn_def(p: &mut Parser, flavor: ItemFlavor) { 304fn fn_def(p: &mut Parser) {
305 assert!(p.at(T![fn])); 305 assert!(p.at(T![fn]));
306 p.bump(T![fn]); 306 p.bump(T![fn]);
307 307
@@ -311,10 +311,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
311 type_params::opt_type_param_list(p); 311 type_params::opt_type_param_list(p);
312 312
313 if p.at(T!['(']) { 313 if p.at(T!['(']) {
314 match flavor { 314 params::param_list_fn_def(p);
315 ItemFlavor::Mod => params::param_list(p),
316 ItemFlavor::Trait => params::param_list_opt_patterns(p),
317 }
318 } else { 315 } else {
319 p.error("expected function arguments"); 316 p.error("expected function arguments");
320 } 317 }
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index c10b53316..94edc7f35 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -7,54 +7,60 @@ 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_def(p: &mut Parser) {
11 list_(p, Flavor::Normal) 11 list_(p, Flavor::FnDef)
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_fn_trait(p: &mut Parser) {
17 list_(p, Flavor::OptionalPattern) 17 list_(p, Flavor::FnTrait)
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 FnDef, // Includes trait fn params; omitted param idents are not supported
34 Flavor::OptionalType => false, 31 FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations
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 FnDef | FnTrait | 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 FnDef = 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 // test param_list_vararg
57 break; 60 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
61 match flavor {
62 FnDef | FnPointer if p.eat(T![...]) => break,
63 _ => (),
58 } 64 }
59 65
60 if !p.at_ts(VALUE_PARAMETER_FIRST) { 66 if !p.at_ts(VALUE_PARAMETER_FIRST) {
@@ -66,11 +72,7 @@ fn list_(p: &mut Parser, flavor: Flavor) {
66 p.expect(T![,]); 72 p.expect(T![,]);
67 } 73 }
68 } 74 }
69 // test param_list_vararg 75
70 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
71 if flavor.type_required() {
72 p.eat(T![...]);
73 }
74 p.expect(ket); 76 p.expect(ket);
75 m.complete(p, PARAM_LIST); 77 m.complete(p, PARAM_LIST);
76} 78}
@@ -80,36 +82,56 @@ const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYP
80fn value_parameter(p: &mut Parser, flavor: Flavor) { 82fn value_parameter(p: &mut Parser, flavor: Flavor) {
81 let m = p.start(); 83 let m = p.start();
82 match flavor { 84 match flavor {
83 Flavor::OptionalType | Flavor::Normal => { 85 // test trait_fn_placeholder_parameter
86 // trait Foo {
87 // fn bar(_: u64, mut x: i32);
88 // }
89
90 // test trait_fn_patterns
91 // trait T {
92 // fn f1((a, b): (usize, usize)) {}
93 // fn f2(S { a, b }: S) {}
94 // fn f3(NewType(a): NewType) {}
95 // fn f4(&&a: &&usize) {}
96 // }
97
98 // test fn_patterns
99 // impl U {
100 // fn f1((a, b): (usize, usize)) {}
101 // fn f2(S { a, b }: S) {}
102 // fn f3(NewType(a): NewType) {}
103 // fn f4(&&a: &&usize) {}
104 // }
105 Flavor::FnDef => {
84 patterns::pattern(p); 106 patterns::pattern(p);
85 if p.at(T![:]) && !p.at(T![::]) || flavor.type_required() { 107 types::ascription(p);
86 types::ascription(p)
87 }
88 } 108 }
89 // test value_parameters_no_patterns 109 // test value_parameters_no_patterns
90 // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>; 110 // type F = Box<Fn(i32, &i32, &i32, ())>;
91 Flavor::OptionalPattern => { 111 Flavor::FnTrait => {
92 let la0 = p.current(); 112 types::type_(p);
93 let la1 = p.nth(1); 113 }
94 let la2 = p.nth(2); 114 // test fn_pointer_param_ident_path
95 let la3 = p.nth(3); 115 // type Foo = fn(Bar::Baz);
96 116 // type Qux = fn(baz: Bar::Baz);
97 // test trait_fn_placeholder_parameter 117 Flavor::FnPointer => {
98 // trait Foo { 118 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); 119 patterns::pattern(p);
108 types::ascription(p); 120 types::ascription(p);
109 } else { 121 } else {
110 types::type_(p); 122 types::type_(p);
111 } 123 }
112 } 124 }
125 // test closure_params
126 // fn main() {
127 // let foo = |bar, baz: Baz, qux: Qux::Quux| ();
128 // }
129 Flavor::Closure => {
130 patterns::pattern(p);
131 if p.at(T![:]) && !p.at(T![::]) {
132 types::ascription(p);
133 }
134 }
113 } 135 }
114 m.complete(p, PARAM); 136 m.complete(p, PARAM);
115} 137}
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs
index ca8e075a1..f5bf3d7ce 100644
--- a/crates/ra_parser/src/grammar/paths.rs
+++ b/crates/ra_parser/src/grammar/paths.rs
@@ -97,9 +97,9 @@ fn opt_path_type_args(p: &mut Parser, mode: Mode) {
97 Mode::Use => return, 97 Mode::Use => return,
98 Mode::Type => { 98 Mode::Type => {
99 // test path_fn_trait_args 99 // test path_fn_trait_args
100 // type F = Box<Fn(x: i32) -> ()>; 100 // type F = Box<Fn(i32) -> ()>;
101 if p.at(T!['(']) { 101 if p.at(T!['(']) {
102 params::param_list_opt_patterns(p); 102 params::param_list_fn_trait(p);
103 opt_fn_ret_type(p); 103 opt_fn_ret_type(p);
104 } else { 104 } else {
105 type_args::opt_type_arg_list(p, false) 105 type_args::opt_type_arg_list(p, false)
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs
index 9b2e440fb..2c00bce80 100644
--- a/crates/ra_parser/src/grammar/types.rs
+++ b/crates/ra_parser/src/grammar/types.rs
@@ -183,7 +183,7 @@ fn fn_pointer_type(p: &mut Parser) {
183 return; 183 return;
184 } 184 }
185 if p.at(T!['(']) { 185 if p.at(T!['(']) {
186 params::param_list_opt_patterns(p); 186 params::param_list_fn_ptr(p);
187 } else { 187 } else {
188 p.error("expected parameters") 188 p.error("expected parameters")
189 } 189 }
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index 02966a3ff..862eb1172 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -33,6 +33,21 @@ pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordF
33 } 33 }
34} 34}
35 35
36pub fn block_expr(
37 stmts: impl IntoIterator<Item = ast::Stmt>,
38 tail_expr: Option<ast::Expr>,
39) -> ast::BlockExpr {
40 let mut text = "{\n".to_string();
41 for stmt in stmts.into_iter() {
42 text += &format!(" {}\n", stmt.syntax());
43 }
44 if let Some(tail_expr) = tail_expr {
45 text += &format!(" {}\n", tail_expr.syntax())
46 }
47 text += "}";
48 ast_from_text(&format!("fn f() {}", text))
49}
50
36pub fn block_from_expr(e: ast::Expr) -> ast::Block { 51pub fn block_from_expr(e: ast::Expr) -> ast::Block {
37 return from_text(&format!("{{ {} }}", e.syntax())); 52 return from_text(&format!("{{ {} }}", e.syntax()));
38 53
@@ -62,6 +77,13 @@ pub fn expr_return() -> ast::Expr {
62pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr { 77pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr {
63 expr_from_text(&format!("match {} {}", expr.syntax(), match_arm_list.syntax())) 78 expr_from_text(&format!("match {} {}", expr.syntax(), match_arm_list.syntax()))
64} 79}
80pub fn expr_if(condition: ast::Expr, then_branch: ast::BlockExpr) -> ast::Expr {
81 expr_from_text(&format!("if {} {}", condition.syntax(), then_branch.syntax()))
82}
83pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr {
84 let token = token(op);
85 expr_from_text(&format!("{}{}", token, expr.syntax()))
86}
65fn expr_from_text(text: &str) -> ast::Expr { 87fn expr_from_text(text: &str) -> ast::Expr {
66 ast_from_text(&format!("const C: () = {};", text)) 88 ast_from_text(&format!("const C: () = {};", text))
67} 89}
@@ -158,14 +180,6 @@ pub fn where_clause(preds: impl IntoIterator<Item = ast::WherePred>) -> ast::Whe
158 } 180 }
159} 181}
160 182
161pub fn if_expression(condition: ast::Expr, statement: &str) -> ast::IfExpr {
162 ast_from_text(&format!(
163 "fn f() {{ if !{} {{\n {}\n}}\n}}",
164 condition.syntax().text(),
165 statement
166 ))
167}
168
169pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetStmt { 183pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetStmt {
170 let text = match initializer { 184 let text = match initializer {
171 Some(it) => format!("let {} = {};", pattern.syntax(), it.syntax()), 185 Some(it) => format!("let {} = {};", pattern.syntax(), it.syntax()),
@@ -173,6 +187,9 @@ pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetSt
173 }; 187 };
174 ast_from_text(&format!("fn f() {{ {} }}", text)) 188 ast_from_text(&format!("fn f() {{ {} }}", text))
175} 189}
190pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt {
191 ast_from_text(&format!("fn f() {{ {}; }}", expr.syntax()))
192}
176 193
177pub fn token(kind: SyntaxKind) -> SyntaxToken { 194pub fn token(kind: SyntaxKind) -> SyntaxToken {
178 tokens::SOURCE_FILE 195 tokens::SOURCE_FILE
@@ -203,7 +220,7 @@ pub mod tokens {
203 use once_cell::sync::Lazy; 220 use once_cell::sync::Lazy;
204 221
205 pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = 222 pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> =
206 Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2)\n;")); 223 Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2, !true)\n;"));
207 224
208 pub fn comma() -> SyntaxToken { 225 pub fn comma() -> SyntaxToken {
209 SOURCE_FILE 226 SOURCE_FILE
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs b/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs
index d8c23c76a..93636e926 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs
@@ -1 +1 @@
type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>; type F = Box<Fn(i32, &i32, &i32, ())>;
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.txt b/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.txt
index 8cfba8420..9241f6fb2 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 54) 1SOURCE_FILE@[0; 39)
2 TYPE_ALIAS_DEF@[0; 53) 2 TYPE_ALIAS_DEF@[0; 38)
3 TYPE_KW@[0; 4) "type" 3 TYPE_KW@[0; 4) "type"
4 WHITESPACE@[4; 5) " " 4 WHITESPACE@[4; 5) " "
5 NAME@[5; 6) 5 NAME@[5; 6)
@@ -7,75 +7,54 @@ SOURCE_FILE@[0; 54)
7 WHITESPACE@[6; 7) " " 7 WHITESPACE@[6; 7) " "
8 EQ@[7; 8) "=" 8 EQ@[7; 8) "="
9 WHITESPACE@[8; 9) " " 9 WHITESPACE@[8; 9) " "
10 PATH_TYPE@[9; 52) 10 PATH_TYPE@[9; 37)
11 PATH@[9; 52) 11 PATH@[9; 37)
12 PATH_SEGMENT@[9; 52) 12 PATH_SEGMENT@[9; 37)
13 NAME_REF@[9; 12) 13 NAME_REF@[9; 12)
14 IDENT@[9; 12) "Box" 14 IDENT@[9; 12) "Box"
15 TYPE_ARG_LIST@[12; 52) 15 TYPE_ARG_LIST@[12; 37)
16 L_ANGLE@[12; 13) "<" 16 L_ANGLE@[12; 13) "<"
17 TYPE_ARG@[13; 51) 17 TYPE_ARG@[13; 36)
18 PATH_TYPE@[13; 51) 18 PATH_TYPE@[13; 36)
19 PATH@[13; 51) 19 PATH@[13; 36)
20 PATH_SEGMENT@[13; 51) 20 PATH_SEGMENT@[13; 36)
21 NAME_REF@[13; 15) 21 NAME_REF@[13; 15)
22 IDENT@[13; 15) "Fn" 22 IDENT@[13; 15) "Fn"
23 PARAM_LIST@[15; 51) 23 PARAM_LIST@[15; 36)
24 L_PAREN@[15; 16) "(" 24 L_PAREN@[15; 16) "("
25 PARAM@[16; 22) 25 PARAM@[16; 19)
26 BIND_PAT@[16; 17) 26 PATH_TYPE@[16; 19)
27 NAME@[16; 17) 27 PATH@[16; 19)
28 IDENT@[16; 17) "a" 28 PATH_SEGMENT@[16; 19)
29 COLON@[17; 18) ":" 29 NAME_REF@[16; 19)
30 WHITESPACE@[18; 19) " " 30 IDENT@[16; 19) "i32"
31 PATH_TYPE@[19; 22) 31 COMMA@[19; 20) ","
32 PATH@[19; 22) 32 WHITESPACE@[20; 21) " "
33 PATH_SEGMENT@[19; 22) 33 PARAM@[21; 25)
34 NAME_REF@[19; 22) 34 REFERENCE_TYPE@[21; 25)
35 IDENT@[19; 22) "i32" 35 AMP@[21; 22) "&"
36 COMMA@[22; 23) "," 36 PATH_TYPE@[22; 25)
37 WHITESPACE@[23; 24) " " 37 PATH@[22; 25)
38 PARAM@[24; 32) 38 PATH_SEGMENT@[22; 25)
39 REF_PAT@[24; 26) 39 NAME_REF@[22; 25)
40 AMP@[24; 25) "&" 40 IDENT@[22; 25) "i32"
41 BIND_PAT@[25; 26) 41 COMMA@[25; 26) ","
42 NAME@[25; 26) 42 WHITESPACE@[26; 27) " "
43 IDENT@[25; 26) "b" 43 PARAM@[27; 31)
44 COLON@[26; 27) ":" 44 REFERENCE_TYPE@[27; 31)
45 WHITESPACE@[27; 28) " " 45 AMP@[27; 28) "&"
46 REFERENCE_TYPE@[28; 32) 46 PATH_TYPE@[28; 31)
47 AMP@[28; 29) "&" 47 PATH@[28; 31)
48 PATH_TYPE@[29; 32) 48 PATH_SEGMENT@[28; 31)
49 PATH@[29; 32) 49 NAME_REF@[28; 31)
50 PATH_SEGMENT@[29; 32) 50 IDENT@[28; 31) "i32"
51 NAME_REF@[29; 32) 51 COMMA@[31; 32) ","
52 IDENT@[29; 32) "i32" 52 WHITESPACE@[32; 33) " "
53 COMMA@[32; 33) "," 53 PARAM@[33; 35)
54 WHITESPACE@[33; 34) " " 54 TUPLE_TYPE@[33; 35)
55 PARAM@[34; 46) 55 L_PAREN@[33; 34) "("
56 REF_PAT@[34; 40) 56 R_PAREN@[34; 35) ")"
57 AMP@[34; 35) "&" 57 R_PAREN@[35; 36) ")"
58 MUT_KW@[35; 38) "mut" 58 R_ANGLE@[36; 37) ">"
59 WHITESPACE@[38; 39) " " 59 SEMI@[37; 38) ";"
60 BIND_PAT@[39; 40) 60 WHITESPACE@[38; 39) "\n"
61 NAME@[39; 40)
62 IDENT@[39; 40) "c"
63 COLON@[40; 41) ":"
64 WHITESPACE@[41; 42) " "
65 REFERENCE_TYPE@[42; 46)
66 AMP@[42; 43) "&"
67 PATH_TYPE@[43; 46)
68 PATH@[43; 46)
69 PATH_SEGMENT@[43; 46)
70 NAME_REF@[43; 46)
71 IDENT@[43; 46) "i32"
72 COMMA@[46; 47) ","
73 WHITESPACE@[47; 48) " "
74 PARAM@[48; 50)
75 TUPLE_TYPE@[48; 50)
76 L_PAREN@[48; 49) "("
77 R_PAREN@[49; 50) ")"
78 R_PAREN@[50; 51) ")"
79 R_ANGLE@[51; 52) ">"
80 SEMI@[52; 53) ";"
81 WHITESPACE@[53; 54) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs b/crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs
index aef45e561..17ed20e5b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs
@@ -1 +1 @@
type F = Box<Fn(x: i32) -> ()>; type F = Box<Fn(i32) -> ()>;
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.txt b/crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.txt
index d6f196811..a983d5954 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 32) 1SOURCE_FILE@[0; 29)
2 TYPE_ALIAS_DEF@[0; 31) 2 TYPE_ALIAS_DEF@[0; 28)
3 TYPE_KW@[0; 4) "type" 3 TYPE_KW@[0; 4) "type"
4 WHITESPACE@[4; 5) " " 4 WHITESPACE@[4; 5) " "
5 NAME@[5; 6) 5 NAME@[5; 6)
@@ -7,40 +7,35 @@ SOURCE_FILE@[0; 32)
7 WHITESPACE@[6; 7) " " 7 WHITESPACE@[6; 7) " "
8 EQ@[7; 8) "=" 8 EQ@[7; 8) "="
9 WHITESPACE@[8; 9) " " 9 WHITESPACE@[8; 9) " "
10 PATH_TYPE@[9; 30) 10 PATH_TYPE@[9; 27)
11 PATH@[9; 30) 11 PATH@[9; 27)
12 PATH_SEGMENT@[9; 30) 12 PATH_SEGMENT@[9; 27)
13 NAME_REF@[9; 12) 13 NAME_REF@[9; 12)
14 IDENT@[9; 12) "Box" 14 IDENT@[9; 12) "Box"
15 TYPE_ARG_LIST@[12; 30) 15 TYPE_ARG_LIST@[12; 27)
16 L_ANGLE@[12; 13) "<" 16 L_ANGLE@[12; 13) "<"
17 TYPE_ARG@[13; 29) 17 TYPE_ARG@[13; 26)
18 PATH_TYPE@[13; 29) 18 PATH_TYPE@[13; 26)
19 PATH@[13; 29) 19 PATH@[13; 26)
20 PATH_SEGMENT@[13; 29) 20 PATH_SEGMENT@[13; 26)
21 NAME_REF@[13; 15) 21 NAME_REF@[13; 15)
22 IDENT@[13; 15) "Fn" 22 IDENT@[13; 15) "Fn"
23 PARAM_LIST@[15; 23) 23 PARAM_LIST@[15; 20)
24 L_PAREN@[15; 16) "(" 24 L_PAREN@[15; 16) "("
25 PARAM@[16; 22) 25 PARAM@[16; 19)
26 BIND_PAT@[16; 17) 26 PATH_TYPE@[16; 19)
27 NAME@[16; 17) 27 PATH@[16; 19)
28 IDENT@[16; 17) "x" 28 PATH_SEGMENT@[16; 19)
29 COLON@[17; 18) ":" 29 NAME_REF@[16; 19)
30 WHITESPACE@[18; 19) " " 30 IDENT@[16; 19) "i32"
31 PATH_TYPE@[19; 22) 31 R_PAREN@[19; 20) ")"
32 PATH@[19; 22) 32 WHITESPACE@[20; 21) " "
33 PATH_SEGMENT@[19; 22) 33 RET_TYPE@[21; 26)
34 NAME_REF@[19; 22) 34 THIN_ARROW@[21; 23) "->"
35 IDENT@[19; 22) "i32" 35 WHITESPACE@[23; 24) " "
36 R_PAREN@[22; 23) ")" 36 TUPLE_TYPE@[24; 26)
37 WHITESPACE@[23; 24) " " 37 L_PAREN@[24; 25) "("
38 RET_TYPE@[24; 29) 38 R_PAREN@[25; 26) ")"
39 THIN_ARROW@[24; 26) "->" 39 R_ANGLE@[26; 27) ">"
40 WHITESPACE@[26; 27) " " 40 SEMI@[27; 28) ";"
41 TUPLE_TYPE@[27; 29) 41 WHITESPACE@[28; 29) "\n"
42 L_PAREN@[27; 28) "("
43 R_PAREN@[28; 29) ")"
44 R_ANGLE@[29; 30) ">"
45 SEMI@[30; 31) ";"
46 WHITESPACE@[31; 32) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0152_fn_patterns.rs b/crates/ra_syntax/test_data/parser/inline/ok/0152_fn_patterns.rs
new file mode 100644
index 000000000..b49e872d7
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0152_fn_patterns.rs
@@ -0,0 +1,6 @@
1impl U {
2 fn f1((a, b): (usize, usize)) {}
3 fn f2(S { a, b }: S) {}
4 fn f3(NewType(a): NewType) {}
5 fn f4(&&a: &&usize) {}
6}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0152_fn_patterns.txt b/crates/ra_syntax/test_data/parser/inline/ok/0152_fn_patterns.txt
new file mode 100644
index 000000000..933f5b7bd
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0152_fn_patterns.txt
@@ -0,0 +1,164 @@
1SOURCE_FILE@[0; 137)
2 IMPL_BLOCK@[0; 136)
3 IMPL_KW@[0; 4) "impl"
4 WHITESPACE@[4; 5) " "
5 PATH_TYPE@[5; 6)
6 PATH@[5; 6)
7 PATH_SEGMENT@[5; 6)
8 NAME_REF@[5; 6)
9 IDENT@[5; 6) "U"
10 WHITESPACE@[6; 7) " "
11 ITEM_LIST@[7; 136)
12 L_CURLY@[7; 8) "{"
13 WHITESPACE@[8; 13) "\n "
14 FN_DEF@[13; 45)
15 FN_KW@[13; 15) "fn"
16 WHITESPACE@[15; 16) " "
17 NAME@[16; 18)
18 IDENT@[16; 18) "f1"
19 PARAM_LIST@[18; 42)
20 L_PAREN@[18; 19) "("
21 PARAM@[19; 41)
22 TUPLE_PAT@[19; 25)
23 L_PAREN@[19; 20) "("
24 BIND_PAT@[20; 21)
25 NAME@[20; 21)
26 IDENT@[20; 21) "a"
27 COMMA@[21; 22) ","
28 WHITESPACE@[22; 23) " "
29 BIND_PAT@[23; 24)
30 NAME@[23; 24)
31 IDENT@[23; 24) "b"
32 R_PAREN@[24; 25) ")"
33 COLON@[25; 26) ":"
34 WHITESPACE@[26; 27) " "
35 TUPLE_TYPE@[27; 41)
36 L_PAREN@[27; 28) "("
37 PATH_TYPE@[28; 33)
38 PATH@[28; 33)
39 PATH_SEGMENT@[28; 33)
40 NAME_REF@[28; 33)
41 IDENT@[28; 33) "usize"
42 COMMA@[33; 34) ","
43 WHITESPACE@[34; 35) " "
44 PATH_TYPE@[35; 40)
45 PATH@[35; 40)
46 PATH_SEGMENT@[35; 40)
47 NAME_REF@[35; 40)
48 IDENT@[35; 40) "usize"
49 R_PAREN@[40; 41) ")"
50 R_PAREN@[41; 42) ")"
51 WHITESPACE@[42; 43) " "
52 BLOCK_EXPR@[43; 45)
53 BLOCK@[43; 45)
54 L_CURLY@[43; 44) "{"
55 R_CURLY@[44; 45) "}"
56 WHITESPACE@[45; 50) "\n "
57 FN_DEF@[50; 73)
58 FN_KW@[50; 52) "fn"
59 WHITESPACE@[52; 53) " "
60 NAME@[53; 55)
61 IDENT@[53; 55) "f2"
62 PARAM_LIST@[55; 70)
63 L_PAREN@[55; 56) "("
64 PARAM@[56; 69)
65 RECORD_PAT@[56; 66)
66 PATH@[56; 57)
67 PATH_SEGMENT@[56; 57)
68 NAME_REF@[56; 57)
69 IDENT@[56; 57) "S"
70 WHITESPACE@[57; 58) " "
71 RECORD_FIELD_PAT_LIST@[58; 66)
72 L_CURLY@[58; 59) "{"
73 WHITESPACE@[59; 60) " "
74 BIND_PAT@[60; 61)
75 NAME@[60; 61)
76 IDENT@[60; 61) "a"
77 COMMA@[61; 62) ","
78 WHITESPACE@[62; 63) " "
79 BIND_PAT@[63; 64)
80 NAME@[63; 64)
81 IDENT@[63; 64) "b"
82 WHITESPACE@[64; 65) " "
83 R_CURLY@[65; 66) "}"
84 COLON@[66; 67) ":"
85 WHITESPACE@[67; 68) " "
86 PATH_TYPE@[68; 69)
87 PATH@[68; 69)
88 PATH_SEGMENT@[68; 69)
89 NAME_REF@[68; 69)
90 IDENT@[68; 69) "S"
91 R_PAREN@[69; 70) ")"
92 WHITESPACE@[70; 71) " "
93 BLOCK_EXPR@[71; 73)
94 BLOCK@[71; 73)
95 L_CURLY@[71; 72) "{"
96 R_CURLY@[72; 73) "}"
97 WHITESPACE@[73; 78) "\n "
98 FN_DEF@[78; 107)
99 FN_KW@[78; 80) "fn"
100 WHITESPACE@[80; 81) " "
101 NAME@[81; 83)
102 IDENT@[81; 83) "f3"
103 PARAM_LIST@[83; 104)
104 L_PAREN@[83; 84) "("
105 PARAM@[84; 103)
106 TUPLE_STRUCT_PAT@[84; 94)
107 PATH@[84; 91)
108 PATH_SEGMENT@[84; 91)
109 NAME_REF@[84; 91)
110 IDENT@[84; 91) "NewType"
111 L_PAREN@[91; 92) "("
112 BIND_PAT@[92; 93)
113 NAME@[92; 93)
114 IDENT@[92; 93) "a"
115 R_PAREN@[93; 94) ")"
116 COLON@[94; 95) ":"
117 WHITESPACE@[95; 96) " "
118 PATH_TYPE@[96; 103)
119 PATH@[96; 103)
120 PATH_SEGMENT@[96; 103)
121 NAME_REF@[96; 103)
122 IDENT@[96; 103) "NewType"
123 R_PAREN@[103; 104) ")"
124 WHITESPACE@[104; 105) " "
125 BLOCK_EXPR@[105; 107)
126 BLOCK@[105; 107)
127 L_CURLY@[105; 106) "{"
128 R_CURLY@[106; 107) "}"
129 WHITESPACE@[107; 112) "\n "
130 FN_DEF@[112; 134)
131 FN_KW@[112; 114) "fn"
132 WHITESPACE@[114; 115) " "
133 NAME@[115; 117)
134 IDENT@[115; 117) "f4"
135 PARAM_LIST@[117; 131)
136 L_PAREN@[117; 118) "("
137 PARAM@[118; 130)
138 REF_PAT@[118; 121)
139 AMP@[118; 119) "&"
140 REF_PAT@[119; 121)
141 AMP@[119; 120) "&"
142 BIND_PAT@[120; 121)
143 NAME@[120; 121)
144 IDENT@[120; 121) "a"
145 COLON@[121; 122) ":"
146 WHITESPACE@[122; 123) " "
147 REFERENCE_TYPE@[123; 130)
148 AMP@[123; 124) "&"
149 REFERENCE_TYPE@[124; 130)
150 AMP@[124; 125) "&"
151 PATH_TYPE@[125; 130)
152 PATH@[125; 130)
153 PATH_SEGMENT@[125; 130)
154 NAME_REF@[125; 130)
155 IDENT@[125; 130) "usize"
156 R_PAREN@[130; 131) ")"
157 WHITESPACE@[131; 132) " "
158 BLOCK_EXPR@[132; 134)
159 BLOCK@[132; 134)
160 L_CURLY@[132; 133) "{"
161 R_CURLY@[133; 134) "}"
162 WHITESPACE@[134; 135) "\n"
163 R_CURLY@[135; 136) "}"
164 WHITESPACE@[136; 137) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0153_trait_fn_patterns.rs b/crates/ra_syntax/test_data/parser/inline/ok/0153_trait_fn_patterns.rs
new file mode 100644
index 000000000..a94bf378a
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0153_trait_fn_patterns.rs
@@ -0,0 +1,6 @@
1trait T {
2 fn f1((a, b): (usize, usize)) {}
3 fn f2(S { a, b }: S) {}
4 fn f3(NewType(a): NewType) {}
5 fn f4(&&a: &&usize) {}
6}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0153_trait_fn_patterns.txt b/crates/ra_syntax/test_data/parser/inline/ok/0153_trait_fn_patterns.txt
new file mode 100644
index 000000000..b22df8dbe
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0153_trait_fn_patterns.txt
@@ -0,0 +1,161 @@
1SOURCE_FILE@[0; 138)
2 TRAIT_DEF@[0; 137)
3 TRAIT_KW@[0; 5) "trait"
4 WHITESPACE@[5; 6) " "
5 NAME@[6; 7)
6 IDENT@[6; 7) "T"
7 WHITESPACE@[7; 8) " "
8 ITEM_LIST@[8; 137)
9 L_CURLY@[8; 9) "{"
10 WHITESPACE@[9; 14) "\n "
11 FN_DEF@[14; 46)
12 FN_KW@[14; 16) "fn"
13 WHITESPACE@[16; 17) " "
14 NAME@[17; 19)
15 IDENT@[17; 19) "f1"
16 PARAM_LIST@[19; 43)
17 L_PAREN@[19; 20) "("
18 PARAM@[20; 42)
19 TUPLE_PAT@[20; 26)
20 L_PAREN@[20; 21) "("
21 BIND_PAT@[21; 22)
22 NAME@[21; 22)
23 IDENT@[21; 22) "a"
24 COMMA@[22; 23) ","
25 WHITESPACE@[23; 24) " "
26 BIND_PAT@[24; 25)
27 NAME@[24; 25)
28 IDENT@[24; 25) "b"
29 R_PAREN@[25; 26) ")"
30 COLON@[26; 27) ":"
31 WHITESPACE@[27; 28) " "
32 TUPLE_TYPE@[28; 42)
33 L_PAREN@[28; 29) "("
34 PATH_TYPE@[29; 34)
35 PATH@[29; 34)
36 PATH_SEGMENT@[29; 34)
37 NAME_REF@[29; 34)
38 IDENT@[29; 34) "usize"
39 COMMA@[34; 35) ","
40 WHITESPACE@[35; 36) " "
41 PATH_TYPE@[36; 41)
42 PATH@[36; 41)
43 PATH_SEGMENT@[36; 41)
44 NAME_REF@[36; 41)
45 IDENT@[36; 41) "usize"
46 R_PAREN@[41; 42) ")"
47 R_PAREN@[42; 43) ")"
48 WHITESPACE@[43; 44) " "
49 BLOCK_EXPR@[44; 46)
50 BLOCK@[44; 46)
51 L_CURLY@[44; 45) "{"
52 R_CURLY@[45; 46) "}"
53 WHITESPACE@[46; 51) "\n "
54 FN_DEF@[51; 74)
55 FN_KW@[51; 53) "fn"
56 WHITESPACE@[53; 54) " "
57 NAME@[54; 56)
58 IDENT@[54; 56) "f2"
59 PARAM_LIST@[56; 71)
60 L_PAREN@[56; 57) "("
61 PARAM@[57; 70)
62 RECORD_PAT@[57; 67)
63 PATH@[57; 58)
64 PATH_SEGMENT@[57; 58)
65 NAME_REF@[57; 58)
66 IDENT@[57; 58) "S"
67 WHITESPACE@[58; 59) " "
68 RECORD_FIELD_PAT_LIST@[59; 67)
69 L_CURLY@[59; 60) "{"
70 WHITESPACE@[60; 61) " "
71 BIND_PAT@[61; 62)
72 NAME@[61; 62)
73 IDENT@[61; 62) "a"
74 COMMA@[62; 63) ","
75 WHITESPACE@[63; 64) " "
76 BIND_PAT@[64; 65)
77 NAME@[64; 65)
78 IDENT@[64; 65) "b"
79 WHITESPACE@[65; 66) " "
80 R_CURLY@[66; 67) "}"
81 COLON@[67; 68) ":"
82 WHITESPACE@[68; 69) " "
83 PATH_TYPE@[69; 70)
84 PATH@[69; 70)
85 PATH_SEGMENT@[69; 70)
86 NAME_REF@[69; 70)
87 IDENT@[69; 70) "S"
88 R_PAREN@[70; 71) ")"
89 WHITESPACE@[71; 72) " "
90 BLOCK_EXPR@[72; 74)
91 BLOCK@[72; 74)
92 L_CURLY@[72; 73) "{"
93 R_CURLY@[73; 74) "}"
94 WHITESPACE@[74; 79) "\n "
95 FN_DEF@[79; 108)
96 FN_KW@[79; 81) "fn"
97 WHITESPACE@[81; 82) " "
98 NAME@[82; 84)
99 IDENT@[82; 84) "f3"
100 PARAM_LIST@[84; 105)
101 L_PAREN@[84; 85) "("
102 PARAM@[85; 104)
103 TUPLE_STRUCT_PAT@[85; 95)
104 PATH@[85; 92)
105 PATH_SEGMENT@[85; 92)
106 NAME_REF@[85; 92)
107 IDENT@[85; 92) "NewType"
108 L_PAREN@[92; 93) "("
109 BIND_PAT@[93; 94)
110 NAME@[93; 94)
111 IDENT@[93; 94) "a"
112 R_PAREN@[94; 95) ")"
113 COLON@[95; 96) ":"
114 WHITESPACE@[96; 97) " "
115 PATH_TYPE@[97; 104)
116 PATH@[97; 104)
117 PATH_SEGMENT@[97; 104)
118 NAME_REF@[97; 104)
119 IDENT@[97; 104) "NewType"
120 R_PAREN@[104; 105) ")"
121 WHITESPACE@[105; 106) " "
122 BLOCK_EXPR@[106; 108)
123 BLOCK@[106; 108)
124 L_CURLY@[106; 107) "{"
125 R_CURLY@[107; 108) "}"
126 WHITESPACE@[108; 113) "\n "
127 FN_DEF@[113; 135)
128 FN_KW@[113; 115) "fn"
129 WHITESPACE@[115; 116) " "
130 NAME@[116; 118)
131 IDENT@[116; 118) "f4"
132 PARAM_LIST@[118; 132)
133 L_PAREN@[118; 119) "("
134 PARAM@[119; 131)
135 REF_PAT@[119; 122)
136 AMP@[119; 120) "&"
137 REF_PAT@[120; 122)
138 AMP@[120; 121) "&"
139 BIND_PAT@[121; 122)
140 NAME@[121; 122)
141 IDENT@[121; 122) "a"
142 COLON@[122; 123) ":"
143 WHITESPACE@[123; 124) " "
144 REFERENCE_TYPE@[124; 131)
145 AMP@[124; 125) "&"
146 REFERENCE_TYPE@[125; 131)
147 AMP@[125; 126) "&"
148 PATH_TYPE@[126; 131)
149 PATH@[126; 131)
150 PATH_SEGMENT@[126; 131)
151 NAME_REF@[126; 131)
152 IDENT@[126; 131) "usize"
153 R_PAREN@[131; 132) ")"
154 WHITESPACE@[132; 133) " "
155 BLOCK_EXPR@[133; 135)
156 BLOCK@[133; 135)
157 L_CURLY@[133; 134) "{"
158 R_CURLY@[134; 135) "}"
159 WHITESPACE@[135; 136) "\n"
160 R_CURLY@[136; 137) "}"
161 WHITESPACE@[137; 138) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs b/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs
new file mode 100644
index 000000000..80a1701fd
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs
@@ -0,0 +1,2 @@
1type Foo = fn(Bar::Baz);
2type Qux = fn(baz: Bar::Baz);
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.txt b/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.txt
new file mode 100644
index 000000000..cb686854a
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.txt
@@ -0,0 +1,58 @@
1SOURCE_FILE@[0; 55)
2 TYPE_ALIAS_DEF@[0; 24)
3 TYPE_KW@[0; 4) "type"
4 WHITESPACE@[4; 5) " "
5 NAME@[5; 8)
6 IDENT@[5; 8) "Foo"
7 WHITESPACE@[8; 9) " "
8 EQ@[9; 10) "="
9 WHITESPACE@[10; 11) " "
10 FN_POINTER_TYPE@[11; 23)
11 FN_KW@[11; 13) "fn"
12 PARAM_LIST@[13; 23)
13 L_PAREN@[13; 14) "("
14 PARAM@[14; 22)
15 PATH_TYPE@[14; 22)
16 PATH@[14; 22)
17 PATH@[14; 17)
18 PATH_SEGMENT@[14; 17)
19 NAME_REF@[14; 17)
20 IDENT@[14; 17) "Bar"
21 COLONCOLON@[17; 19) "::"
22 PATH_SEGMENT@[19; 22)
23 NAME_REF@[19; 22)
24 IDENT@[19; 22) "Baz"
25 R_PAREN@[22; 23) ")"
26 SEMI@[23; 24) ";"
27 WHITESPACE@[24; 25) "\n"
28 TYPE_ALIAS_DEF@[25; 54)
29 TYPE_KW@[25; 29) "type"
30 WHITESPACE@[29; 30) " "
31 NAME@[30; 33)
32 IDENT@[30; 33) "Qux"
33 WHITESPACE@[33; 34) " "
34 EQ@[34; 35) "="
35 WHITESPACE@[35; 36) " "
36 FN_POINTER_TYPE@[36; 53)
37 FN_KW@[36; 38) "fn"
38 PARAM_LIST@[38; 53)
39 L_PAREN@[38; 39) "("
40 PARAM@[39; 52)
41 BIND_PAT@[39; 42)
42 NAME@[39; 42)
43 IDENT@[39; 42) "baz"
44 COLON@[42; 43) ":"
45 WHITESPACE@[43; 44) " "
46 PATH_TYPE@[44; 52)
47 PATH@[44; 52)
48 PATH@[44; 47)
49 PATH_SEGMENT@[44; 47)
50 NAME_REF@[44; 47)
51 IDENT@[44; 47) "Bar"
52 COLONCOLON@[47; 49) "::"
53 PATH_SEGMENT@[49; 52)
54 NAME_REF@[49; 52)
55 IDENT@[49; 52) "Baz"
56 R_PAREN@[52; 53) ")"
57 SEMI@[53; 54) ";"
58 WHITESPACE@[54; 55) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rs b/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rs
new file mode 100644
index 000000000..6ca8dd2d6
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rs
@@ -0,0 +1,3 @@
1fn main() {
2 let foo = |bar, baz: Baz, qux: Qux::Quux| ();
3}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.txt b/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.txt
new file mode 100644
index 000000000..98727ae98
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.txt
@@ -0,0 +1,70 @@
1SOURCE_FILE@[0; 63)
2 FN_DEF@[0; 62)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 7)
6 IDENT@[3; 7) "main"
7 PARAM_LIST@[7; 9)
8 L_PAREN@[7; 8) "("
9 R_PAREN@[8; 9) ")"
10 WHITESPACE@[9; 10) " "
11 BLOCK_EXPR@[10; 62)
12 BLOCK@[10; 62)
13 L_CURLY@[10; 11) "{"
14 WHITESPACE@[11; 15) "\n "
15 LET_STMT@[15; 60)
16 LET_KW@[15; 18) "let"
17 WHITESPACE@[18; 19) " "
18 BIND_PAT@[19; 22)
19 NAME@[19; 22)
20 IDENT@[19; 22) "foo"
21 WHITESPACE@[22; 23) " "
22 EQ@[23; 24) "="
23 WHITESPACE@[24; 25) " "
24 LAMBDA_EXPR@[25; 59)
25 PARAM_LIST@[25; 56)
26 PIPE@[25; 26) "|"
27 PARAM@[26; 29)
28 BIND_PAT@[26; 29)
29 NAME@[26; 29)
30 IDENT@[26; 29) "bar"
31 COMMA@[29; 30) ","
32 WHITESPACE@[30; 31) " "
33 PARAM@[31; 39)
34 BIND_PAT@[31; 34)
35 NAME@[31; 34)
36 IDENT@[31; 34) "baz"
37 COLON@[34; 35) ":"
38 WHITESPACE@[35; 36) " "
39 PATH_TYPE@[36; 39)
40 PATH@[36; 39)
41 PATH_SEGMENT@[36; 39)
42 NAME_REF@[36; 39)
43 IDENT@[36; 39) "Baz"
44 COMMA@[39; 40) ","
45 WHITESPACE@[40; 41) " "
46 PARAM@[41; 55)
47 BIND_PAT@[41; 44)
48 NAME@[41; 44)
49 IDENT@[41; 44) "qux"
50 COLON@[44; 45) ":"
51 WHITESPACE@[45; 46) " "
52 PATH_TYPE@[46; 55)
53 PATH@[46; 55)
54 PATH@[46; 49)
55 PATH_SEGMENT@[46; 49)
56 NAME_REF@[46; 49)
57 IDENT@[46; 49) "Qux"
58 COLONCOLON@[49; 51) "::"
59 PATH_SEGMENT@[51; 55)
60 NAME_REF@[51; 55)
61 IDENT@[51; 55) "Quux"
62 PIPE@[55; 56) "|"
63 WHITESPACE@[56; 57) " "
64 TUPLE_EXPR@[57; 59)
65 L_PAREN@[57; 58) "("
66 R_PAREN@[58; 59) ")"
67 SEMI@[59; 60) ";"
68 WHITESPACE@[60; 61) "\n"
69 R_CURLY@[61; 62) "}"
70 WHITESPACE@[62; 63) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0030_traits.rs b/crates/ra_syntax/test_data/parser/ok/0030_traits.rs
index 23c4be0e1..ac30843ef 100644
--- a/crates/ra_syntax/test_data/parser/ok/0030_traits.rs
+++ b/crates/ra_syntax/test_data/parser/ok/0030_traits.rs
@@ -1,7 +1,3 @@
1pub trait WriteMessage {
2 fn write_message(&FrontendMessage);
3}
4
5trait Runnable { 1trait Runnable {
6 fn handler(); 2 fn handler();
7} 3}
diff --git a/crates/ra_syntax/test_data/parser/ok/0030_traits.txt b/crates/ra_syntax/test_data/parser/ok/0030_traits.txt
index b656c1a81..ac314ae50 100644
--- a/crates/ra_syntax/test_data/parser/ok/0030_traits.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0030_traits.txt
@@ -1,93 +1,61 @@
1SOURCE_FILE@[0; 164) 1SOURCE_FILE@[0; 96)
2 TRAIT_DEF@[0; 66) 2 TRAIT_DEF@[0; 36)
3 VISIBILITY@[0; 3) 3 TRAIT_KW@[0; 5) "trait"
4 PUB_KW@[0; 3) "pub" 4 WHITESPACE@[5; 6) " "
5 WHITESPACE@[3; 4) " " 5 NAME@[6; 14)
6 TRAIT_KW@[4; 9) "trait" 6 IDENT@[6; 14) "Runnable"
7 WHITESPACE@[9; 10) " " 7 WHITESPACE@[14; 15) " "
8 NAME@[10; 22) 8 ITEM_LIST@[15; 36)
9 IDENT@[10; 22) "WriteMessage" 9 L_CURLY@[15; 16) "{"
10 WHITESPACE@[22; 23) " " 10 WHITESPACE@[16; 21) "\n "
11 ITEM_LIST@[23; 66) 11 FN_DEF@[21; 34)
12 L_CURLY@[23; 24) "{" 12 FN_KW@[21; 23) "fn"
13 WHITESPACE@[24; 29) "\n " 13 WHITESPACE@[23; 24) " "
14 FN_DEF@[29; 64) 14 NAME@[24; 31)
15 FN_KW@[29; 31) "fn" 15 IDENT@[24; 31) "handler"
16 WHITESPACE@[31; 32) " " 16 PARAM_LIST@[31; 33)
17 NAME@[32; 45) 17 L_PAREN@[31; 32) "("
18 IDENT@[32; 45) "write_message" 18 R_PAREN@[32; 33) ")"
19 PARAM_LIST@[45; 63) 19 SEMI@[33; 34) ";"
20 L_PAREN@[45; 46) "(" 20 WHITESPACE@[34; 35) "\n"
21 PARAM@[46; 62) 21 R_CURLY@[35; 36) "}"
22 REFERENCE_TYPE@[46; 62) 22 WHITESPACE@[36; 38) "\n\n"
23 AMP@[46; 47) "&" 23 TRAIT_DEF@[38; 95)
24 PATH_TYPE@[47; 62) 24 TRAIT_KW@[38; 43) "trait"
25 PATH@[47; 62) 25 WHITESPACE@[43; 44) " "
26 PATH_SEGMENT@[47; 62) 26 NAME@[44; 57)
27 NAME_REF@[47; 62) 27 IDENT@[44; 57) "TraitWithExpr"
28 IDENT@[47; 62) "FrontendMessage" 28 WHITESPACE@[57; 58) " "
29 R_PAREN@[62; 63) ")" 29 ITEM_LIST@[58; 95)
30 SEMI@[63; 64) ";" 30 L_CURLY@[58; 59) "{"
31 WHITESPACE@[64; 65) "\n" 31 WHITESPACE@[59; 64) "\n "
32 R_CURLY@[65; 66) "}" 32 FN_DEF@[64; 93)
33 WHITESPACE@[66; 68) "\n\n" 33 FN_KW@[64; 66) "fn"
34 TRAIT_DEF@[68; 104) 34 WHITESPACE@[66; 67) " "
35 TRAIT_KW@[68; 73) "trait" 35 NAME@[67; 79)
36 WHITESPACE@[73; 74) " " 36 IDENT@[67; 79) "fn_with_expr"
37 NAME@[74; 82) 37 PARAM_LIST@[79; 92)
38 IDENT@[74; 82) "Runnable" 38 L_PAREN@[79; 80) "("
39 WHITESPACE@[82; 83) " " 39 PARAM@[80; 91)
40 ITEM_LIST@[83; 104) 40 BIND_PAT@[80; 81)
41 L_CURLY@[83; 84) "{" 41 NAME@[80; 81)
42 WHITESPACE@[84; 89) "\n " 42 IDENT@[80; 81) "x"
43 FN_DEF@[89; 102) 43 COLON@[81; 82) ":"
44 FN_KW@[89; 91) "fn" 44 WHITESPACE@[82; 83) " "
45 WHITESPACE@[91; 92) " " 45 ARRAY_TYPE@[83; 91)
46 NAME@[92; 99) 46 L_BRACK@[83; 84) "["
47 IDENT@[92; 99) "handler" 47 PATH_TYPE@[84; 87)
48 PARAM_LIST@[99; 101) 48 PATH@[84; 87)
49 L_PAREN@[99; 100) "(" 49 PATH_SEGMENT@[84; 87)
50 R_PAREN@[100; 101) ")" 50 NAME_REF@[84; 87)
51 SEMI@[101; 102) ";" 51 IDENT@[84; 87) "i32"
52 WHITESPACE@[102; 103) "\n" 52 SEMI@[87; 88) ";"
53 R_CURLY@[103; 104) "}" 53 WHITESPACE@[88; 89) " "
54 WHITESPACE@[104; 106) "\n\n" 54 LITERAL@[89; 90)
55 TRAIT_DEF@[106; 163) 55 INT_NUMBER@[89; 90) "1"
56 TRAIT_KW@[106; 111) "trait" 56 R_BRACK@[90; 91) "]"
57 WHITESPACE@[111; 112) " " 57 R_PAREN@[91; 92) ")"
58 NAME@[112; 125) 58 SEMI@[92; 93) ";"
59 IDENT@[112; 125) "TraitWithExpr" 59 WHITESPACE@[93; 94) "\n"
60 WHITESPACE@[125; 126) " " 60 R_CURLY@[94; 95) "}"
61 ITEM_LIST@[126; 163) 61 WHITESPACE@[95; 96) "\n"
62 L_CURLY@[126; 127) "{"
63 WHITESPACE@[127; 132) "\n "
64 FN_DEF@[132; 161)
65 FN_KW@[132; 134) "fn"
66 WHITESPACE@[134; 135) " "
67 NAME@[135; 147)
68 IDENT@[135; 147) "fn_with_expr"
69 PARAM_LIST@[147; 160)
70 L_PAREN@[147; 148) "("
71 PARAM@[148; 159)
72 BIND_PAT@[148; 149)
73 NAME@[148; 149)
74 IDENT@[148; 149) "x"
75 COLON@[149; 150) ":"
76 WHITESPACE@[150; 151) " "
77 ARRAY_TYPE@[151; 159)
78 L_BRACK@[151; 152) "["
79 PATH_TYPE@[152; 155)
80 PATH@[152; 155)
81 PATH_SEGMENT@[152; 155)
82 NAME_REF@[152; 155)
83 IDENT@[152; 155) "i32"
84 SEMI@[155; 156) ";"
85 WHITESPACE@[156; 157) " "
86 LITERAL@[157; 158)
87 INT_NUMBER@[157; 158) "1"
88 R_BRACK@[158; 159) "]"
89 R_PAREN@[159; 160) ")"
90 SEMI@[160; 161) ";"
91 WHITESPACE@[161; 162) "\n"
92 R_CURLY@[162; 163) "}"
93 WHITESPACE@[163; 164) "\n"