mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-01 15:58:47 +00:00
Let macro_use
bypass module scope
This commit is contained in:
parent
a66214b34e
commit
0d23286caf
2 changed files with 52 additions and 35 deletions
|
@ -166,6 +166,33 @@ where
|
||||||
self.global_macro_scope.insert(name, macro_id);
|
self.global_macro_scope.insert(name, macro_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Import macros from `#[macro_use] extern crate`.
|
||||||
|
///
|
||||||
|
/// They are non-scoped, and will only be inserted into mutable `global_macro_scope`.
|
||||||
|
fn import_macros_from_extern_crate(&mut self, import: &raw::ImportData) {
|
||||||
|
log::debug!(
|
||||||
|
"importing macros from extern crate: {:?} ({:?})",
|
||||||
|
import,
|
||||||
|
self.def_map.edition,
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = self.def_map.resolve_name_in_extern_prelude(
|
||||||
|
&import
|
||||||
|
.path
|
||||||
|
.as_ident()
|
||||||
|
.expect("extern crate should have been desugared to one-element path"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(ModuleDef::Module(m)) = res.take_types() {
|
||||||
|
tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
|
||||||
|
|
||||||
|
let item_map = self.db.crate_def_map(m.krate);
|
||||||
|
for (name, ¯o_id) in &item_map.exported_macros {
|
||||||
|
self.global_macro_scope.insert(name.clone(), macro_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_imports(&mut self) -> ReachedFixedPoint {
|
fn resolve_imports(&mut self) -> ReachedFixedPoint {
|
||||||
let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
|
let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
|
||||||
let mut resolved = Vec::new();
|
let mut resolved = Vec::new();
|
||||||
|
@ -299,21 +326,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `#[macro_use] extern crate` glob imports all macros exported,
|
|
||||||
// ignoring their scopes
|
|
||||||
if import.is_extern_crate && import.is_macro_use {
|
|
||||||
if let Some(ModuleDef::Module(m)) =
|
|
||||||
def.a().and_then(|item| item.take_types())
|
|
||||||
{
|
|
||||||
tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
|
|
||||||
|
|
||||||
let item_map = self.db.crate_def_map(m.krate);
|
|
||||||
for (name, ¯o_id) in &item_map.exported_macros {
|
|
||||||
self.define_macro(module_id, name.clone(), macro_id, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let resolution = match def {
|
let resolution = match def {
|
||||||
Either::A(item) => {
|
Either::A(item) => {
|
||||||
Either::A(Resolution { def: item, import: Some(import_id) })
|
Either::A(Resolution { def: item, import: Some(import_id) })
|
||||||
|
@ -513,11 +525,17 @@ where
|
||||||
for item in items {
|
for item in items {
|
||||||
match *item {
|
match *item {
|
||||||
raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]),
|
raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]),
|
||||||
raw::RawItem::Import(import) => self.def_collector.unresolved_imports.push((
|
raw::RawItem::Import(import_id) => {
|
||||||
self.module_id,
|
let import = self.raw_items[import_id].clone();
|
||||||
import,
|
// This should be processed eagerly instead of deferred to resolving.
|
||||||
self.raw_items[import].clone(),
|
// Otherwise, since it will only mutate `global_macro_scope`
|
||||||
)),
|
// without `update` names in `mod`s, unresolved macros cannot be expanded.
|
||||||
|
if import.is_extern_crate && import.is_macro_use {
|
||||||
|
self.def_collector.import_macros_from_extern_crate(&import);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.def_collector.unresolved_imports.push((self.module_id, import_id, import));
|
||||||
|
}
|
||||||
raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]),
|
raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]),
|
||||||
raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
|
raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,25 +147,31 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate foo;
|
extern crate foo;
|
||||||
|
|
||||||
structs!(Foo, Bar)
|
structs!(Foo);
|
||||||
|
structs_priv!(Bar);
|
||||||
|
structs_not_exported!(MacroNotResolved1);
|
||||||
|
crates::structs!(MacroNotResolved2);
|
||||||
|
|
||||||
mod bar;
|
mod bar;
|
||||||
|
|
||||||
//- /bar.rs
|
//- /bar.rs
|
||||||
use crate::*;
|
structs!(Baz);
|
||||||
|
crates::structs!(MacroNotResolved3);
|
||||||
|
|
||||||
//- /lib.rs
|
//- /lib.rs
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! structs {
|
macro_rules! structs {
|
||||||
($($i:ident),*) => {
|
($i:ident) => { struct $i; }
|
||||||
$(struct $i { field: u32 } )*
|
}
|
||||||
}
|
|
||||||
|
macro_rules! structs_not_exported {
|
||||||
|
($i:ident) => { struct $i; }
|
||||||
}
|
}
|
||||||
|
|
||||||
mod priv_mod {
|
mod priv_mod {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! baz {
|
macro_rules! structs_priv {
|
||||||
() => {};
|
($i:ident) => { struct $i; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
|
@ -179,16 +185,9 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
|
||||||
⋮Bar: t v
|
⋮Bar: t v
|
||||||
⋮Foo: t v
|
⋮Foo: t v
|
||||||
⋮bar: t
|
⋮bar: t
|
||||||
⋮baz: m
|
|
||||||
⋮foo: t
|
⋮foo: t
|
||||||
⋮structs: m
|
|
||||||
⋮
|
⋮
|
||||||
⋮crate::bar
|
⋮crate::bar
|
||||||
⋮Bar: t v
|
⋮Baz: t v
|
||||||
⋮Foo: t v
|
|
||||||
⋮bar: t
|
|
||||||
⋮baz: m
|
|
||||||
⋮foo: t
|
|
||||||
⋮structs: m
|
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue