diff options
Diffstat (limited to 'crates/ra_ide/src/call_hierarchy.rs')
-rw-r--r-- | crates/ra_ide/src/call_hierarchy.rs | 97 |
1 files changed, 66 insertions, 31 deletions
diff --git a/crates/ra_ide/src/call_hierarchy.rs b/crates/ra_ide/src/call_hierarchy.rs index 1e3a31602..1fcaf4a32 100644 --- a/crates/ra_ide/src/call_hierarchy.rs +++ b/crates/ra_ide/src/call_hierarchy.rs | |||
@@ -39,10 +39,11 @@ pub(crate) fn call_hierarchy( | |||
39 | 39 | ||
40 | pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> { | 40 | pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> { |
41 | let sema = Semantics::new(db); | 41 | let sema = Semantics::new(db); |
42 | |||
42 | // 1. Find all refs | 43 | // 1. Find all refs |
43 | // 2. Loop through refs and determine unique fndef. This will become our `from: CallHierarchyItem,` in the reply. | 44 | // 2. Loop through refs and determine unique fndef. This will become our `from: CallHierarchyItem,` in the reply. |
44 | // 3. Add ranges relative to the start of the fndef. | 45 | // 3. Add ranges relative to the start of the fndef. |
45 | let refs = references::find_all_refs(db, position, None)?; | 46 | let refs = references::find_all_refs(&sema, position, None)?; |
46 | 47 | ||
47 | let mut calls = CallLocations::default(); | 48 | let mut calls = CallLocations::default(); |
48 | 49 | ||
@@ -58,7 +59,7 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
58 | if let Some(nav) = syntax.ancestors().find_map(|node| { | 59 | if let Some(nav) = syntax.ancestors().find_map(|node| { |
59 | match_ast! { | 60 | match_ast! { |
60 | match node { | 61 | match node { |
61 | ast::FnDef(it) => { | 62 | ast::Fn(it) => { |
62 | let def = sema.to_def(&it)?; | 63 | let def = sema.to_def(&it)?; |
63 | Some(def.to_nav(sema.db)) | 64 | Some(def.to_nav(sema.db)) |
64 | }, | 65 | }, |
@@ -94,9 +95,9 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
94 | if let Some(func_target) = match &call_node { | 95 | if let Some(func_target) = match &call_node { |
95 | FnCallNode::CallExpr(expr) => { | 96 | FnCallNode::CallExpr(expr) => { |
96 | //FIXME: Type::as_callable is broken | 97 | //FIXME: Type::as_callable is broken |
97 | let callable_def = sema.type_of_expr(&expr.expr()?)?.as_callable()?; | 98 | let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(db)?; |
98 | match callable_def { | 99 | match callable.kind() { |
99 | hir::CallableDef::FunctionId(it) => { | 100 | hir::CallableKind::Function(it) => { |
100 | let fn_def: hir::Function = it.into(); | 101 | let fn_def: hir::Function = it.into(); |
101 | let nav = fn_def.to_nav(db); | 102 | let nav = fn_def.to_nav(db); |
102 | Some(nav) | 103 | Some(nav) |
@@ -108,10 +109,6 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
108 | let function = sema.resolve_method_call(&expr)?; | 109 | let function = sema.resolve_method_call(&expr)?; |
109 | Some(function.to_nav(db)) | 110 | Some(function.to_nav(db)) |
110 | } | 111 | } |
111 | FnCallNode::MacroCallExpr(macro_call) => { | ||
112 | let macro_def = sema.resolve_macro_call(¯o_call)?; | ||
113 | Some(macro_def.to_nav(db)) | ||
114 | } | ||
115 | } { | 112 | } { |
116 | Some((func_target, name_ref.syntax().text_range())) | 113 | Some((func_target, name_ref.syntax().text_range())) |
117 | } else { | 114 | } else { |
@@ -157,7 +154,8 @@ mod tests { | |||
157 | let nav = navs.pop().unwrap(); | 154 | let nav = navs.pop().unwrap(); |
158 | nav.assert_match(expected); | 155 | nav.assert_match(expected); |
159 | 156 | ||
160 | let item_pos = FilePosition { file_id: nav.file_id(), offset: nav.range().start() }; | 157 | let item_pos = |
158 | FilePosition { file_id: nav.file_id, offset: nav.focus_or_full_range().start() }; | ||
161 | let incoming_calls = analysis.incoming_calls(item_pos).unwrap().unwrap(); | 159 | let incoming_calls = analysis.incoming_calls(item_pos).unwrap().unwrap(); |
162 | assert_eq!(incoming_calls.len(), expected_incoming.len()); | 160 | assert_eq!(incoming_calls.len(), expected_incoming.len()); |
163 | 161 | ||
@@ -183,8 +181,8 @@ fn caller() { | |||
183 | call<|>ee(); | 181 | call<|>ee(); |
184 | } | 182 | } |
185 | "#, | 183 | "#, |
186 | "callee FN_DEF FileId(1) 0..14 3..9", | 184 | "callee FN FileId(1) 0..14 3..9", |
187 | &["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"], | 185 | &["caller FN FileId(1) 15..44 18..24 : [33..39]"], |
188 | &[], | 186 | &[], |
189 | ); | 187 | ); |
190 | } | 188 | } |
@@ -199,8 +197,8 @@ fn caller() { | |||
199 | callee(); | 197 | callee(); |
200 | } | 198 | } |
201 | "#, | 199 | "#, |
202 | "callee FN_DEF FileId(1) 0..14 3..9", | 200 | "callee FN FileId(1) 0..14 3..9", |
203 | &["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"], | 201 | &["caller FN FileId(1) 15..44 18..24 : [33..39]"], |
204 | &[], | 202 | &[], |
205 | ); | 203 | ); |
206 | } | 204 | } |
@@ -216,8 +214,8 @@ fn caller() { | |||
216 | callee(); | 214 | callee(); |
217 | } | 215 | } |
218 | "#, | 216 | "#, |
219 | "callee FN_DEF FileId(1) 0..14 3..9", | 217 | "callee FN FileId(1) 0..14 3..9", |
220 | &["caller FN_DEF FileId(1) 15..58 18..24 : [33..39, 47..53]"], | 218 | &["caller FN FileId(1) 15..58 18..24 : [33..39, 47..53]"], |
221 | &[], | 219 | &[], |
222 | ); | 220 | ); |
223 | } | 221 | } |
@@ -236,10 +234,10 @@ fn caller2() { | |||
236 | callee(); | 234 | callee(); |
237 | } | 235 | } |
238 | "#, | 236 | "#, |
239 | "callee FN_DEF FileId(1) 0..14 3..9", | 237 | "callee FN FileId(1) 0..14 3..9", |
240 | &[ | 238 | &[ |
241 | "caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]", | 239 | "caller1 FN FileId(1) 15..45 18..25 : [34..40]", |
242 | "caller2 FN_DEF FileId(1) 47..77 50..57 : [66..72]", | 240 | "caller2 FN FileId(1) 47..77 50..57 : [66..72]", |
243 | ], | 241 | ], |
244 | &[], | 242 | &[], |
245 | ); | 243 | ); |
@@ -265,10 +263,10 @@ mod tests { | |||
265 | } | 263 | } |
266 | } | 264 | } |
267 | "#, | 265 | "#, |
268 | "callee FN_DEF FileId(1) 0..14 3..9", | 266 | "callee FN FileId(1) 0..14 3..9", |
269 | &[ | 267 | &[ |
270 | "caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]", | 268 | "caller1 FN FileId(1) 15..45 18..25 : [34..40]", |
271 | "test_caller FN_DEF FileId(1) 95..149 110..121 : [134..140]", | 269 | "test_caller FN FileId(1) 95..149 110..121 : [134..140]", |
272 | ], | 270 | ], |
273 | &[], | 271 | &[], |
274 | ); | 272 | ); |
@@ -289,8 +287,8 @@ fn caller() { | |||
289 | //- /foo/mod.rs | 287 | //- /foo/mod.rs |
290 | pub fn callee() {} | 288 | pub fn callee() {} |
291 | "#, | 289 | "#, |
292 | "callee FN_DEF FileId(2) 0..18 7..13", | 290 | "callee FN FileId(2) 0..18 7..13", |
293 | &["caller FN_DEF FileId(1) 27..56 30..36 : [45..51]"], | 291 | &["caller FN FileId(1) 27..56 30..36 : [45..51]"], |
294 | &[], | 292 | &[], |
295 | ); | 293 | ); |
296 | } | 294 | } |
@@ -306,9 +304,9 @@ fn call<|>er() { | |||
306 | callee(); | 304 | callee(); |
307 | } | 305 | } |
308 | "#, | 306 | "#, |
309 | "caller FN_DEF FileId(1) 15..58 18..24", | 307 | "caller FN FileId(1) 15..58 18..24", |
310 | &[], | 308 | &[], |
311 | &["callee FN_DEF FileId(1) 0..14 3..9 : [33..39, 47..53]"], | 309 | &["callee FN FileId(1) 0..14 3..9 : [33..39, 47..53]"], |
312 | ); | 310 | ); |
313 | } | 311 | } |
314 | 312 | ||
@@ -327,9 +325,9 @@ fn call<|>er() { | |||
327 | //- /foo/mod.rs | 325 | //- /foo/mod.rs |
328 | pub fn callee() {} | 326 | pub fn callee() {} |
329 | "#, | 327 | "#, |
330 | "caller FN_DEF FileId(1) 27..56 30..36", | 328 | "caller FN FileId(1) 27..56 30..36", |
331 | &[], | 329 | &[], |
332 | &["callee FN_DEF FileId(2) 0..18 7..13 : [45..51]"], | 330 | &["callee FN FileId(2) 0..18 7..13 : [45..51]"], |
333 | ); | 331 | ); |
334 | } | 332 | } |
335 | 333 | ||
@@ -350,9 +348,46 @@ fn caller3() { | |||
350 | 348 | ||
351 | } | 349 | } |
352 | "#, | 350 | "#, |
353 | "caller2 FN_DEF FileId(1) 33..64 36..43", | 351 | "caller2 FN FileId(1) 33..64 36..43", |
354 | &["caller1 FN_DEF FileId(1) 0..31 3..10 : [19..26]"], | 352 | &["caller1 FN FileId(1) 0..31 3..10 : [19..26]"], |
355 | &["caller3 FN_DEF FileId(1) 66..83 69..76 : [52..59]"], | 353 | &["caller3 FN FileId(1) 66..83 69..76 : [52..59]"], |
354 | ); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
358 | fn test_call_hierarchy_issue_5103() { | ||
359 | check_hierarchy( | ||
360 | r#" | ||
361 | fn a() { | ||
362 | b() | ||
363 | } | ||
364 | |||
365 | fn b() {} | ||
366 | |||
367 | fn main() { | ||
368 | a<|>() | ||
369 | } | ||
370 | "#, | ||
371 | "a FN FileId(1) 0..18 3..4", | ||
372 | &["main FN FileId(1) 31..52 34..38 : [47..48]"], | ||
373 | &["b FN FileId(1) 20..29 23..24 : [13..14]"], | ||
374 | ); | ||
375 | |||
376 | check_hierarchy( | ||
377 | r#" | ||
378 | fn a() { | ||
379 | b<|>() | ||
380 | } | ||
381 | |||
382 | fn b() {} | ||
383 | |||
384 | fn main() { | ||
385 | a() | ||
386 | } | ||
387 | "#, | ||
388 | "b FN FileId(1) 20..29 23..24", | ||
389 | &["a FN FileId(1) 0..18 3..4 : [13..14]"], | ||
390 | &[], | ||
356 | ); | 391 | ); |
357 | } | 392 | } |
358 | } | 393 | } |