aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/call_hierarchy.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/call_hierarchy.rs')
-rw-r--r--crates/ra_ide/src/call_hierarchy.rs97
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
40pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> { 40pub(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(&macro_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
290pub fn callee() {} 288pub 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
328pub fn callee() {} 326pub 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#"
361fn a() {
362 b()
363}
364
365fn b() {}
366
367fn 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#"
378fn a() {
379 b<|>()
380}
381
382fn b() {}
383
384fn 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}