mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
fix: properly import all types of macros with #[macro_use] again
This commit is contained in:
parent
0b3daef537
commit
18ad750786
5 changed files with 59 additions and 20 deletions
|
@ -3,7 +3,7 @@
|
||||||
use base_db::FileRange;
|
use base_db::FileRange;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId,
|
item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId,
|
||||||
ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
|
HasModule, ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
|
||||||
};
|
};
|
||||||
use hir_expand::{HirFileId, InFile};
|
use hir_expand::{HirFileId, InFile};
|
||||||
use hir_ty::db::HirDatabase;
|
use hir_ty::db::HirDatabase;
|
||||||
|
@ -176,9 +176,12 @@ impl<'a> SymbolCollector<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (_, id) in scope.legacy_macros() {
|
for (_, id) in scope.legacy_macros() {
|
||||||
let loc = id.lookup(self.db.upcast());
|
if id.module(self.db.upcast()) == module_id {
|
||||||
if loc.container == module_id {
|
match id {
|
||||||
self.push_decl(id, FileSymbolKind::Macro);
|
MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
|
||||||
|
MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
|
||||||
|
MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,9 +103,11 @@ impl ChildBySource for ItemScope {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.legacy_macros().for_each(|(_, id)| {
|
self.legacy_macros().for_each(|(_, id)| {
|
||||||
let loc = id.lookup(db);
|
if let MacroId::MacroRulesId(id) = id {
|
||||||
if loc.id.file_id() == file_id {
|
let loc = id.lookup(db);
|
||||||
res[keys::MACRO_RULES].insert(loc.source(db).value, id);
|
if loc.id.file_id() == file_id {
|
||||||
|
res[keys::MACRO_RULES].insert(loc.source(db).value, id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
|
self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
|
||||||
|
|
|
@ -14,8 +14,7 @@ use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
attr::AttrId, db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType,
|
attr::AttrId, db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType,
|
||||||
ConstId, HasModule, ImplId, LocalModuleId, MacroId, MacroRulesId, ModuleDefId, ModuleId,
|
ConstId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
|
||||||
TraitId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -62,7 +61,7 @@ pub struct ItemScope {
|
||||||
/// Module scoped macros will be inserted into `items` instead of here.
|
/// Module scoped macros will be inserted into `items` instead of here.
|
||||||
// FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
|
// FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
|
||||||
// be all resolved to the last one defined if shadowing happens.
|
// be all resolved to the last one defined if shadowing happens.
|
||||||
legacy_macros: FxHashMap<Name, MacroRulesId>,
|
legacy_macros: FxHashMap<Name, MacroId>,
|
||||||
/// The derive macro invocations in this scope.
|
/// The derive macro invocations in this scope.
|
||||||
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
|
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
|
||||||
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
|
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
|
||||||
|
@ -135,7 +134,7 @@ impl ItemScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all legacy textual scoped macros visible at the end of the module
|
/// Iterate over all legacy textual scoped macros visible at the end of the module
|
||||||
pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroRulesId)> + 'a {
|
pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroId)> + 'a {
|
||||||
self.legacy_macros.iter().map(|(name, def)| (name, *def))
|
self.legacy_macros.iter().map(|(name, def)| (name, *def))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +180,7 @@ impl ItemScope {
|
||||||
self.declarations.push(def)
|
self.declarations.push(def)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroRulesId> {
|
pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroId> {
|
||||||
self.legacy_macros.get(name).copied()
|
self.legacy_macros.get(name).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +192,7 @@ impl ItemScope {
|
||||||
self.unnamed_consts.push(konst);
|
self.unnamed_consts.push(konst);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroRulesId) {
|
pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroId) {
|
||||||
self.legacy_macros.insert(name, mac);
|
self.legacy_macros.insert(name, mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +322,7 @@ impl ItemScope {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroRulesId> {
|
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroId> {
|
||||||
self.legacy_macros.clone()
|
self.legacy_macros.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -610,7 +610,7 @@ impl DefCollector<'_> {
|
||||||
export: bool,
|
export: bool,
|
||||||
) {
|
) {
|
||||||
// Textual scoping
|
// Textual scoping
|
||||||
self.define_legacy_macro(module_id, name.clone(), macro_);
|
self.define_legacy_macro(module_id, name.clone(), macro_.into());
|
||||||
|
|
||||||
// Module scoping
|
// Module scoping
|
||||||
// In Rust, `#[macro_export]` macros are unconditionally visible at the
|
// In Rust, `#[macro_export]` macros are unconditionally visible at the
|
||||||
|
@ -634,7 +634,7 @@ impl DefCollector<'_> {
|
||||||
/// the definition of current module.
|
/// the definition of current module.
|
||||||
/// And also, `macro_use` on a module will import all legacy macros visible inside to
|
/// And also, `macro_use` on a module will import all legacy macros visible inside to
|
||||||
/// current legacy scope, with possible shadowing.
|
/// current legacy scope, with possible shadowing.
|
||||||
fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroRulesId) {
|
fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroId) {
|
||||||
// Always shadowing
|
// Always shadowing
|
||||||
self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
|
self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
|
||||||
}
|
}
|
||||||
|
@ -706,10 +706,8 @@ impl DefCollector<'_> {
|
||||||
fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
|
fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
|
||||||
let def_map = self.db.crate_def_map(krate);
|
let def_map = self.db.crate_def_map(krate);
|
||||||
for (name, def) in def_map[def_map.root].scope.macros() {
|
for (name, def) in def_map[def_map.root].scope.macros() {
|
||||||
if let MacroId::MacroRulesId(def) = def {
|
// `#[macro_use]` brings macros into legacy scope. Yes, even non-`macro_rules!` macros.
|
||||||
// `macro_use` only bring things into legacy scope.
|
self.define_legacy_macro(current_module_id, name.clone(), def);
|
||||||
self.define_legacy_macro(current_module_id, name.clone(), def);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1143,3 +1143,40 @@ struct A;
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn macro_use_imports_all_macro_types() {
|
||||||
|
let def_map = compute_crate_def_map(
|
||||||
|
r#"
|
||||||
|
//- /main.rs crate:main deps:lib
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lib;
|
||||||
|
|
||||||
|
//- /lib.rs crate:lib deps:proc
|
||||||
|
pub use proc::*;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! legacy { () => () }
|
||||||
|
|
||||||
|
pub macro macro20 {}
|
||||||
|
|
||||||
|
//- /proc.rs crate:proc
|
||||||
|
#![crate_type="proc-macro"]
|
||||||
|
|
||||||
|
struct TokenStream;
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
let root = &def_map[def_map.root()].scope;
|
||||||
|
let actual = root.legacy_macros().map(|(name, _)| format!("{name}\n")).collect::<String>();
|
||||||
|
|
||||||
|
expect![[r#"
|
||||||
|
macro20
|
||||||
|
legacy
|
||||||
|
proc_attr
|
||||||
|
"#]]
|
||||||
|
.assert_eq(&actual);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue