aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/call_info.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/call_info.rs')
-rw-r--r--crates/ra_ide/src/call_info.rs43
1 files changed, 33 insertions, 10 deletions
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs
index d559dc4d0..2c2b6fa48 100644
--- a/crates/ra_ide/src/call_info.rs
+++ b/crates/ra_ide/src/call_info.rs
@@ -1,24 +1,26 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_db::SourceDatabase; 3use hir::db::AstDatabase;
4use ra_syntax::{ 4use ra_syntax::{
5 algo::ancestors_at_offset,
6 ast::{self, ArgListOwner}, 5 ast::{self, ArgListOwner},
7 match_ast, AstNode, SyntaxNode, TextUnit, 6 match_ast, AstNode, SyntaxNode,
8}; 7};
9use test_utils::tested_by; 8use test_utils::tested_by;
10 9
11use crate::{db::RootDatabase, CallInfo, FilePosition, FunctionSignature}; 10use crate::{
11 db::RootDatabase, expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature,
12};
12 13
13/// Computes parameter information for the given call expression. 14/// Computes parameter information for the given call expression.
14pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { 15pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
15 let parse = db.parse(position.file_id); 16 let file = db.parse_or_expand(position.file_id.into())?;
16 let syntax = parse.tree().syntax().clone(); 17 let token = file.token_at_offset(position.offset).next()?;
18 let token = descend_into_macros(db, position.file_id, token);
17 19
18 // Find the calling expression and it's NameRef 20 // Find the calling expression and it's NameRef
19 let calling_node = FnCallNode::with_node(&syntax, position.offset)?; 21 let calling_node = FnCallNode::with_node(&token.value.parent())?;
20 let name_ref = calling_node.name_ref()?; 22 let name_ref = calling_node.name_ref()?;
21 let name_ref = hir::Source::new(position.file_id.into(), name_ref.syntax()); 23 let name_ref = token.with_value(name_ref.syntax());
22 24
23 let analyzer = hir::SourceAnalyzer::new(db, name_ref, None); 25 let analyzer = hir::SourceAnalyzer::new(db, name_ref, None);
24 let (mut call_info, has_self) = match &calling_node { 26 let (mut call_info, has_self) = match &calling_node {
@@ -93,8 +95,8 @@ enum FnCallNode {
93} 95}
94 96
95impl FnCallNode { 97impl FnCallNode {
96 fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option<FnCallNode> { 98 fn with_node(syntax: &SyntaxNode) -> Option<FnCallNode> {
97 ancestors_at_offset(syntax, offset).find_map(|node| { 99 syntax.ancestors().find_map(|node| {
98 match_ast! { 100 match_ast! {
99 match node { 101 match node {
100 ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, 102 ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) },
@@ -589,4 +591,25 @@ fn f() {
589 assert_eq!(info.label(), "foo!()"); 591 assert_eq!(info.label(), "foo!()");
590 assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string())); 592 assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string()));
591 } 593 }
594
595 #[test]
596 fn fn_signature_for_call_in_macro() {
597 let info = call_info(
598 r#"
599 macro_rules! id {
600 ($($tt:tt)*) => { $($tt)* }
601 }
602 fn foo() {
603
604 }
605 id! {
606 fn bar() {
607 foo(<|>);
608 }
609 }
610 "#,
611 );
612
613 assert_eq!(info.label(), "fn foo()");
614 }
592} 615}