diff options
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 34 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions/atom.rs | 14 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/items.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt | 56 |
5 files changed, 94 insertions, 15 deletions
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index c5e8d5843..29fa7d30b 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -28,6 +28,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
28 | let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?; | 28 | let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?; |
29 | 29 | ||
30 | let mut call_info = CallInfo::new(db, function, fn_def)?; | 30 | let mut call_info = CallInfo::new(db, function, fn_def)?; |
31 | |||
31 | // If we have a calling expression let's find which argument we are on | 32 | // If we have a calling expression let's find which argument we are on |
32 | let num_params = call_info.parameters.len(); | 33 | let num_params = call_info.parameters.len(); |
33 | let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); | 34 | let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); |
@@ -38,18 +39,28 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
38 | } | 39 | } |
39 | } else if num_params > 1 { | 40 | } else if num_params > 1 { |
40 | // Count how many parameters into the call we are. | 41 | // Count how many parameters into the call we are. |
41 | if let Some(ref arg_list) = calling_node.arg_list() { | 42 | if let Some(arg_list) = calling_node.arg_list() { |
43 | // Number of arguments specified at the call site | ||
44 | let num_args_at_callsite = arg_list.args().count(); | ||
45 | |||
42 | let arg_list_range = arg_list.syntax().range(); | 46 | let arg_list_range = arg_list.syntax().range(); |
43 | if !arg_list_range.contains_inclusive(position.offset) { | 47 | if !arg_list_range.contains_inclusive(position.offset) { |
44 | tested_by!(call_info_bad_offset); | 48 | tested_by!(call_info_bad_offset); |
45 | return None; | 49 | return None; |
46 | } | 50 | } |
47 | 51 | ||
48 | let param = arg_list | 52 | let mut param = std::cmp::min( |
49 | .args() | 53 | num_args_at_callsite, |
50 | .position(|arg| arg.syntax().range().contains(position.offset)) | 54 | arg_list |
51 | .or(Some(num_params - 1)) | 55 | .args() |
52 | .unwrap(); | 56 | .take_while(|arg| arg.syntax().range().end() < position.offset) |
57 | .count(), | ||
58 | ); | ||
59 | |||
60 | // If we are in a method account for `self` | ||
61 | if has_self { | ||
62 | param = param + 1; | ||
63 | } | ||
53 | 64 | ||
54 | call_info.active_parameter = Some(param); | 65 | call_info.active_parameter = Some(param); |
55 | } | 66 | } |
@@ -156,6 +167,17 @@ fn bar() { foo(3, <|>); }"#, | |||
156 | } | 167 | } |
157 | 168 | ||
158 | #[test] | 169 | #[test] |
170 | fn test_fn_signature_two_args_empty() { | ||
171 | let info = call_info( | ||
172 | r#"fn foo(x: u32, y: u32) -> u32 {x + y} | ||
173 | fn bar() { foo(<|>); }"#, | ||
174 | ); | ||
175 | |||
176 | assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string())); | ||
177 | assert_eq!(info.active_parameter, Some(0)); | ||
178 | } | ||
179 | |||
180 | #[test] | ||
159 | fn test_fn_signature_for_impl() { | 181 | fn test_fn_signature_for_impl() { |
160 | let info = call_info( | 182 | let info = call_info( |
161 | r#"struct F; impl F { pub fn new() { F{}} } | 183 | r#"struct F; impl F { pub fn new() { F{}} } |
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index b82fa17cb..8dc7e44a9 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -69,6 +69,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar | |||
69 | L_BRACK => array_expr(p), | 69 | L_BRACK => array_expr(p), |
70 | PIPE => lambda_expr(p), | 70 | PIPE => lambda_expr(p), |
71 | MOVE_KW if la == PIPE => lambda_expr(p), | 71 | MOVE_KW if la == PIPE => lambda_expr(p), |
72 | ASYNC_KW if la == PIPE || (la == MOVE_KW && p.nth(2) == PIPE) => lambda_expr(p), | ||
72 | IF_KW => if_expr(p), | 73 | IF_KW => if_expr(p), |
73 | 74 | ||
74 | LOOP_KW => loop_expr(p, None), | 75 | LOOP_KW => loop_expr(p, None), |
@@ -93,7 +94,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar | |||
93 | } | 94 | } |
94 | } | 95 | } |
95 | } | 96 | } |
96 | ASYNC_KW if la == L_CURLY || la == MOVE_KW => { | 97 | ASYNC_KW if la == L_CURLY || (la == MOVE_KW && p.nth(2) == L_CURLY) => { |
97 | let m = p.start(); | 98 | let m = p.start(); |
98 | p.bump(); | 99 | p.bump(); |
99 | p.eat(MOVE_KW); | 100 | p.eat(MOVE_KW); |
@@ -191,10 +192,19 @@ fn array_expr(p: &mut Parser) -> CompletedMarker { | |||
191 | // || -> i32 { 92 }; | 192 | // || -> i32 { 92 }; |
192 | // |x| x; | 193 | // |x| x; |
193 | // move |x: i32,| x; | 194 | // move |x: i32,| x; |
195 | // async || {}; | ||
196 | // move || {}; | ||
197 | // async move || {}; | ||
194 | // } | 198 | // } |
195 | fn lambda_expr(p: &mut Parser) -> CompletedMarker { | 199 | fn lambda_expr(p: &mut Parser) -> CompletedMarker { |
196 | assert!(p.at(PIPE) || (p.at(MOVE_KW) && p.nth(1) == PIPE)); | 200 | assert!( |
201 | p.at(PIPE) | ||
202 | || (p.at(MOVE_KW) && p.nth(1) == PIPE) | ||
203 | || (p.at(ASYNC_KW) && p.nth(1) == PIPE) | ||
204 | || (p.at(ASYNC_KW) && p.nth(1) == MOVE_KW && p.nth(2) == PIPE) | ||
205 | ); | ||
197 | let m = p.start(); | 206 | let m = p.start(); |
207 | p.eat(ASYNC_KW); | ||
198 | p.eat(MOVE_KW); | 208 | p.eat(MOVE_KW); |
199 | params::param_list_opt_types(p); | 209 | params::param_list_opt_types(p); |
200 | if opt_fn_ret_type(p) { | 210 | if opt_fn_ret_type(p) { |
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 8d8828652..c4b8ef3c7 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs | |||
@@ -82,7 +82,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul | |||
82 | // test_err async_without_semicolon | 82 | // test_err async_without_semicolon |
83 | // fn foo() { let _ = async {} } | 83 | // fn foo() { let _ = async {} } |
84 | has_mods |= p.eat(CONST_KW); | 84 | has_mods |= p.eat(CONST_KW); |
85 | if p.at(ASYNC_KW) && p.nth(1) != L_CURLY && p.nth(1) != MOVE_KW { | 85 | if p.at(ASYNC_KW) && p.nth(1) != L_CURLY && p.nth(1) != MOVE_KW && p.nth(1) != PIPE { |
86 | p.eat(ASYNC_KW); | 86 | p.eat(ASYNC_KW); |
87 | has_mods = true; | 87 | has_mods = true; |
88 | } | 88 | } |
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs index c20d29751..075717823 100644 --- a/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs | |||
@@ -3,4 +3,7 @@ fn foo() { | |||
3 | || -> i32 { 92 }; | 3 | || -> i32 { 92 }; |
4 | |x| x; | 4 | |x| x; |
5 | move |x: i32,| x; | 5 | move |x: i32,| x; |
6 | async || {}; | ||
7 | move || {}; | ||
8 | async move || {}; | ||
6 | } | 9 | } |
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt index 98271c233..b885d239a 100644 --- a/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt | |||
@@ -1,5 +1,5 @@ | |||
1 | SOURCE_FILE@[0; 79) | 1 | SOURCE_FILE@[0; 134) |
2 | FN_DEF@[0; 78) | 2 | FN_DEF@[0; 133) |
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; 133) |
12 | L_CURLY@[9; 10) | 12 | L_CURLY@[9; 10) |
13 | WHITESPACE@[10; 15) | 13 | WHITESPACE@[10; 15) |
14 | EXPR_STMT@[15; 21) | 14 | EXPR_STMT@[15; 21) |
@@ -90,6 +90,50 @@ SOURCE_FILE@[0; 79) | |||
90 | NAME_REF@[74; 75) | 90 | NAME_REF@[74; 75) |
91 | IDENT@[74; 75) "x" | 91 | IDENT@[74; 75) "x" |
92 | SEMI@[75; 76) | 92 | SEMI@[75; 76) |
93 | WHITESPACE@[76; 77) | 93 | WHITESPACE@[76; 81) |
94 | R_CURLY@[77; 78) | 94 | EXPR_STMT@[81; 93) |
95 | WHITESPACE@[78; 79) | 95 | LAMBDA_EXPR@[81; 92) |
96 | ASYNC_KW@[81; 86) | ||
97 | WHITESPACE@[86; 87) | ||
98 | PARAM_LIST@[87; 89) | ||
99 | PIPE@[87; 88) | ||
100 | PIPE@[88; 89) | ||
101 | WHITESPACE@[89; 90) | ||
102 | BLOCK_EXPR@[90; 92) | ||
103 | BLOCK@[90; 92) | ||
104 | L_CURLY@[90; 91) | ||
105 | R_CURLY@[91; 92) | ||
106 | SEMI@[92; 93) | ||
107 | WHITESPACE@[93; 98) | ||
108 | EXPR_STMT@[98; 109) | ||
109 | LAMBDA_EXPR@[98; 108) | ||
110 | MOVE_KW@[98; 102) | ||
111 | WHITESPACE@[102; 103) | ||
112 | PARAM_LIST@[103; 105) | ||
113 | PIPE@[103; 104) | ||
114 | PIPE@[104; 105) | ||
115 | WHITESPACE@[105; 106) | ||
116 | BLOCK_EXPR@[106; 108) | ||
117 | BLOCK@[106; 108) | ||
118 | L_CURLY@[106; 107) | ||
119 | R_CURLY@[107; 108) | ||
120 | SEMI@[108; 109) | ||
121 | WHITESPACE@[109; 114) | ||
122 | EXPR_STMT@[114; 131) | ||
123 | LAMBDA_EXPR@[114; 130) | ||
124 | ASYNC_KW@[114; 119) | ||
125 | WHITESPACE@[119; 120) | ||
126 | MOVE_KW@[120; 124) | ||
127 | WHITESPACE@[124; 125) | ||
128 | PARAM_LIST@[125; 127) | ||
129 | PIPE@[125; 126) | ||
130 | PIPE@[126; 127) | ||
131 | WHITESPACE@[127; 128) | ||
132 | BLOCK_EXPR@[128; 130) | ||
133 | BLOCK@[128; 130) | ||
134 | L_CURLY@[128; 129) | ||
135 | R_CURLY@[129; 130) | ||
136 | SEMI@[130; 131) | ||
137 | WHITESPACE@[131; 132) | ||
138 | R_CURLY@[132; 133) | ||
139 | WHITESPACE@[133; 134) | ||