mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 07:04:49 +00:00
Expand more single ident macro calls upon their collection
This commit is contained in:
parent
f2a35deb50
commit
e9ddb62c65
3 changed files with 61 additions and 15 deletions
|
@ -44,7 +44,8 @@ use crate::{
|
||||||
mod_resolution::ModDir,
|
mod_resolution::ModDir,
|
||||||
path_resolution::ReachedFixedPoint,
|
path_resolution::ReachedFixedPoint,
|
||||||
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
|
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
|
||||||
BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
|
sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin,
|
||||||
|
ResolveMode,
|
||||||
},
|
},
|
||||||
path::{ImportAlias, ModPath, PathKind},
|
path::{ImportAlias, ModPath, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
|
@ -2141,26 +2142,34 @@ impl ModCollector<'_, '_> {
|
||||||
|
|
||||||
fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
|
fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
|
||||||
let ast_id = AstIdWithPath::new(self.file_id(), mac.ast_id, ModPath::clone(&mac.path));
|
let ast_id = AstIdWithPath::new(self.file_id(), mac.ast_id, ModPath::clone(&mac.path));
|
||||||
|
let db = self.def_collector.db;
|
||||||
|
|
||||||
// Case 1: try to resolve in legacy scope and expand macro_rules
|
// FIXME: Immediately expanding in "Case 1" is insufficient since "Case 2" may also define
|
||||||
|
// new legacy macros that create textual scopes. We need a way to resolve names in textual
|
||||||
|
// scopes without eager expansion.
|
||||||
|
|
||||||
|
// Case 1: try to resolve macro calls with single-segment name and expand macro_rules
|
||||||
if let Ok(res) = macro_call_as_call_id(
|
if let Ok(res) = macro_call_as_call_id(
|
||||||
self.def_collector.db.upcast(),
|
db.upcast(),
|
||||||
&ast_id,
|
&ast_id,
|
||||||
mac.expand_to,
|
mac.expand_to,
|
||||||
self.def_collector.def_map.krate,
|
self.def_collector.def_map.krate,
|
||||||
|path| {
|
|path| {
|
||||||
path.as_ident().and_then(|name| {
|
path.as_ident().and_then(|name| {
|
||||||
self.def_collector.def_map.with_ancestor_maps(
|
let def_map = &self.def_collector.def_map;
|
||||||
self.def_collector.db,
|
def_map
|
||||||
self.module_id,
|
.with_ancestor_maps(db, self.module_id, &mut |map, module| {
|
||||||
&mut |map, module| {
|
map[module].scope.get_legacy_macro(name)?.last().copied()
|
||||||
map[module]
|
})
|
||||||
.scope
|
.or_else(|| def_map[self.module_id].scope.get(name).take_macros())
|
||||||
.get_legacy_macro(name)
|
.or_else(|| def_map.macro_use_prelude.get(name).copied())
|
||||||
.and_then(|it| it.last())
|
.filter(|&id| {
|
||||||
.map(|&it| macro_id_to_def_id(self.def_collector.db, it))
|
sub_namespace_match(
|
||||||
},
|
Some(MacroSubNs::from_id(db, id)),
|
||||||
)
|
Some(MacroSubNs::Bang),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|it| macro_id_to_def_id(self.def_collector.db, it))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -59,7 +59,11 @@ impl ResolvePathResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PerNs {
|
impl PerNs {
|
||||||
fn filter_macro(mut self, db: &dyn DefDatabase, expected: Option<MacroSubNs>) -> Self {
|
pub(super) fn filter_macro(
|
||||||
|
mut self,
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
expected: Option<MacroSubNs>,
|
||||||
|
) -> Self {
|
||||||
self.macros = self.macros.filter(|&(id, _)| {
|
self.macros = self.macros.filter(|&(id, _)| {
|
||||||
let this = MacroSubNs::from_id(db, id);
|
let this = MacroSubNs::from_id(db, id);
|
||||||
sub_namespace_match(Some(this), expected)
|
sub_namespace_match(Some(this), expected)
|
||||||
|
|
|
@ -1272,6 +1272,39 @@ pub mod prelude {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn macro_use_prelude_is_eagerly_expanded() {
|
||||||
|
// See FIXME in `ModCollector::collect_macro_call()`.
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- /main.rs crate:main deps:lib
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lib;
|
||||||
|
mk_foo!();
|
||||||
|
mod a {
|
||||||
|
foo!();
|
||||||
|
}
|
||||||
|
//- /lib.rs crate:lib
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! mk_foo {
|
||||||
|
() => {
|
||||||
|
macro_rules! foo {
|
||||||
|
() => { struct Ok; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
crate
|
||||||
|
a: t
|
||||||
|
lib: t
|
||||||
|
|
||||||
|
crate::a
|
||||||
|
Ok: t v
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_sub_namespace() {
|
fn macro_sub_namespace() {
|
||||||
let map = compute_crate_def_map(
|
let map = compute_crate_def_map(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue