mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 14:03:35 +00:00
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.
This commit is contained in:
parent
242f0ae1d8
commit
7ec43ee07a
1 changed files with 30 additions and 9 deletions
|
@ -1,22 +1,22 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use ra_db::SourceDatabase;
|
use hir::db::AstDatabase;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::ancestors_at_offset,
|
|
||||||
ast::{self, ArgListOwner},
|
ast::{self, ArgListOwner},
|
||||||
match_ast, AstNode, SyntaxNode, TextUnit,
|
match_ast, AstNode, SyntaxNode,
|
||||||
};
|
};
|
||||||
use test_utils::tested_by;
|
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.
|
/// Computes parameter information for the given call expression.
|
||||||
pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
|
pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
|
||||||
let parse = db.parse(position.file_id);
|
let file = db.parse_or_expand(position.file_id.into())?;
|
||||||
let syntax = parse.tree().syntax().clone();
|
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
|
// 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 = calling_node.name_ref()?;
|
||||||
let name_ref = hir::InFile::new(position.file_id.into(), name_ref.syntax());
|
let name_ref = hir::InFile::new(position.file_id.into(), name_ref.syntax());
|
||||||
|
|
||||||
|
@ -93,8 +93,8 @@ enum FnCallNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnCallNode {
|
impl FnCallNode {
|
||||||
fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option<FnCallNode> {
|
fn with_node(syntax: &SyntaxNode) -> Option<FnCallNode> {
|
||||||
ancestors_at_offset(syntax, offset).find_map(|node| {
|
syntax.ancestors().find_map(|node| {
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) },
|
ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) },
|
||||||
|
@ -589,4 +589,25 @@ fn f() {
|
||||||
assert_eq!(info.label(), "foo!()");
|
assert_eq!(info.label(), "foo!()");
|
||||||
assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string()));
|
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()");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue