]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_def/src/nameres.rs
parameters.split_last()
[rust.git] / crates / hir_def / src / nameres.rs
index c829b6a64ca1a60f7f81d3ed1d508fee2ab19209..ca4255c58193f9b407b543448107789a906b3ccd 100644 (file)
@@ -1,14 +1,14 @@
 //! This module implements import-resolution/macro expansion algorithm.
 //!
-//! The result of this module is `CrateDefMap`: a data structure which contains:
+//! The result of this module is `DefMap`: a data structure which contains:
 //!
 //!   * a tree of modules for the crate
 //!   * for each module, a set of items visible in the module (directly declared
 //!     or imported)
 //!
-//! Note that `CrateDefMap` contains fully macro expanded code.
+//! Note that `DefMap` contains fully macro expanded code.
 //!
-//! Computing `CrateDefMap` can be partitioned into several logically
+//! Computing `DefMap` can be partitioned into several logically
 //! independent "phases". The phases are mutually recursive though, there's no
 //! strict ordering.
 //!
@@ -47,6 +47,7 @@
 //! path and, upon success, we run macro expansion and "collect module" phase on
 //! the result
 
+pub mod attr_resolution;
 pub mod diagnostics;
 mod collector;
 mod mod_resolution;
 use profile::Count;
 use rustc_hash::FxHashMap;
 use stdx::format_to;
-use syntax::ast;
+use syntax::{ast, SmolStr};
 
 use crate::{
     db::DefDatabase,
     item_scope::{BuiltinShadowMode, ItemScope},
+    item_tree::TreeId,
     nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
     path::ModPath,
     per_ns::PerNs,
+    visibility::Visibility,
     AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId,
 };
 
@@ -102,10 +105,16 @@ pub struct DefMap {
     /// Side table with additional proc. macro info, for use by name resolution in downstream
     /// crates.
     ///
-    /// (the primary purpose is to resolve derive helpers)
+    /// (the primary purpose is to resolve derive helpers and fetch a proc-macros name)
     exported_proc_macros: FxHashMap<MacroDefId, ProcMacroDef>,
 
+    /// Custom attributes registered with `#![register_attr]`.
+    registered_attrs: Vec<SmolStr>,
+    /// Custom tool modules registered with `#![register_tool]`.
+    registered_tools: Vec<SmolStr>,
+
     edition: Edition,
+    recursion_limit: Option<u32>,
     diagnostics: Vec<DefDiagnostic>,
 }
 
@@ -146,7 +155,7 @@ pub enum ModuleOrigin {
 }
 
 impl ModuleOrigin {
-    fn declaration(&self) -> Option<AstId<ast::Module>> {
+    pub fn declaration(&self) -> Option<AstId<ast::Module>> {
         match self {
             ModuleOrigin::File { declaration: module, .. }
             | ModuleOrigin::Inline { definition: module, .. } => Some(*module),
@@ -192,18 +201,14 @@ fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
 
 #[derive(Debug, PartialEq, Eq)]
 pub struct ModuleData {
-    pub parent: Option<LocalModuleId>,
-    pub children: FxHashMap<Name, LocalModuleId>,
-    pub scope: ItemScope,
-
     /// Where does this module come from?
     pub origin: ModuleOrigin,
-}
+    /// Declared visibility of this module.
+    pub visibility: Visibility,
 
-impl Default for ModuleData {
-    fn default() -> Self {
-        ModuleData::new(ModuleOrigin::CrateRoot { definition: FileId(!0) })
-    }
+    pub parent: Option<LocalModuleId>,
+    pub children: FxHashMap<Name, LocalModuleId>,
+    pub scope: ItemScope,
 }
 
 impl DefMap {
@@ -211,9 +216,18 @@ pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<D
         let _p = profile::span("crate_def_map_query").detail(|| {
             db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string()
         });
-        let edition = db.crate_graph()[krate].edition;
-        let def_map = DefMap::empty(krate, edition);
-        let def_map = collector::collect_defs(db, def_map, None);
+
+        let crate_graph = db.crate_graph();
+
+        let edition = crate_graph[krate].edition;
+        let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id };
+        let def_map = DefMap::empty(krate, edition, origin);
+        let def_map = collector::collect_defs(
+            db,
+            def_map,
+            TreeId::new(crate_graph[krate].root_file_id.into(), None),
+        );
+
         Arc::new(def_map)
     }
 
@@ -223,34 +237,50 @@ pub(crate) fn block_def_map_query(
     ) -> Option<Arc<DefMap>> {
         let block: BlockLoc = db.lookup_intern_block(block_id);
 
-        let item_tree = db.file_item_tree(block.ast_id.file_id);
-        if item_tree.inner_items_of_block(block.ast_id.value).is_empty() {
+        let tree_id = TreeId::new(block.ast_id.file_id, Some(block_id));
+        let item_tree = tree_id.item_tree(db);
+        if item_tree.top_level_items().is_empty() {
             return None;
         }
 
         let block_info = BlockInfo { block: block_id, parent: block.module };
 
         let parent_map = block.module.def_map(db);
-        let mut def_map = DefMap::empty(block.module.krate, parent_map.edition);
+        let mut def_map = DefMap::empty(
+            block.module.krate,
+            parent_map.edition,
+            ModuleOrigin::BlockExpr { block: block.ast_id },
+        );
         def_map.block = Some(block_info);
 
-        let def_map = collector::collect_defs(db, def_map, Some(block.ast_id));
+        let def_map = collector::collect_defs(db, def_map, tree_id);
         Some(Arc::new(def_map))
     }
 
-    fn empty(krate: CrateId, edition: Edition) -> DefMap {
+    fn empty(krate: CrateId, edition: Edition, root_module_origin: ModuleOrigin) -> DefMap {
         let mut modules: Arena<ModuleData> = Arena::default();
-        let root = modules.alloc(ModuleData::default());
+
+        let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
+        // NB: we use `None` as block here, which would be wrong for implicit
+        // modules declared by blocks with items. At the moment, we don't use
+        // this visibility for anything outside IDE, so that's probably OK.
+        let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
+        let root = modules.alloc(ModuleData::new(root_module_origin, visibility));
+        assert_eq!(local_id, root);
+
         DefMap {
             _c: Count::new(),
             block: None,
             krate,
             edition,
+            recursion_limit: None,
             extern_prelude: FxHashMap::default(),
             exported_proc_macros: FxHashMap::default(),
             prelude: None,
             root,
             modules,
+            registered_attrs: Vec::new(),
+            registered_tools: Vec::new(),
             diagnostics: Vec::new(),
         }
     }
@@ -265,7 +295,15 @@ pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalMod
     pub fn modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_ {
         self.modules.iter()
     }
-
+    pub fn exported_proc_macros(&self) -> impl Iterator<Item = (MacroDefId, Name)> + '_ {
+        self.exported_proc_macros.iter().map(|(id, def)| (*id, def.name.clone()))
+    }
+    pub fn registered_tools(&self) -> &[SmolStr] {
+        &self.registered_tools
+    }
+    pub fn registered_attrs(&self) -> &[SmolStr] {
+        &self.registered_attrs
+    }
     pub fn root(&self) -> LocalModuleId {
         self.root
     }
@@ -421,8 +459,11 @@ fn shrink_to_fit(&mut self) {
             extern_prelude,
             diagnostics,
             modules,
+            registered_attrs,
+            registered_tools,
             block: _,
             edition: _,
+            recursion_limit: _,
             krate: _,
             prelude: _,
             root: _,
@@ -432,6 +473,8 @@ fn shrink_to_fit(&mut self) {
         exported_proc_macros.shrink_to_fit();
         diagnostics.shrink_to_fit();
         modules.shrink_to_fit();
+        registered_attrs.shrink_to_fit();
+        registered_tools.shrink_to_fit();
         for (_, module) in modules.iter_mut() {
             module.children.shrink_to_fit();
             module.scope.shrink_to_fit();
@@ -442,15 +485,20 @@ fn shrink_to_fit(&mut self) {
     pub fn diagnostics(&self) -> &[DefDiagnostic] {
         self.diagnostics.as_slice()
     }
+
+    pub fn recursion_limit(&self) -> Option<u32> {
+        self.recursion_limit
+    }
 }
 
 impl ModuleData {
-    pub(crate) fn new(origin: ModuleOrigin) -> Self {
+    pub(crate) fn new(origin: ModuleOrigin, visibility: Visibility) -> Self {
         ModuleData {
+            origin,
+            visibility,
             parent: None,
             children: FxHashMap::default(),
             scope: ItemScope::default(),
-            origin,
         }
     }