collect macros

This commit is contained in:
Jake Heinz 2021-11-29 05:22:30 +00:00
parent d69e0dab56
commit 1ed5699355
4 changed files with 81 additions and 33 deletions

View file

@ -47,7 +47,7 @@ use hir_def::{
AttrDefId, ConstId, ConstParamId, EnumId, FunctionId, GenericDefId, HasModule, LifetimeParamId, AttrDefId, ConstId, ConstParamId, EnumId, FunctionId, GenericDefId, HasModule, LifetimeParamId,
LocalEnumVariantId, LocalFieldId, StaticId, StructId, TypeAliasId, TypeParamId, UnionId, LocalEnumVariantId, LocalFieldId, StaticId, StructId, TypeAliasId, TypeParamId, UnionId,
}; };
use hir_expand::{name::name, MacroCallKind, MacroDefId, MacroDefKind}; use hir_expand::{name::name, MacroCallKind, MacroDefKind};
use hir_ty::{ use hir_ty::{
autoderef, autoderef,
consteval::ConstExt, consteval::ConstExt,
@ -126,7 +126,7 @@ pub use {
}, },
hir_expand::{ hir_expand::{
name::{known, Name}, name::{known, Name},
ExpandResult, HirFileId, InFile, MacroFile, Origin, ExpandResult, HirFileId, InFile, MacroDefId, MacroFile, Origin,
}, },
hir_ty::display::HirDisplay, hir_ty::display::HirDisplay,
}; };

View file

@ -44,6 +44,8 @@ pub struct ItemScope {
/// The defs declared in this scope. Each def has a single scope where it is /// The defs declared in this scope. Each def has a single scope where it is
/// declared. /// declared.
declarations: Vec<ModuleDefId>, declarations: Vec<ModuleDefId>,
macro_declarations: Vec<MacroDefId>,
impls: Vec<ImplId>, impls: Vec<ImplId>,
unnamed_consts: Vec<ConstId>, unnamed_consts: Vec<ConstId>,
/// Traits imported via `use Trait as _;`. /// Traits imported via `use Trait as _;`.
@ -101,6 +103,10 @@ impl ItemScope {
self.declarations.iter().copied() self.declarations.iter().copied()
} }
pub fn macro_declarations(&self) -> impl Iterator<Item = MacroDefId> + '_ {
self.macro_declarations.iter().copied()
}
pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ { pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
self.impls.iter().copied() self.impls.iter().copied()
} }
@ -121,7 +127,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(crate) fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
self.legacy_macros.iter().map(|(name, def)| (name, *def)) self.legacy_macros.iter().map(|(name, def)| (name, *def))
} }
@ -163,6 +169,10 @@ impl ItemScope {
self.declarations.push(def) self.declarations.push(def)
} }
pub(crate) fn declare_macro(&mut self, def: MacroDefId) {
self.macro_declarations.push(def);
}
pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> { pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
self.legacy_macros.get(name).copied() self.legacy_macros.get(name).copied()
} }
@ -336,7 +346,8 @@ impl ItemScope {
values, values,
macros, macros,
unresolved, unresolved,
declarations: defs, declarations,
macro_declarations,
impls, impls,
unnamed_consts, unnamed_consts,
unnamed_trait_imports, unnamed_trait_imports,
@ -348,7 +359,8 @@ impl ItemScope {
values.shrink_to_fit(); values.shrink_to_fit();
macros.shrink_to_fit(); macros.shrink_to_fit();
unresolved.shrink_to_fit(); unresolved.shrink_to_fit();
defs.shrink_to_fit(); declarations.shrink_to_fit();
macro_declarations.shrink_to_fit();
impls.shrink_to_fit(); impls.shrink_to_fit();
unnamed_consts.shrink_to_fit(); unnamed_consts.shrink_to_fit();
unnamed_trait_imports.shrink_to_fit(); unnamed_trait_imports.shrink_to_fit();

View file

@ -632,6 +632,7 @@ impl DefCollector<'_> {
) { ) {
let vis = let vis =
self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public); self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
self.def_map.modules[module_id].scope.declare_macro(macro_);
self.update(module_id, &[(Some(name), PerNs::macros(macro_, vis))], vis, ImportType::Named); self.update(module_id, &[(Some(name), PerNs::macros(macro_, vis))], vis, ImportType::Named);
} }
@ -640,6 +641,7 @@ impl DefCollector<'_> {
/// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped. /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
/// And unconditionally exported. /// And unconditionally exported.
fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) {
self.def_map.modules[self.def_map.root].scope.declare_macro(macro_);
self.update( self.update(
self.def_map.root, self.def_map.root,
&[(Some(name), PerNs::macros(macro_, Visibility::Public))], &[(Some(name), PerNs::macros(macro_, Visibility::Public))],

View file

@ -32,10 +32,12 @@ use base_db::{
salsa::{self, ParallelDatabase}, salsa::{self, ParallelDatabase},
CrateId, FileId, FileRange, SourceDatabaseExt, SourceRootId, Upcast, CrateId, FileId, FileRange, SourceDatabaseExt, SourceRootId, Upcast,
}; };
use either::Either;
use fst::{self, Streamer}; use fst::{self, Streamer};
use hir::{ use hir::{
db::DefDatabase, AdtId, AssocContainerId, AssocItemId, AssocItemLoc, DefHasSource, db::{DefDatabase, HirDatabase},
DefWithBodyId, HirFileId, ImplId, InFile, ItemLoc, ItemTreeNode, Lookup, ModuleDefId, ModuleId, AdtId, AssocContainerId, AssocItemId, AssocItemLoc, DefHasSource, DefWithBodyId, HasSource,
HirFileId, ImplId, InFile, ItemLoc, ItemTreeNode, Lookup, MacroDef, ModuleDefId, ModuleId,
Semantics, TraitId, Semantics, TraitId,
}; };
use rayon::prelude::*; use rayon::prelude::*;
@ -94,7 +96,7 @@ impl Query {
} }
#[salsa::query_group(SymbolsDatabaseStorage)] #[salsa::query_group(SymbolsDatabaseStorage)]
pub trait SymbolsDatabase: hir::db::HirDatabase + SourceDatabaseExt { pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast<dyn HirDatabase> {
fn module_symbols(&self, module_id: ModuleId) -> Arc<SymbolIndex>; fn module_symbols(&self, module_id: ModuleId) -> Arc<SymbolIndex>;
fn library_symbols(&self) -> Arc<FxHashMap<SourceRootId, SymbolIndex>>; fn library_symbols(&self) -> Arc<FxHashMap<SourceRootId, SymbolIndex>>;
/// The set of "local" (that is, from the current workspace) roots. /// The set of "local" (that is, from the current workspace) roots.
@ -129,7 +131,7 @@ fn library_symbols(db: &dyn SymbolsDatabase) -> Arc<FxHashMap<SourceRootId, Symb
} }
fn module_symbols(db: &dyn SymbolsDatabase, module_id: ModuleId) -> Arc<SymbolIndex> { fn module_symbols(db: &dyn SymbolsDatabase, module_id: ModuleId) -> Arc<SymbolIndex> {
let symbols = SymbolCollector::collect(db.upcast(), module_id); let symbols = SymbolCollector::collect(db, module_id);
Arc::new(SymbolIndex::new(symbols)) Arc::new(SymbolIndex::new(symbols))
} }
@ -205,10 +207,6 @@ pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<Fil
.map_with(snap, |snap, &module_id| snap.0.module_symbols(module_id)) .map_with(snap, |snap, &module_id| snap.0.module_symbols(module_id))
.collect(); .collect();
for i in &buf {
dbg!(&i.symbols);
}
let buf = buf.iter().map(|it| &**it).collect::<Vec<_>>(); let buf = buf.iter().map(|it| &**it).collect::<Vec<_>>();
query.search(&buf) query.search(&buf)
} }
@ -446,14 +444,16 @@ enum SymbolCollectorWorkItem {
} }
struct SymbolCollector<'a> { struct SymbolCollector<'a> {
db: &'a dyn DefDatabase, db: &'a dyn SymbolsDatabase,
symbols: Vec<FileSymbol>, symbols: Vec<FileSymbol>,
work: Vec<SymbolCollectorWorkItem>, work: Vec<SymbolCollectorWorkItem>,
container_name_stack: Vec<SmolStr>, container_name_stack: Vec<SmolStr>,
} }
/// Given a [`ModuleId`] and a [`SymbolsDatabase`], use the DefMap for the module's crate to collect all symbols that should be
/// indexed for the given module.
impl<'a> SymbolCollector<'a> { impl<'a> SymbolCollector<'a> {
fn collect(db: &dyn DefDatabase, module_id: ModuleId) -> Vec<FileSymbol> { fn collect(db: &dyn SymbolsDatabase, module_id: ModuleId) -> Vec<FileSymbol> {
let mut symbol_collector = SymbolCollector { let mut symbol_collector = SymbolCollector {
db, db,
symbols: Default::default(), symbols: Default::default(),
@ -486,10 +486,12 @@ impl<'a> SymbolCollector<'a> {
} }
fn collect_from_module(&mut self, module_id: ModuleId) { fn collect_from_module(&mut self, module_id: ModuleId) {
let def_map = module_id.def_map(self.db); let def_map = module_id.def_map(self.db.upcast());
let module_data = &def_map[module_id.local_id]; let module_data = &def_map[module_id.local_id];
let scope = &module_data.scope; let scope = &module_data.scope;
dbg!(scope);
for module_def_id in scope.declarations() { for module_def_id in scope.declarations() {
match module_def_id { match module_def_id {
ModuleDefId::ModuleId(id) => self.push_module(id), ModuleDefId::ModuleId(id) => self.push_module(id),
@ -531,14 +533,23 @@ impl<'a> SymbolCollector<'a> {
self.work.push(SymbolCollectorWorkItem::Body { body: const_id.into() }) self.work.push(SymbolCollectorWorkItem::Body { body: const_id.into() })
} }
// todo: collect macros. // Collect legacy macros from the root module only:
if module_data.parent.is_none() {
for (_, macro_def_id) in scope.legacy_macros() {
self.push_decl_macro(macro_def_id.into());
}
}
for macro_def_id in scope.macro_declarations() {
self.push_decl_macro(macro_def_id.into());
}
} }
fn collect_from_body(&mut self, body_id: DefWithBodyId) { fn collect_from_body(&mut self, body_id: DefWithBodyId) {
let body = self.db.body(body_id); let body = self.db.body(body_id);
// Descend into the blocks and enqueue collection of all modules within. // Descend into the blocks and enqueue collection of all modules within.
for (_, def_map) in body.blocks(self.db) { for (_, def_map) in body.blocks(self.db.upcast()) {
for (id, _) in def_map.modules() { for (id, _) in def_map.modules() {
self.work.push(SymbolCollectorWorkItem::Module { self.work.push(SymbolCollectorWorkItem::Module {
module_id: def_map.module_id(id), module_id: def_map.module_id(id),
@ -578,15 +589,15 @@ impl<'a> SymbolCollector<'a> {
fn def_with_body_id_name(&self, body_id: DefWithBodyId) -> Option<SmolStr> { fn def_with_body_id_name(&self, body_id: DefWithBodyId) -> Option<SmolStr> {
match body_id { match body_id {
DefWithBodyId::FunctionId(id) => { DefWithBodyId::FunctionId(id) => Some(
Some(id.lookup(self.db).source(self.db).value.name()?.text().into()) id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
} ),
DefWithBodyId::StaticId(id) => { DefWithBodyId::StaticId(id) => Some(
Some(id.lookup(self.db).source(self.db).value.name()?.text().into()) id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
} ),
DefWithBodyId::ConstId(id) => { DefWithBodyId::ConstId(id) => Some(
Some(id.lookup(self.db).source(self.db).value.name()?.text().into()) id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
} ),
} }
} }
@ -624,11 +635,11 @@ impl<'a> SymbolCollector<'a> {
} }
self.push_file_symbol(|s| { self.push_file_symbol(|s| {
let loc = id.lookup(s.db); let loc = id.lookup(s.db.upcast());
let source = loc.source(s.db); let source = loc.source(s.db.upcast());
let name_node = source.value.name()?; let name_node = source.value.name()?;
let container_name = let container_name =
container_name(s.db, loc.container).or_else(|| s.current_container_name()); container_name(s.db.upcast(), loc.container).or_else(|| s.current_container_name());
Some(FileSymbol { Some(FileSymbol {
name: name_node.text().into(), name: name_node.text().into(),
@ -650,8 +661,8 @@ impl<'a> SymbolCollector<'a> {
<T as ItemTreeNode>::Source: HasName, <T as ItemTreeNode>::Source: HasName,
{ {
self.push_file_symbol(|s| { self.push_file_symbol(|s| {
let loc = id.lookup(s.db); let loc = id.lookup(s.db.upcast());
let source = loc.source(s.db); let source = loc.source(s.db.upcast());
let name_node = source.value.name()?; let name_node = source.value.name()?;
Some(FileSymbol { Some(FileSymbol {
@ -669,7 +680,7 @@ impl<'a> SymbolCollector<'a> {
fn push_module(&mut self, module_id: ModuleId) { fn push_module(&mut self, module_id: ModuleId) {
self.push_file_symbol(|s| { self.push_file_symbol(|s| {
let def_map = module_id.def_map(s.db); let def_map = module_id.def_map(s.db.upcast());
let module_data = &def_map[module_id.local_id]; let module_data = &def_map[module_id.local_id];
let declaration = module_data.origin.declaration()?; let declaration = module_data.origin.declaration()?;
let module = declaration.to_node(s.db.upcast()); let module = declaration.to_node(s.db.upcast());
@ -688,6 +699,29 @@ impl<'a> SymbolCollector<'a> {
}) })
} }
pub(crate) fn push_decl_macro(&mut self, macro_def: MacroDef) {
self.push_file_symbol(|s| {
let name = macro_def.name(s.db.upcast())?.as_text()?;
let source = macro_def.source(s.db.upcast())?;
let (ptr, name_ptr) = match source.value {
Either::Left(m) => {
(SyntaxNodePtr::new(m.syntax()), SyntaxNodePtr::new(m.name()?.syntax()))
}
Either::Right(f) => {
(SyntaxNodePtr::new(f.syntax()), SyntaxNodePtr::new(f.name()?.syntax()))
}
};
Some(FileSymbol {
name,
kind: FileSymbolKind::Macro,
container_name: s.current_container_name(),
loc: DeclarationLocation { hir_file_id: source.file_id, name_ptr, ptr },
})
})
}
fn push_file_symbol(&mut self, f: impl FnOnce(&Self) -> Option<FileSymbol>) { fn push_file_symbol(&mut self, f: impl FnOnce(&Self) -> Option<FileSymbol>) {
if let Some(file_symbol) = f(self) { if let Some(file_symbol) = f(self) {
self.symbols.push(file_symbol); self.symbols.push(file_symbol);