diff options
Diffstat (limited to 'crates/ra_ide_api/src/call_info.rs')
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 114 |
1 files changed, 75 insertions, 39 deletions
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index 29fa7d30b..dbb3853d0 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -6,9 +6,8 @@ use ra_syntax::{ | |||
6 | ast::{self, ArgListOwner}, | 6 | ast::{self, ArgListOwner}, |
7 | algo::find_node_at_offset, | 7 | algo::find_node_at_offset, |
8 | }; | 8 | }; |
9 | use hir::Docs; | ||
10 | 9 | ||
11 | use crate::{FilePosition, CallInfo, db::RootDatabase}; | 10 | use crate::{FilePosition, CallInfo, FunctionSignature, db::RootDatabase}; |
12 | 11 | ||
13 | /// Computes parameter information for the given call expression. | 12 | /// Computes parameter information for the given call expression. |
14 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { | 13 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { |
@@ -27,10 +26,10 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
27 | let fn_def = ast::FnDef::cast(fn_def).unwrap(); | 26 | let fn_def = ast::FnDef::cast(fn_def).unwrap(); |
28 | let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?; | 27 | let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?; |
29 | 28 | ||
30 | let mut call_info = CallInfo::new(db, function, fn_def)?; | 29 | let mut call_info = CallInfo::new(db, function); |
31 | 30 | ||
32 | // If we have a calling expression let's find which argument we are on | 31 | // If we have a calling expression let's find which argument we are on |
33 | let num_params = call_info.parameters.len(); | 32 | let num_params = call_info.parameters().len(); |
34 | let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); | 33 | let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); |
35 | 34 | ||
36 | if num_params == 1 { | 35 | if num_params == 1 { |
@@ -107,28 +106,15 @@ impl<'a> FnCallNode<'a> { | |||
107 | } | 106 | } |
108 | 107 | ||
109 | impl CallInfo { | 108 | impl CallInfo { |
110 | fn new(db: &RootDatabase, function: hir::Function, node: &ast::FnDef) -> Option<Self> { | 109 | fn new(db: &RootDatabase, function: hir::Function) -> Self { |
111 | let label = crate::completion::function_label(node)?; | 110 | let signature = FunctionSignature::from_hir(db, function); |
112 | let doc = function.docs(db); | ||
113 | 111 | ||
114 | Some(CallInfo { parameters: param_list(node), label, doc, active_parameter: None }) | 112 | CallInfo { signature, active_parameter: None } |
115 | } | 113 | } |
116 | } | ||
117 | |||
118 | fn param_list(node: &ast::FnDef) -> Vec<String> { | ||
119 | let mut res = vec![]; | ||
120 | if let Some(param_list) = node.param_list() { | ||
121 | if let Some(self_param) = param_list.self_param() { | ||
122 | res.push(self_param.syntax().text().to_string()) | ||
123 | } | ||
124 | 114 | ||
125 | // Maybe use param.pat here? See if we can just extract the name? | 115 | fn parameters(&self) -> &[String] { |
126 | //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); | 116 | &self.signature.parameters |
127 | res.extend( | ||
128 | param_list.params().filter_map(|p| p.pat()).map(|pat| pat.syntax().text().to_string()), | ||
129 | ); | ||
130 | } | 117 | } |
131 | res | ||
132 | } | 118 | } |
133 | 119 | ||
134 | #[cfg(test)] | 120 | #[cfg(test)] |
@@ -139,6 +125,17 @@ mod tests { | |||
139 | 125 | ||
140 | use super::*; | 126 | use super::*; |
141 | 127 | ||
128 | // These are only used when testing | ||
129 | impl CallInfo { | ||
130 | fn doc(&self) -> Option<hir::Documentation> { | ||
131 | self.signature.doc.clone() | ||
132 | } | ||
133 | |||
134 | fn label(&self) -> String { | ||
135 | self.signature.to_string() | ||
136 | } | ||
137 | } | ||
138 | |||
142 | fn call_info(text: &str) -> CallInfo { | 139 | fn call_info(text: &str) -> CallInfo { |
143 | let (analysis, position) = single_file_with_position(text); | 140 | let (analysis, position) = single_file_with_position(text); |
144 | analysis.call_info(position).unwrap().unwrap() | 141 | analysis.call_info(position).unwrap().unwrap() |
@@ -151,7 +148,7 @@ mod tests { | |||
151 | fn bar() { foo(<|>3, ); }"#, | 148 | fn bar() { foo(<|>3, ); }"#, |
152 | ); | 149 | ); |
153 | 150 | ||
154 | assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string())); | 151 | assert_eq!(info.parameters(), ["x: u32", "y: u32"]); |
155 | assert_eq!(info.active_parameter, Some(0)); | 152 | assert_eq!(info.active_parameter, Some(0)); |
156 | } | 153 | } |
157 | 154 | ||
@@ -162,7 +159,7 @@ fn bar() { foo(<|>3, ); }"#, | |||
162 | fn bar() { foo(3, <|>); }"#, | 159 | fn bar() { foo(3, <|>); }"#, |
163 | ); | 160 | ); |
164 | 161 | ||
165 | assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string())); | 162 | assert_eq!(info.parameters(), ["x: u32", "y: u32"]); |
166 | assert_eq!(info.active_parameter, Some(1)); | 163 | assert_eq!(info.active_parameter, Some(1)); |
167 | } | 164 | } |
168 | 165 | ||
@@ -173,18 +170,57 @@ fn bar() { foo(3, <|>); }"#, | |||
173 | fn bar() { foo(<|>); }"#, | 170 | fn bar() { foo(<|>); }"#, |
174 | ); | 171 | ); |
175 | 172 | ||
176 | assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string())); | 173 | assert_eq!(info.parameters(), ["x: u32", "y: u32"]); |
174 | assert_eq!(info.active_parameter, Some(0)); | ||
175 | } | ||
176 | |||
177 | #[test] | ||
178 | fn test_fn_signature_two_args_first_generics() { | ||
179 | let info = call_info( | ||
180 | r#"fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 where T: Copy + Display, U: Debug {x + y} | ||
181 | fn bar() { foo(<|>3, ); }"#, | ||
182 | ); | ||
183 | |||
184 | assert_eq!(info.parameters(), ["x: T", "y: U"]); | ||
185 | assert_eq!( | ||
186 | info.label(), | ||
187 | r#" | ||
188 | fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 | ||
189 | where T: Copy + Display, | ||
190 | U: Debug | ||
191 | "# | ||
192 | .trim() | ||
193 | ); | ||
177 | assert_eq!(info.active_parameter, Some(0)); | 194 | assert_eq!(info.active_parameter, Some(0)); |
178 | } | 195 | } |
179 | 196 | ||
180 | #[test] | 197 | #[test] |
198 | fn test_fn_signature_no_params() { | ||
199 | let info = call_info( | ||
200 | r#"fn foo<T>() -> T where T: Copy + Display {} | ||
201 | fn bar() { foo(<|>); }"#, | ||
202 | ); | ||
203 | |||
204 | assert!(info.parameters().is_empty()); | ||
205 | assert_eq!( | ||
206 | info.label(), | ||
207 | r#" | ||
208 | fn foo<T>() -> T | ||
209 | where T: Copy + Display | ||
210 | "# | ||
211 | .trim() | ||
212 | ); | ||
213 | assert!(info.active_parameter.is_none()); | ||
214 | } | ||
215 | |||
216 | #[test] | ||
181 | fn test_fn_signature_for_impl() { | 217 | fn test_fn_signature_for_impl() { |
182 | let info = call_info( | 218 | let info = call_info( |
183 | r#"struct F; impl F { pub fn new() { F{}} } | 219 | r#"struct F; impl F { pub fn new() { F{}} } |
184 | fn bar() {let _ : F = F::new(<|>);}"#, | 220 | fn bar() {let _ : F = F::new(<|>);}"#, |
185 | ); | 221 | ); |
186 | 222 | ||
187 | assert_eq!(info.parameters, Vec::<String>::new()); | 223 | assert!(info.parameters().is_empty()); |
188 | assert_eq!(info.active_parameter, None); | 224 | assert_eq!(info.active_parameter, None); |
189 | } | 225 | } |
190 | 226 | ||
@@ -206,7 +242,7 @@ fn bar() { | |||
206 | }"#, | 242 | }"#, |
207 | ); | 243 | ); |
208 | 244 | ||
209 | assert_eq!(info.parameters, vec!["&self".to_string()]); | 245 | assert_eq!(info.parameters(), ["&self"]); |
210 | assert_eq!(info.active_parameter, None); | 246 | assert_eq!(info.active_parameter, None); |
211 | } | 247 | } |
212 | 248 | ||
@@ -228,7 +264,7 @@ fn bar() { | |||
228 | }"#, | 264 | }"#, |
229 | ); | 265 | ); |
230 | 266 | ||
231 | assert_eq!(info.parameters, vec!["&self".to_string(), "x".to_string()]); | 267 | assert_eq!(info.parameters(), ["&self", "x: i32"]); |
232 | assert_eq!(info.active_parameter, Some(1)); | 268 | assert_eq!(info.active_parameter, Some(1)); |
233 | } | 269 | } |
234 | 270 | ||
@@ -248,10 +284,10 @@ fn bar() { | |||
248 | "#, | 284 | "#, |
249 | ); | 285 | ); |
250 | 286 | ||
251 | assert_eq!(info.parameters, vec!["j".to_string()]); | 287 | assert_eq!(info.parameters(), ["j: u32"]); |
252 | assert_eq!(info.active_parameter, Some(0)); | 288 | assert_eq!(info.active_parameter, Some(0)); |
253 | assert_eq!(info.label, "fn foo(j: u32) -> u32".to_string()); | 289 | assert_eq!(info.label(), "fn foo(j: u32) -> u32"); |
254 | assert_eq!(info.doc.map(|it| it.into()), Some("test".to_string())); | 290 | assert_eq!(info.doc().map(|it| it.into()), Some("test".to_string())); |
255 | } | 291 | } |
256 | 292 | ||
257 | #[test] | 293 | #[test] |
@@ -276,11 +312,11 @@ pub fn do() { | |||
276 | }"#, | 312 | }"#, |
277 | ); | 313 | ); |
278 | 314 | ||
279 | assert_eq!(info.parameters, vec!["x".to_string()]); | 315 | assert_eq!(info.parameters(), ["x: i32"]); |
280 | assert_eq!(info.active_parameter, Some(0)); | 316 | assert_eq!(info.active_parameter, Some(0)); |
281 | assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string()); | 317 | assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32"); |
282 | assert_eq!( | 318 | assert_eq!( |
283 | info.doc.map(|it| it.into()), | 319 | info.doc().map(|it| it.into()), |
284 | Some( | 320 | Some( |
285 | r#"Adds one to the number given. | 321 | r#"Adds one to the number given. |
286 | 322 | ||
@@ -322,11 +358,11 @@ pub fn do_it() { | |||
322 | }"#, | 358 | }"#, |
323 | ); | 359 | ); |
324 | 360 | ||
325 | assert_eq!(info.parameters, vec!["x".to_string()]); | 361 | assert_eq!(info.parameters(), ["x: i32"]); |
326 | assert_eq!(info.active_parameter, Some(0)); | 362 | assert_eq!(info.active_parameter, Some(0)); |
327 | assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string()); | 363 | assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32"); |
328 | assert_eq!( | 364 | assert_eq!( |
329 | info.doc.map(|it| it.into()), | 365 | info.doc().map(|it| it.into()), |
330 | Some( | 366 | Some( |
331 | r#"Adds one to the number given. | 367 | r#"Adds one to the number given. |
332 | 368 | ||
@@ -375,10 +411,10 @@ pub fn foo() { | |||
375 | "#, | 411 | "#, |
376 | ); | 412 | ); |
377 | 413 | ||
378 | assert_eq!(info.parameters, vec!["&mut self".to_string(), "ctx".to_string()]); | 414 | assert_eq!(info.parameters(), ["&mut self", "ctx: &mut Self::Context"]); |
379 | assert_eq!(info.active_parameter, Some(1)); | 415 | assert_eq!(info.active_parameter, Some(1)); |
380 | assert_eq!( | 416 | assert_eq!( |
381 | info.doc.map(|it| it.into()), | 417 | info.doc().map(|it| it.into()), |
382 | Some( | 418 | Some( |
383 | r#"Method is called when writer finishes. | 419 | r#"Method is called when writer finishes. |
384 | 420 | ||