7000: Store invocation site for eager macros r=edwin0cheng a=jonas-schievink

Fixes https://github.com/rust-analyzer/rust-analyzer/issues/6992

r? @edwin0cheng 

I'm not sure if this is totally correct, it looks like we create **two** `EagerCallLoc`s per macro invocation, one for the arguments (?), and one for the actual macro call. I gave both the same `AstId`, hopefully that's correct.

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2020-12-23 06:22:28 +00:00 committed by GitHub
commit 493e29d713
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 28 deletions

View File

@ -563,6 +563,7 @@ fn expand_builtin_macro(ra_fixture: &str) -> String {
let args = macro_call.token_tree().unwrap();
let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0;
let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call));
let arg_id = db.intern_eager_expansion({
EagerCallLoc {
@ -570,7 +571,7 @@ fn expand_builtin_macro(ra_fixture: &str) -> String {
fragment: FragmentKind::Expr,
subtree: Arc::new(parsed_args.clone()),
krate,
file_id: file_id.into(),
call: call_id,
}
});
@ -580,7 +581,7 @@ fn expand_builtin_macro(ra_fixture: &str) -> String {
fragment,
subtree: Arc::new(subtree),
krate,
file_id: file_id.into(),
call: call_id,
};
let id: MacroCallId = db.intern_eager_expansion(eager).into();

View File

@ -5,7 +5,7 @@
use base_db::{salsa, SourceDatabase};
use mbe::{ExpandError, ExpandResult, MacroRules};
use parser::FragmentKind;
use syntax::{algo::diff, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode};
use syntax::{algo::diff, ast::NameOwner, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode};
use crate::{
ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId,
@ -129,11 +129,11 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
match id.kind {
MacroDefKind::Declarative => {
let macro_call = match id.ast_id?.to_node(db) {
let macro_rules = match id.ast_id?.to_node(db) {
syntax::ast::Macro::MacroRules(mac) => mac,
syntax::ast::Macro::MacroDef(_) => return None,
};
let arg = macro_call.token_tree()?;
let arg = macro_rules.token_tree()?;
let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| {
log::warn!("fail on macro_def to token tree: {:#?}", arg);
None
@ -141,7 +141,8 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander,
let rules = match MacroRules::parse(&tt) {
Ok(it) => it,
Err(err) => {
log::warn!("fail on macro_def parse: error: {:#?} {:#?}", err, tt);
let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default();
log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt);
return None;
}
};

View File

@ -110,6 +110,9 @@ pub fn expand_eager_macro(
|| err("malformed macro invocation"),
)?;
let ast_map = db.ast_id_map(macro_call.file_id);
let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(&macro_call.value));
// Note:
// When `lazy_expand` is called, its *parent* file must be already exists.
// Here we store an eager macro id for the argument expanded subtree here
@ -120,7 +123,7 @@ pub fn expand_eager_macro(
fragment: FragmentKind::Expr,
subtree: Arc::new(parsed_args.clone()),
krate,
file_id: macro_call.file_id,
call: call_id,
}
});
let arg_file_id: MacroCallId = arg_id.into();
@ -141,13 +144,8 @@ pub fn expand_eager_macro(
let res = eager.expand(db, arg_id, &subtree);
let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?;
let eager = EagerCallLoc {
def,
fragment,
subtree: Arc::new(subtree),
krate,
file_id: macro_call.file_id,
};
let eager =
EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id };
Ok(db.intern_eager_expansion(eager))
} else {

View File

@ -83,7 +83,7 @@ pub fn original_file(self, db: &dyn db::AstDatabase) -> FileId {
}
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
loc.file_id
loc.call.file_id
}
};
file_id.original_file(db)
@ -103,7 +103,7 @@ pub fn expansion_level(self, db: &dyn db::AstDatabase) -> u32 {
}
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
loc.file_id
loc.call.file_id
}
};
}
@ -114,17 +114,16 @@ pub fn expansion_level(self, db: &dyn db::AstDatabase) -> u32 {
pub fn call_node(self, db: &dyn db::AstDatabase) -> Option<InFile<SyntaxNode>> {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(macro_file) => {
let lazy_id = match macro_file.macro_call_id {
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(_id) => {
// FIXME: handle call node for eager macro
return None;
}
};
let loc = db.lookup_intern_macro(lazy_id);
Some(loc.kind.node(db))
}
HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
MacroCallId::LazyMacro(lazy_id) => {
let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id);
Some(loc.kind.node(db))
}
MacroCallId::EagerMacro(id) => {
let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id);
Some(loc.call.with_value(loc.call.to_node(db).syntax().clone()))
}
},
}
}
@ -304,7 +303,7 @@ pub struct EagerCallLoc {
pub(crate) fragment: FragmentKind,
pub(crate) subtree: Arc<tt::Subtree>,
pub(crate) krate: CrateId,
pub(crate) file_id: HirFileId,
pub(crate) call: AstId<ast::MacroCall>,
}
/// ExpansionInfo mainly describes how to map text range between src and expanded macro

View File

@ -749,6 +749,31 @@ fn test() {
);
}
#[test]
fn goto_through_included_file() {
check(
r#"
//- /main.rs
#[rustc_builtin_macro]
macro_rules! include {}
include!("foo.rs");
//^^^^^^^^^^^^^^^^^^^
fn f() {
foo<|>();
}
mod confuse_index {
pub fn foo() {}
}
//- /foo.rs
fn foo() {}
"#,
);
}
#[test]
fn goto_for_type_param() {
check(