1 //! The core of the module-level name resolution algorithm.
3 //! `DefCollector::collect` contains the fixed-point iteration loop which
4 //! resolves imports and expands macros.
7 builtin_derive::find_builtin_derive,
8 builtin_macro::find_builtin_macro,
9 name::{name, AsName, Name},
10 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
12 use ra_cfg::CfgOptions;
13 use ra_db::{CrateId, FileId};
15 use rustc_hash::FxHashMap;
16 use test_utils::tested_by;
21 item_scope::Resolution,
23 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
24 raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
26 path::{ModPath, PathKind},
28 AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
29 LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc,
30 TypeAliasLoc, UnionLoc,
33 pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
34 let crate_graph = db.crate_graph();
36 // populate external prelude
37 for dep in crate_graph.dependencies(def_map.krate) {
38 let dep_def_map = db.crate_def_map(dep.crate_id);
39 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
40 def_map.extern_prelude.insert(
42 ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(),
45 // look for the prelude
46 // If the dependency defines a prelude, we overwrite an already defined
47 // prelude. This is necessary to import the "std" prelude if a crate
48 // depends on both "core" and "std".
49 let dep_def_map = db.crate_def_map(dep.crate_id);
50 if dep_def_map.prelude.is_some() {
51 def_map.prelude = dep_def_map.prelude;
55 let cfg_options = crate_graph.cfg_options(def_map.krate);
57 let mut collector = DefCollector {
60 glob_imports: FxHashMap::default(),
61 unresolved_imports: Vec::new(),
62 resolved_imports: Vec::new(),
64 unexpanded_macros: Vec::new(),
65 unexpanded_attribute_macros: Vec::new(),
66 mod_dirs: FxHashMap::default(),
73 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
74 enum PartialResolvedImport {
75 /// None of any namespaces is resolved
77 /// One of namespaces is resolved
79 /// All namespaces are resolved, OR it is came from other crate
83 impl PartialResolvedImport {
84 fn namespaces(&self) -> PerNs {
86 PartialResolvedImport::Unresolved => PerNs::none(),
87 PartialResolvedImport::Indeterminate(ns) => *ns,
88 PartialResolvedImport::Resolved(ns) => *ns,
93 #[derive(Clone, Debug, Eq, PartialEq)]
94 struct ImportDirective {
95 module_id: LocalModuleId,
96 import_id: LocalImportId,
97 import: raw::ImportData,
98 status: PartialResolvedImport,
101 #[derive(Clone, Debug, Eq, PartialEq)]
102 struct MacroDirective {
103 module_id: LocalModuleId,
104 ast_id: AstId<ast::MacroCall>,
106 legacy: Option<MacroCallId>,
109 /// Walks the tree of module recursively
110 struct DefCollector<'a, DB> {
112 def_map: CrateDefMap,
113 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
114 unresolved_imports: Vec<ImportDirective>,
115 resolved_imports: Vec<ImportDirective>,
116 unexpanded_macros: Vec<MacroDirective>,
117 unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, ModPath)>,
118 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
119 cfg_options: &'a CfgOptions,
122 impl<DB> DefCollector<'_, DB>
126 fn collect(&mut self) {
127 let crate_graph = self.db.crate_graph();
128 let file_id = crate_graph.crate_root(self.def_map.krate);
129 let raw_items = self.db.raw_items(file_id.into());
130 let module_id = self.def_map.root;
131 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
133 def_collector: &mut *self,
135 file_id: file_id.into(),
136 raw_items: &raw_items,
137 mod_dir: ModDir::root(),
139 .collect(raw_items.items());
141 // main name resolution fixed-point loop.
144 self.db.check_canceled();
145 self.resolve_imports();
147 match self.resolve_macros() {
148 ReachedFixedPoint::Yes => break,
149 ReachedFixedPoint::No => i += 1,
152 log::error!("name resolution is stuck");
157 // Resolve all indeterminate resolved imports again
158 // As some of the macros will expand newly import shadowing partial resolved imports
159 // FIXME: We maybe could skip this, if we handle the Indetermine imports in `resolve_imports`
161 let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
162 if let PartialResolvedImport::Indeterminate(_) = directive.status {
163 let mut directive = directive.clone();
164 directive.status = PartialResolvedImport::Unresolved;
170 self.unresolved_imports.extend(partial_resolved);
171 self.resolve_imports();
173 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
174 // show unresolved imports in completion, etc
175 for directive in unresolved_imports {
176 self.record_resolved_import(&directive)
180 /// Define a macro with `macro_rules`.
182 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
183 /// then it is also defined in the root module scope.
184 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
186 /// It is surprising that the macro will never be in the current module scope.
187 /// These code fails with "unresolved import/macro",
188 /// ```rust,compile_fail
189 /// mod m { macro_rules! foo { () => {} } }
190 /// use m::foo as bar;
193 /// ```rust,compile_fail
194 /// macro_rules! foo { () => {} }
199 /// Well, this code compiles, because the plain path `foo` in `use` is searched
200 /// in the legacy textual scope only.
202 /// macro_rules! foo { () => {} }
207 module_id: LocalModuleId,
213 self.define_legacy_macro(module_id, name.clone(), macro_);
216 // In Rust, `#[macro_export]` macros are unconditionally visible at the
217 // crate root, even if the parent modules is **not** visible.
222 &[(name, Resolution { def: PerNs::macros(macro_), import: None })],
227 /// Define a legacy textual scoped macro in module
229 /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
230 /// It will clone all macros from parent legacy scope, whose definition is prior to
231 /// the definition of current module.
232 /// And also, `macro_use` on a module will import all legacy macros visible inside to
233 /// current legacy scope, with possible shadowing.
234 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) {
236 self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
239 /// Import macros from `#[macro_use] extern crate`.
240 fn import_macros_from_extern_crate(
242 current_module_id: LocalModuleId,
243 import: &raw::ImportData,
246 "importing macros from extern crate: {:?} ({:?})",
248 self.def_map.edition,
251 let res = self.def_map.resolve_name_in_extern_prelude(
255 .expect("extern crate should have been desugared to one-element path"),
258 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
259 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
260 self.import_all_macros_exported(current_module_id, m.krate);
264 /// Import all exported macros from another crate
266 /// Exported macros are just all macros in the root module scope.
267 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
268 /// created by `use` in the root module, ignoring the visibility of `use`.
269 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
270 let def_map = self.db.crate_def_map(krate);
271 for (name, def) in def_map[def_map.root].scope.macros() {
272 // `macro_use` only bring things into legacy scope.
273 self.define_legacy_macro(current_module_id, name.clone(), def);
277 /// Import resolution
279 /// This is a fix point algorithm. We resolve imports until no forward
280 /// progress in resolving imports is made
281 fn resolve_imports(&mut self) {
282 let mut n_previous_unresolved = self.unresolved_imports.len() + 1;
284 while self.unresolved_imports.len() < n_previous_unresolved {
285 n_previous_unresolved = self.unresolved_imports.len();
286 let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
287 for mut directive in imports {
288 directive.status = self.resolve_import(directive.module_id, &directive.import);
290 match directive.status {
291 PartialResolvedImport::Indeterminate(_) => {
292 self.record_resolved_import(&directive);
293 // FIXME: For avoid performance regression,
294 // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
295 self.resolved_imports.push(directive)
297 PartialResolvedImport::Resolved(_) => {
298 self.record_resolved_import(&directive);
299 self.resolved_imports.push(directive)
301 PartialResolvedImport::Unresolved => {
302 self.unresolved_imports.push(directive);
311 module_id: LocalModuleId,
312 import: &raw::ImportData,
313 ) -> PartialResolvedImport {
314 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
315 if import.is_extern_crate {
316 let res = self.def_map.resolve_name_in_extern_prelude(
320 .expect("extern crate should have been desugared to one-element path"),
322 PartialResolvedImport::Resolved(res)
324 let res = self.def_map.resolve_path_fp_with_macro(
329 BuiltinShadowMode::Module,
332 let def = res.resolved_def;
333 if res.reached_fixedpoint == ReachedFixedPoint::No {
334 return PartialResolvedImport::Unresolved;
337 if let Some(krate) = res.krate {
338 if krate != self.def_map.krate {
339 return PartialResolvedImport::Resolved(def);
343 // Check whether all namespace is resolved
344 if def.take_types().is_some()
345 && def.take_values().is_some()
346 && def.take_macros().is_some()
348 PartialResolvedImport::Resolved(def)
350 PartialResolvedImport::Indeterminate(def)
355 fn record_resolved_import(&mut self, directive: &ImportDirective) {
356 let module_id = directive.module_id;
357 let import_id = directive.import_id;
358 let import = &directive.import;
359 let def = directive.status.namespaces();
362 log::debug!("glob import: {:?}", import);
363 match def.take_types() {
364 Some(ModuleDefId::ModuleId(m)) => {
365 if import.is_prelude {
366 tested_by!(std_prelude);
367 self.def_map.prelude = Some(m);
368 } else if m.krate != self.def_map.krate {
369 tested_by!(glob_across_crates);
370 // glob import from other crate => we can just import everything once
371 let item_map = self.db.crate_def_map(m.krate);
372 let scope = &item_map[m.local_id].scope;
374 // Module scoped macros is included
375 let items = scope.collect_resolutions();
377 self.update(module_id, Some(import_id), &items);
379 // glob import from same crate => we do an initial
380 // import, and then need to propagate any further
382 let scope = &self.def_map[m.local_id].scope;
384 // Module scoped macros is included
385 let items = scope.collect_resolutions();
387 self.update(module_id, Some(import_id), &items);
388 // record the glob import in case we add further items
389 let glob = self.glob_imports.entry(m.local_id).or_default();
390 if !glob.iter().any(|it| *it == (module_id, import_id)) {
391 glob.push((module_id, import_id));
395 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
396 tested_by!(glob_enum);
397 // glob import from enum => just import all the variants
398 let enum_data = self.db.enum_data(e);
399 let resolutions = enum_data
402 .filter_map(|(local_id, variant_data)| {
403 let name = variant_data.name.clone();
404 let variant = EnumVariantId { parent: e, local_id };
405 let res = Resolution {
406 def: PerNs::both(variant.into(), variant.into()),
407 import: Some(import_id),
411 .collect::<Vec<_>>();
412 self.update(module_id, Some(import_id), &resolutions);
415 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
418 log::debug!("glob import {:?} didn't resolve as type", import);
422 match import.path.segments.last() {
423 Some(last_segment) => {
424 let name = import.alias.clone().unwrap_or_else(|| last_segment.clone());
425 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
427 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
428 if import.is_extern_crate && module_id == self.def_map.root {
429 if let Some(def) = def.take_types() {
430 self.def_map.extern_prelude.insert(name.clone(), def);
434 let resolution = Resolution { def, import: Some(import_id) };
435 self.update(module_id, Some(import_id), &[(name, resolution)]);
437 None => tested_by!(bogus_paths),
444 module_id: LocalModuleId,
445 import: Option<LocalImportId>,
446 resolutions: &[(Name, Resolution)],
448 self.update_recursive(module_id, import, resolutions, 0)
453 module_id: LocalModuleId,
454 import: Option<LocalImportId>,
455 resolutions: &[(Name, Resolution)],
459 // prevent stack overflows (but this shouldn't be possible)
460 panic!("infinite recursion in glob imports!");
462 let scope = &mut self.def_map.modules[module_id].scope;
463 let mut changed = false;
464 for (name, res) in resolutions {
465 changed |= scope.push_res(name.clone(), res, import);
471 let glob_imports = self
475 .flat_map(|v| v.iter())
477 .collect::<Vec<_>>();
478 for (glob_importing_module, glob_import) in glob_imports {
479 // We pass the glob import so that the tracked import in those modules is that glob import
480 self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1);
484 fn resolve_macros(&mut self) -> ReachedFixedPoint {
485 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
486 let mut attribute_macros =
487 std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
488 let mut resolved = Vec::new();
489 let mut res = ReachedFixedPoint::Yes;
490 macros.retain(|directive| {
491 if let Some(call_id) = directive.legacy {
492 res = ReachedFixedPoint::No;
493 resolved.push((directive.module_id, call_id));
497 let resolved_res = self.def_map.resolve_path_fp_with_macro(
502 BuiltinShadowMode::Module,
505 if let Some(def) = resolved_res.resolved_def.take_macros() {
506 let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id));
507 resolved.push((directive.module_id, call_id));
508 res = ReachedFixedPoint::No;
514 attribute_macros.retain(|(module_id, ast_id, path)| {
515 let resolved_res = self.resolve_attribute_macro(path);
517 if let Some(def) = resolved_res {
518 let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id));
519 resolved.push((*module_id, call_id));
520 res = ReachedFixedPoint::No;
527 self.unexpanded_macros = macros;
528 self.unexpanded_attribute_macros = attribute_macros;
530 for (module_id, macro_call_id) in resolved {
531 self.collect_macro_expansion(module_id, macro_call_id);
537 fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> {
538 // FIXME this is currently super hacky, just enough to support the
540 if let Some(name) = path.as_ident() {
541 // FIXME this should actually be handled with the normal name
542 // resolution; the std lib defines built-in stubs for the derives,
543 // but these are new-style `macro`s, which we don't support yet
544 if let Some(def_id) = find_builtin_derive(name) {
551 fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) {
552 let file_id: HirFileId = macro_call_id.as_file();
553 let raw_items = self.db.raw_items(file_id);
554 let mod_dir = self.mod_dirs[&module_id].clone();
556 def_collector: &mut *self,
559 raw_items: &raw_items,
562 .collect(raw_items.items());
565 fn finish(self) -> CrateDefMap {
570 /// Walks a single module, populating defs, imports and macros
571 struct ModCollector<'a, D> {
573 module_id: LocalModuleId,
575 raw_items: &'a raw::RawItems,
579 impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
583 fn collect(&mut self, items: &[raw::RawItem]) {
584 // Note: don't assert that inserted value is fresh: it's simply not true
586 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
588 // Prelude module is always considered to be `#[macro_use]`.
589 if let Some(prelude_module) = self.def_collector.def_map.prelude {
590 if prelude_module.krate != self.def_collector.def_map.krate {
591 tested_by!(prelude_is_macro_use);
592 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
596 // This should be processed eagerly instead of deferred to resolving.
597 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
600 if self.is_cfg_enabled(&item.attrs) {
601 if let raw::RawItemKind::Import(import_id) = item.kind {
602 let import = self.raw_items[import_id].clone();
603 if import.is_extern_crate && import.is_macro_use {
604 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
611 if self.is_cfg_enabled(&item.attrs) {
613 raw::RawItemKind::Module(m) => {
614 self.collect_module(&self.raw_items[m], &item.attrs)
616 raw::RawItemKind::Import(import_id) => {
617 self.def_collector.unresolved_imports.push(ImportDirective {
618 module_id: self.module_id,
620 import: self.raw_items[import_id].clone(),
621 status: PartialResolvedImport::Unresolved,
624 raw::RawItemKind::Def(def) => {
625 self.define_def(&self.raw_items[def], &item.attrs)
627 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
628 raw::RawItemKind::Impl(imp) => {
629 let module = ModuleId {
630 krate: self.def_collector.def_map.krate,
631 local_id: self.module_id,
633 let container = ContainerId::ModuleId(module);
634 let ast_id = self.raw_items[imp].ast_id;
636 ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
637 .intern(self.def_collector.db);
638 self.def_collector.def_map.modules[self.module_id]
640 .define_impl(impl_id)
647 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
648 let path_attr = attrs.by_key("path").string_value();
649 let is_macro_use = attrs.by_key("macro_use").exists();
651 // inline module, just recurse
652 raw::ModuleData::Definition { name, items, ast_id } => {
654 self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
657 def_collector: &mut *self.def_collector,
659 file_id: self.file_id,
660 raw_items: self.raw_items,
661 mod_dir: self.mod_dir.descend_into_definition(name, path_attr),
665 self.import_all_legacy_macros(module_id);
668 // out of line module, resolve, parse and recurse
669 raw::ModuleData::Declaration { name, ast_id } => {
670 let ast_id = AstId::new(self.file_id, *ast_id);
671 match self.mod_dir.resolve_declaration(
672 self.def_collector.db,
677 Ok((file_id, mod_dir)) => {
678 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
679 let raw_items = self.def_collector.db.raw_items(file_id.into());
681 def_collector: &mut *self.def_collector,
683 file_id: file_id.into(),
684 raw_items: &raw_items,
687 .collect(raw_items.items());
689 self.import_all_legacy_macros(module_id);
692 Err(candidate) => self.def_collector.def_map.diagnostics.push(
693 DefDiagnostic::UnresolvedModule {
694 module: self.module_id,
704 fn push_child_module(
707 declaration: AstId<ast::Module>,
708 definition: Option<FileId>,
710 let modules = &mut self.def_collector.def_map.modules;
711 let res = modules.alloc(ModuleData::default());
712 modules[res].parent = Some(self.module_id);
713 modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
714 for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
715 modules[res].scope.define_legacy_macro(name, mac)
717 modules[self.module_id].children.insert(name.clone(), res);
718 let resolution = Resolution {
720 ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(),
724 self.def_collector.update(self.module_id, None, &[(name, resolution)]);
728 fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) {
729 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
730 // FIXME: check attrs to see if this is an attribute macro invocation;
731 // in which case we don't add the invocation, just a single attribute
734 self.collect_derives(attrs, def);
736 let name = def.name.clone();
737 let container = ContainerId::ModuleId(module);
738 let def: PerNs = match def.kind {
739 raw::DefKind::Function(ast_id) => {
740 let def = FunctionLoc {
741 container: container.into(),
742 ast_id: AstId::new(self.file_id, ast_id),
744 .intern(self.def_collector.db);
746 PerNs::values(def.into())
748 raw::DefKind::Struct(ast_id) => {
749 let def = StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
750 .intern(self.def_collector.db);
751 PerNs::both(def.into(), def.into())
753 raw::DefKind::Union(ast_id) => {
754 let def = UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
755 .intern(self.def_collector.db);
756 PerNs::both(def.into(), def.into())
758 raw::DefKind::Enum(ast_id) => {
759 let def = EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
760 .intern(self.def_collector.db);
761 PerNs::types(def.into())
763 raw::DefKind::Const(ast_id) => {
765 container: container.into(),
766 ast_id: AstId::new(self.file_id, ast_id),
768 .intern(self.def_collector.db);
770 PerNs::values(def.into())
772 raw::DefKind::Static(ast_id) => {
773 let def = StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
774 .intern(self.def_collector.db);
776 PerNs::values(def.into())
778 raw::DefKind::Trait(ast_id) => {
779 let def = TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
780 .intern(self.def_collector.db);
782 PerNs::types(def.into())
784 raw::DefKind::TypeAlias(ast_id) => {
785 let def = TypeAliasLoc {
786 container: container.into(),
787 ast_id: AstId::new(self.file_id, ast_id),
789 .intern(self.def_collector.db);
791 PerNs::types(def.into())
794 let resolution = Resolution { def, import: None };
795 self.def_collector.update(self.module_id, None, &[(name, resolution)])
798 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
799 for derive_subtree in attrs.by_key("derive").tt_values() {
800 // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
801 for tt in &derive_subtree.token_trees {
802 let ident = match &tt {
803 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
804 tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
805 _ => continue, // anything else would be an error (which we currently ignore)
807 let path = ModPath::from_tt_ident(ident);
809 let ast_id = AstId::new(self.file_id, def.kind.ast_id());
810 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path));
815 fn collect_macro(&mut self, mac: &raw::MacroData) {
816 let ast_id = AstId::new(self.file_id, mac.ast_id);
818 // Case 0: builtin macros
820 if let Some(name) = &mac.name {
821 let krate = self.def_collector.def_map.krate;
822 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
823 self.def_collector.define_macro(
834 // Case 1: macro rules, define a macro in crate-global mutable scope
835 if is_macro_rules(&mac.path) {
836 if let Some(name) = &mac.name {
837 let macro_id = MacroDefId {
838 ast_id: Some(ast_id),
839 krate: Some(self.def_collector.def_map.krate),
840 kind: MacroDefKind::Declarative,
842 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
847 // Case 2: try to resolve in legacy scope and expand macro_rules
848 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
849 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
852 macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id));
854 self.def_collector.unexpanded_macros.push(MacroDirective {
855 module_id: self.module_id,
856 path: mac.path.clone(),
858 legacy: Some(macro_call_id),
864 // Case 3: resolve in module scope, expand during name resolution.
865 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
866 let mut path = mac.path.clone();
868 path.kind = PathKind::Super(0);
871 self.def_collector.unexpanded_macros.push(MacroDirective {
872 module_id: self.module_id,
879 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
880 let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
881 for (name, macro_) in macros {
882 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
886 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
887 // FIXME: handle cfg_attr :-)
891 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
895 fn is_macro_rules(path: &ModPath) -> bool {
896 path.as_ident() == Some(&name![macro_rules])
901 use crate::{db::DefDatabase, test_db::TestDB};
903 use ra_db::{fixture::WithFixture, SourceDatabase};
907 fn do_collect_defs(db: &impl DefDatabase, def_map: CrateDefMap) -> CrateDefMap {
908 let mut collector = DefCollector {
911 glob_imports: FxHashMap::default(),
912 unresolved_imports: Vec::new(),
913 resolved_imports: Vec::new(),
914 unexpanded_macros: Vec::new(),
915 unexpanded_attribute_macros: Vec::new(),
916 mod_dirs: FxHashMap::default(),
917 cfg_options: &CfgOptions::default(),
923 fn do_resolve(code: &str) -> CrateDefMap {
924 let (db, _file_id) = TestDB::with_single_file(&code);
925 let krate = db.test_crate();
928 let edition = db.crate_graph().edition(krate);
929 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
930 let root = modules.alloc(ModuleData::default());
934 extern_prelude: FxHashMap::default(),
938 diagnostics: Vec::new(),
941 do_collect_defs(&db, def_map)
945 fn test_macro_expand_will_stop() {
949 ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }