From 7ec43ee07a26667bb1458990ec667f82670aff22 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Mon, 18 Nov 2019 18:08:39 -0500 Subject: WIP: See through Macros for SignatureHelp Note: we meed to skip the trivia filter to make sure that `covers!(call_info_bad_offset)` succeeds otherwise we exit call_info too early. Also the test doesn't pass: `FnCallNode::with_node` always detects a MacroCall. --- crates/ra_ide/src/call_info.rs | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index b3c323d38..2da9c4e76 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -1,22 +1,22 @@ //! FIXME: write short doc here -use ra_db::SourceDatabase; +use hir::db::AstDatabase; use ra_syntax::{ - algo::ancestors_at_offset, ast::{self, ArgListOwner}, - match_ast, AstNode, SyntaxNode, TextUnit, + match_ast, AstNode, SyntaxNode, }; use test_utils::tested_by; -use crate::{db::RootDatabase, CallInfo, FilePosition, FunctionSignature}; +use crate::{db::RootDatabase, expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature}; /// Computes parameter information for the given call expression. pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option { - let parse = db.parse(position.file_id); - let syntax = parse.tree().syntax().clone(); + let file = db.parse_or_expand(position.file_id.into())?; + let token = file.token_at_offset(position.offset).next()?; + let token = descend_into_macros(db, position.file_id, token); // Find the calling expression and it's NameRef - let calling_node = FnCallNode::with_node(&syntax, position.offset)?; + let calling_node = FnCallNode::with_node(&token.value.parent())?; let name_ref = calling_node.name_ref()?; let name_ref = hir::InFile::new(position.file_id.into(), name_ref.syntax()); @@ -93,8 +93,8 @@ enum FnCallNode { } impl FnCallNode { - fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option { - ancestors_at_offset(syntax, offset).find_map(|node| { + fn with_node(syntax: &SyntaxNode) -> Option { + syntax.ancestors().find_map(|node| { match_ast! { match node { ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, @@ -589,4 +589,25 @@ fn f() { assert_eq!(info.label(), "foo!()"); assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string())); } + + #[test] + fn fn_signature_for_call_in_macro() { + let info = call_info( + r#" + macro_rules! id { + ($($tt:tt)*) => { $($tt)* } + } + fn foo() { + + } + id! { + fn bar() { + foo(<|>); + } + } + "#, + ); + + assert_eq!(info.label(), "fn foo()"); + } } -- cgit v1.2.3