aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide_api/src/call_info.rs34
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs14
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs3
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt56
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}
173fn 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// }
195fn lambda_expr(p: &mut Parser) -> CompletedMarker { 199fn 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 @@
1SOURCE_FILE@[0; 79) 1SOURCE_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)