Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #14561 - jonas-schievink:goto-included-file, r=Veykril
feat: Map tokens from `include!` expansion to the included file Fixes https://github.com/rust-lang/rust-analyzer/issues/3767
bors 2023-04-13
parent 1605911 · parent 901c8a4 · commit 08ce44e
-rw-r--r--crates/hir-expand/src/builtin_fn_macro.rs14
-rw-r--r--crates/hir-expand/src/db.rs22
-rw-r--r--crates/hir-expand/src/lib.rs17
-rw-r--r--crates/ide/src/goto_definition.rs4
4 files changed, 37 insertions, 20 deletions
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 44510f2b7f..08c924d0e9 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -3,7 +3,7 @@
use base_db::{AnchoredPath, Edition, FileId};
use cfg::CfgExpr;
use either::Either;
-use mbe::{parse_exprs_with_sep, parse_to_token_tree};
+use mbe::{parse_exprs_with_sep, parse_to_token_tree, TokenMap};
use syntax::{
ast::{self, AstToken},
SmolStr,
@@ -67,7 +67,7 @@ macro_rules! register_builtin {
pub struct ExpandedEager {
pub(crate) subtree: tt::Subtree,
/// The included file ID of the include macro.
- pub(crate) included_file: Option<FileId>,
+ pub(crate) included_file: Option<(FileId, TokenMap)>,
}
impl ExpandedEager {
@@ -566,14 +566,14 @@ fn include_expand(
let path = parse_string(tt)?;
let file_id = relative_file(db, arg_id, &path, false)?;
- let subtree =
- parse_to_token_tree(&db.file_text(file_id)).ok_or(mbe::ExpandError::ConversionError)?.0;
- Ok((subtree, file_id))
+ let (subtree, map) =
+ parse_to_token_tree(&db.file_text(file_id)).ok_or(mbe::ExpandError::ConversionError)?;
+ Ok((subtree, map, file_id))
})();
match res {
- Ok((subtree, file_id)) => {
- ExpandResult::ok(ExpandedEager { subtree, included_file: Some(file_id) })
+ Ok((subtree, map, file_id)) => {
+ ExpandResult::ok(ExpandedEager { subtree, included_file: Some((file_id, map)) })
}
Err(e) => ExpandResult::with_err(
ExpandedEager { subtree: tt::Subtree::empty(), included_file: None },
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index 45572499e8..37c3661540 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -13,10 +13,11 @@ use syntax::{
};
use crate::{
- ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion, fixup,
- hygiene::HygieneFrame, tt, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander,
- ExpandError, ExpandResult, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind,
- MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
+ ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion,
+ builtin_fn_macro::EagerExpander, fixup, hygiene::HygieneFrame, tt, BuiltinAttrExpander,
+ BuiltinDeriveExpander, BuiltinFnLikeExpander, ExpandError, ExpandResult, ExpandTo, HirFileId,
+ HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile,
+ ProcMacroExpander,
};
/// Total limit on the number of tokens produced by any macro invocation.
@@ -33,6 +34,8 @@ pub enum TokenExpander {
DeclarativeMacro { mac: mbe::DeclarativeMacro, def_site_token_map: mbe::TokenMap },
/// Stuff like `line!` and `file!`.
Builtin(BuiltinFnLikeExpander),
+ /// Built-in eagerly expanded fn-like macros (`include!`, `concat!`, etc.)
+ BuiltinEager(EagerExpander),
/// `global_allocator` and such.
BuiltinAttr(BuiltinAttrExpander),
/// `derive(Copy)` and such.
@@ -51,6 +54,9 @@ impl TokenExpander {
match self {
TokenExpander::DeclarativeMacro { mac, .. } => mac.expand(tt).map_err(Into::into),
TokenExpander::Builtin(it) => it.expand(db, id, tt).map_err(Into::into),
+ TokenExpander::BuiltinEager(it) => {
+ it.expand(db, id, tt).map_err(Into::into).map(|res| res.subtree)
+ }
TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt),
TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt),
TokenExpander::ProcMacro(_) => {
@@ -66,6 +72,7 @@ impl TokenExpander {
match self {
TokenExpander::DeclarativeMacro { mac, .. } => mac.map_id_down(id),
TokenExpander::Builtin(..)
+ | TokenExpander::BuiltinEager(..)
| TokenExpander::BuiltinAttr(..)
| TokenExpander::BuiltinDerive(..)
| TokenExpander::ProcMacro(..) => id,
@@ -76,6 +83,7 @@ impl TokenExpander {
match self {
TokenExpander::DeclarativeMacro { mac, .. } => mac.map_id_up(id),
TokenExpander::Builtin(..)
+ | TokenExpander::BuiltinEager(..)
| TokenExpander::BuiltinAttr(..)
| TokenExpander::BuiltinDerive(..)
| TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
@@ -412,10 +420,8 @@ fn macro_def(
MacroDefKind::BuiltInDerive(expander, _) => {
Ok(Arc::new(TokenExpander::BuiltinDerive(expander)))
}
- MacroDefKind::BuiltInEager(..) => {
- // FIXME: Return a random error here just to make the types align.
- // This obviously should do something real instead.
- Err(mbe::ParseError::UnexpectedToken("unexpected eager macro".into()))
+ MacroDefKind::BuiltInEager(expander, ..) => {
+ Ok(Arc::new(TokenExpander::BuiltinEager(expander)))
}
MacroDefKind::ProcMacro(expander, ..) => Ok(Arc::new(TokenExpander::ProcMacro(expander))),
}
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 929dabcaf6..d26fdbf7d6 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -20,6 +20,7 @@ pub mod mod_path;
pub mod attrs;
mod fixup;
+use mbe::TokenMap;
pub use mbe::{Origin, ValueResult};
use ::tt::token_id as tt;
@@ -139,7 +140,7 @@ pub enum MacroDefKind {
struct EagerCallInfo {
/// NOTE: This can be *either* the expansion result, *or* the argument to the eager macro!
arg_or_expansion: Arc<tt::Subtree>,
- included_file: Option<FileId>,
+ included_file: Option<(FileId, TokenMap)>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -206,7 +207,7 @@ impl HirFileId {
HirFileIdRepr::MacroFile(MacroFile { macro_call_id }) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_call_id);
file_id = match loc.eager {
- Some(EagerCallInfo { included_file: Some(file), .. }) => file.into(),
+ Some(EagerCallInfo { included_file: Some((file, _)), .. }) => file.into(),
_ => loc.kind.file_id(),
};
}
@@ -319,7 +320,7 @@ impl HirFileId {
match self.macro_file() {
Some(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
- matches!(loc.eager, Some(EagerCallInfo { included_file: Some(_), .. }))
+ matches!(loc.eager, Some(EagerCallInfo { included_file: Some(..), .. }))
}
_ => false,
}
@@ -677,6 +678,16 @@ impl ExpansionInfo {
let call_id = self.expanded.file_id.macro_file()?.macro_call_id;
let loc = db.lookup_intern_macro_call(call_id);
+ if let Some((file, map)) = loc.eager.and_then(|e| e.included_file) {
+ // Special case: map tokens from `include!` expansions to the included file
+ let range = map.first_range_by_token(token_id, token.value.kind())?;
+ let source = db.parse(file);
+
+ let token = source.syntax_node().covering_element(range).into_token()?;
+
+ return Some((InFile::new(file.into(), token), Origin::Call));
+ }
+
// Attributes are a bit special for us, they have two inputs, the input tokentree and the annotated item.
let (token_map, tt) = match &loc.kind {
MacroCallKind::Attr { attr_args, is_derive: true, .. } => {
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index cf0819a252..004c33a8a7 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -833,8 +833,7 @@ fn test() {
#[rustc_builtin_macro]
macro_rules! include {}
- include!("foo.rs");
-//^^^^^^^^^^^^^^^^^^^
+include!("foo.rs");
fn f() {
foo$0();
@@ -846,6 +845,7 @@ mod confuse_index {
//- /foo.rs
fn foo() {}
+ //^^^
"#,
);
}