diff options
Diffstat (limited to 'crates/ra_ide/src/call_hierarchy.rs')
-rw-r--r-- | crates/ra_ide/src/call_hierarchy.rs | 52 |
1 files changed, 22 insertions, 30 deletions
diff --git a/crates/ra_ide/src/call_hierarchy.rs b/crates/ra_ide/src/call_hierarchy.rs index f984f40ad..b00b6d431 100644 --- a/crates/ra_ide/src/call_hierarchy.rs +++ b/crates/ra_ide/src/call_hierarchy.rs | |||
@@ -2,18 +2,13 @@ | |||
2 | 2 | ||
3 | use indexmap::IndexMap; | 3 | use indexmap::IndexMap; |
4 | 4 | ||
5 | use hir::db::AstDatabase; | 5 | use hir::Semantics; |
6 | use ra_ide_db::RootDatabase; | 6 | use ra_ide_db::RootDatabase; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{ast, match_ast, AstNode, TextRange}; |
8 | ast::{self, DocCommentsOwner}, | ||
9 | match_ast, AstNode, TextRange, | ||
10 | }; | ||
11 | 8 | ||
12 | use crate::{ | 9 | use crate::{ |
13 | call_info::FnCallNode, | 10 | call_info::FnCallNode, display::ToNav, goto_definition, references, FilePosition, |
14 | display::{ShortLabel, ToNav}, | 11 | NavigationTarget, RangeInfo, |
15 | expand::descend_into_macros, | ||
16 | goto_definition, references, FilePosition, NavigationTarget, RangeInfo, | ||
17 | }; | 12 | }; |
18 | 13 | ||
19 | #[derive(Debug, Clone)] | 14 | #[derive(Debug, Clone)] |
@@ -43,6 +38,7 @@ pub(crate) fn call_hierarchy( | |||
43 | } | 38 | } |
44 | 39 | ||
45 | 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); | ||
46 | // 1. Find all refs | 42 | // 1. Find all refs |
47 | // 2. Loop through refs and determine unique fndef. This will become our `from: CallHierarchyItem,` in the reply. | 43 | // 2. Loop through refs and determine unique fndef. This will become our `from: CallHierarchyItem,` in the reply. |
48 | // 3. Add ranges relative to the start of the fndef. | 44 | // 3. Add ranges relative to the start of the fndef. |
@@ -52,24 +48,21 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
52 | 48 | ||
53 | for reference in refs.info.references() { | 49 | for reference in refs.info.references() { |
54 | let file_id = reference.file_range.file_id; | 50 | let file_id = reference.file_range.file_id; |
55 | let file = db.parse_or_expand(file_id.into())?; | 51 | let file = sema.parse(file_id); |
52 | let file = file.syntax(); | ||
56 | let token = file.token_at_offset(reference.file_range.range.start()).next()?; | 53 | let token = file.token_at_offset(reference.file_range.range.start()).next()?; |
57 | let token = descend_into_macros(db, file_id, token); | 54 | let token = sema.descend_into_macros(token); |
58 | let syntax = token.value.parent(); | 55 | let syntax = token.parent(); |
59 | 56 | ||
60 | // This target is the containing function | 57 | // This target is the containing function |
61 | if let Some(nav) = syntax.ancestors().find_map(|node| { | 58 | if let Some(nav) = syntax.ancestors().find_map(|node| { |
62 | match_ast! { | 59 | match_ast! { |
63 | match node { | 60 | match node { |
64 | ast::FnDef(it) => { | 61 | ast::FnDef(it) => { |
65 | Some(NavigationTarget::from_named( | 62 | let def = sema.to_def(&it)?; |
66 | db, | 63 | Some(def.to_nav(sema.db)) |
67 | token.with_value(&it), | ||
68 | it.doc_comment_text(), | ||
69 | it.short_label(), | ||
70 | )) | ||
71 | }, | 64 | }, |
72 | _ => { None }, | 65 | _ => None, |
73 | } | 66 | } |
74 | } | 67 | } |
75 | }) { | 68 | }) { |
@@ -82,11 +75,13 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
82 | } | 75 | } |
83 | 76 | ||
84 | pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> { | 77 | pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> { |
78 | let sema = Semantics::new(db); | ||
85 | let file_id = position.file_id; | 79 | let file_id = position.file_id; |
86 | let file = db.parse_or_expand(file_id.into())?; | 80 | let file = sema.parse(file_id); |
81 | let file = file.syntax(); | ||
87 | let token = file.token_at_offset(position.offset).next()?; | 82 | let token = file.token_at_offset(position.offset).next()?; |
88 | let token = descend_into_macros(db, file_id, token); | 83 | let token = sema.descend_into_macros(token); |
89 | let syntax = token.value.parent(); | 84 | let syntax = token.parent(); |
90 | 85 | ||
91 | let mut calls = CallLocations::default(); | 86 | let mut calls = CallLocations::default(); |
92 | 87 | ||
@@ -95,14 +90,11 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
95 | .filter_map(|node| FnCallNode::with_node_exact(&node)) | 90 | .filter_map(|node| FnCallNode::with_node_exact(&node)) |
96 | .filter_map(|call_node| { | 91 | .filter_map(|call_node| { |
97 | let name_ref = call_node.name_ref()?; | 92 | let name_ref = call_node.name_ref()?; |
98 | let name_ref = token.with_value(name_ref.syntax()); | ||
99 | |||
100 | let analyzer = hir::SourceAnalyzer::new(db, name_ref, None); | ||
101 | 93 | ||
102 | if let Some(func_target) = match &call_node { | 94 | if let Some(func_target) = match &call_node { |
103 | FnCallNode::CallExpr(expr) => { | 95 | FnCallNode::CallExpr(expr) => { |
104 | //FIXME: Type::as_callable is broken | 96 | //FIXME: Type::as_callable is broken |
105 | let callable_def = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; | 97 | let callable_def = sema.type_of_expr(&expr.expr()?)?.as_callable()?; |
106 | match callable_def { | 98 | match callable_def { |
107 | hir::CallableDef::FunctionId(it) => { | 99 | hir::CallableDef::FunctionId(it) => { |
108 | let fn_def: hir::Function = it.into(); | 100 | let fn_def: hir::Function = it.into(); |
@@ -113,15 +105,15 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
113 | } | 105 | } |
114 | } | 106 | } |
115 | FnCallNode::MethodCallExpr(expr) => { | 107 | FnCallNode::MethodCallExpr(expr) => { |
116 | let function = analyzer.resolve_method_call(&expr)?; | 108 | let function = sema.resolve_method_call(&expr)?; |
117 | Some(function.to_nav(db)) | 109 | Some(function.to_nav(db)) |
118 | } | 110 | } |
119 | FnCallNode::MacroCallExpr(expr) => { | 111 | FnCallNode::MacroCallExpr(macro_call) => { |
120 | let macro_def = analyzer.resolve_macro_call(db, name_ref.with_value(&expr))?; | 112 | let macro_def = sema.resolve_macro_call(¯o_call)?; |
121 | Some(macro_def.to_nav(db)) | 113 | Some(macro_def.to_nav(db)) |
122 | } | 114 | } |
123 | } { | 115 | } { |
124 | Some((func_target, name_ref.value.text_range())) | 116 | Some((func_target, name_ref.syntax().text_range())) |
125 | } else { | 117 | } else { |
126 | None | 118 | None |
127 | } | 119 | } |