diff options
Diffstat (limited to 'crates/ra_ide/src/call_info.rs')
-rw-r--r-- | crates/ra_ide/src/call_info.rs | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 7c6322cb4..2b35a3803 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs | |||
@@ -1,48 +1,55 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use hir::db::AstDatabase; | 2 | use hir::Semantics; |
3 | use ra_ide_db::RootDatabase; | 3 | use ra_ide_db::RootDatabase; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | ast::{self, ArgListOwner}, | 5 | ast::{self, ArgListOwner}, |
6 | match_ast, AstNode, SyntaxNode, | 6 | match_ast, AstNode, SyntaxNode, SyntaxToken, |
7 | }; | 7 | }; |
8 | use test_utils::tested_by; | 8 | use test_utils::tested_by; |
9 | 9 | ||
10 | use crate::{expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature}; | 10 | use crate::{CallInfo, FilePosition, FunctionSignature}; |
11 | 11 | ||
12 | /// Computes parameter information for the given call expression. | 12 | /// Computes parameter information for the given call expression. |
13 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { | 13 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { |
14 | let file = db.parse_or_expand(position.file_id.into())?; | 14 | let sema = Semantics::new(db); |
15 | let file = sema.parse(position.file_id); | ||
16 | let file = file.syntax(); | ||
15 | let token = file.token_at_offset(position.offset).next()?; | 17 | let token = file.token_at_offset(position.offset).next()?; |
16 | let token = descend_into_macros(db, position.file_id, token); | 18 | let token = sema.descend_into_macros(token); |
19 | call_info_for_token(&sema, token) | ||
20 | } | ||
17 | 21 | ||
22 | pub(crate) fn call_info_for_token( | ||
23 | sema: &Semantics<RootDatabase>, | ||
24 | token: SyntaxToken, | ||
25 | ) -> Option<CallInfo> { | ||
18 | // Find the calling expression and it's NameRef | 26 | // Find the calling expression and it's NameRef |
19 | let calling_node = FnCallNode::with_node(&token.value.parent())?; | 27 | let calling_node = FnCallNode::with_node(&token.parent())?; |
20 | let name_ref = calling_node.name_ref()?; | ||
21 | let name_ref = token.with_value(name_ref.syntax()); | ||
22 | 28 | ||
23 | let analyzer = hir::SourceAnalyzer::new(db, name_ref, None); | ||
24 | let (mut call_info, has_self) = match &calling_node { | 29 | let (mut call_info, has_self) = match &calling_node { |
25 | FnCallNode::CallExpr(expr) => { | 30 | FnCallNode::CallExpr(call) => { |
26 | //FIXME: Type::as_callable is broken | 31 | //FIXME: Type::as_callable is broken |
27 | let callable_def = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; | 32 | let callable_def = sema.type_of_expr(&call.expr()?)?.as_callable()?; |
28 | match callable_def { | 33 | match callable_def { |
29 | hir::CallableDef::FunctionId(it) => { | 34 | hir::CallableDef::FunctionId(it) => { |
30 | let fn_def = it.into(); | 35 | let fn_def = it.into(); |
31 | (CallInfo::with_fn(db, fn_def), fn_def.has_self_param(db)) | 36 | (CallInfo::with_fn(sema.db, fn_def), fn_def.has_self_param(sema.db)) |
37 | } | ||
38 | hir::CallableDef::StructId(it) => { | ||
39 | (CallInfo::with_struct(sema.db, it.into())?, false) | ||
32 | } | 40 | } |
33 | hir::CallableDef::StructId(it) => (CallInfo::with_struct(db, it.into())?, false), | ||
34 | hir::CallableDef::EnumVariantId(it) => { | 41 | hir::CallableDef::EnumVariantId(it) => { |
35 | (CallInfo::with_enum_variant(db, it.into())?, false) | 42 | (CallInfo::with_enum_variant(sema.db, it.into())?, false) |
36 | } | 43 | } |
37 | } | 44 | } |
38 | } | 45 | } |
39 | FnCallNode::MethodCallExpr(expr) => { | 46 | FnCallNode::MethodCallExpr(method_call) => { |
40 | let function = analyzer.resolve_method_call(&expr)?; | 47 | let function = sema.resolve_method_call(&method_call)?; |
41 | (CallInfo::with_fn(db, function), function.has_self_param(db)) | 48 | (CallInfo::with_fn(sema.db, function), function.has_self_param(sema.db)) |
42 | } | 49 | } |
43 | FnCallNode::MacroCallExpr(expr) => { | 50 | FnCallNode::MacroCallExpr(macro_call) => { |
44 | let macro_def = analyzer.resolve_macro_call(db, name_ref.with_value(&expr))?; | 51 | let macro_def = sema.resolve_macro_call(¯o_call)?; |
45 | (CallInfo::with_macro(db, macro_def)?, false) | 52 | (CallInfo::with_macro(sema.db, macro_def)?, false) |
46 | } | 53 | } |
47 | }; | 54 | }; |
48 | 55 | ||
@@ -62,7 +69,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
62 | let num_args_at_callsite = arg_list.args().count(); | 69 | let num_args_at_callsite = arg_list.args().count(); |
63 | 70 | ||
64 | let arg_list_range = arg_list.syntax().text_range(); | 71 | let arg_list_range = arg_list.syntax().text_range(); |
65 | if !arg_list_range.contains_inclusive(position.offset) { | 72 | if !arg_list_range.contains_inclusive(token.text_range().start()) { |
66 | tested_by!(call_info_bad_offset); | 73 | tested_by!(call_info_bad_offset); |
67 | return None; | 74 | return None; |
68 | } | 75 | } |
@@ -71,7 +78,9 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
71 | num_args_at_callsite, | 78 | num_args_at_callsite, |
72 | arg_list | 79 | arg_list |
73 | .args() | 80 | .args() |
74 | .take_while(|arg| arg.syntax().text_range().end() < position.offset) | 81 | .take_while(|arg| { |
82 | arg.syntax().text_range().end() < token.text_range().start() | ||
83 | }) | ||
75 | .count(), | 84 | .count(), |
76 | ); | 85 | ); |
77 | 86 | ||
@@ -101,7 +110,13 @@ impl FnCallNode { | |||
101 | match_ast! { | 110 | match_ast! { |
102 | match node { | 111 | match node { |
103 | ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, | 112 | ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, |
104 | ast::MethodCallExpr(it) => { Some(FnCallNode::MethodCallExpr(it)) }, | 113 | ast::MethodCallExpr(it) => { |
114 | let arg_list = it.arg_list()?; | ||
115 | if !syntax.text_range().is_subrange(&arg_list.syntax().text_range()) { | ||
116 | return None; | ||
117 | } | ||
118 | Some(FnCallNode::MethodCallExpr(it)) | ||
119 | }, | ||
105 | ast::MacroCall(it) => { Some(FnCallNode::MacroCallExpr(it)) }, | 120 | ast::MacroCall(it) => { Some(FnCallNode::MacroCallExpr(it)) }, |
106 | _ => { None }, | 121 | _ => { None }, |
107 | } | 122 | } |