aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/crate_def_map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres/crate_def_map.rs')
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map.rs118
1 files changed, 100 insertions, 18 deletions
diff --git a/crates/ra_hir/src/nameres/crate_def_map.rs b/crates/ra_hir/src/nameres/crate_def_map.rs
index 483878c78..d7ccb6584 100644
--- a/crates/ra_hir/src/nameres/crate_def_map.rs
+++ b/crates/ra_hir/src/nameres/crate_def_map.rs
@@ -48,25 +48,40 @@ mod tests;
48 48
49use rustc_hash::FxHashMap; 49use rustc_hash::FxHashMap;
50use test_utils::tested_by; 50use test_utils::tested_by;
51use ra_arena::Arena; 51use ra_arena::{Arena, RawId, impl_arena_id};
52use ra_db::FileId;
53
54use std::sync::Arc;
52 55
53use crate::{ 56use crate::{
54 Name, Module, Path, PathKind, ModuleDef, Crate, 57 Name, Module, Path, PathKind, ModuleDef, Crate, Problem, HirFileId,
55 PersistentHirDatabase, 58 PersistentHirDatabase,
56 module_tree::ModuleId,
57 nameres::{ModuleScope, ResolveMode, ResolvePathResult, PerNs, Edition, ReachedFixedPoint}, 59 nameres::{ModuleScope, ResolveMode, ResolvePathResult, PerNs, Edition, ReachedFixedPoint},
60 ids::{SourceItemId, SourceFileItemId},
58}; 61};
59 62
60#[derive(Default, Debug)] 63pub(crate) use self::raw::RawItems;
61struct ModuleData { 64
62 parent: Option<ModuleId>, 65#[derive(Default, Debug, PartialEq, Eq)]
63 children: FxHashMap<Name, ModuleId>, 66pub(crate) struct ModuleData {
64 scope: ModuleScope, 67 pub(crate) parent: Option<ModuleId>,
68 pub(crate) children: FxHashMap<Name, ModuleId>,
69 pub(crate) scope: ModuleScope,
70 /// None for root
71 pub(crate) declaration: Option<SourceItemId>,
72 /// None for inline modules.
73 ///
74 /// Note that non-inline modules, by definition, live inside non-macro file.
75 pub(crate) definition: Option<FileId>,
65} 76}
66 77
78#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
79pub(crate) struct ModuleId(RawId);
80impl_arena_id!(ModuleId);
81
67/// Contans all top-level defs from a macro-expanded crate 82/// Contans all top-level defs from a macro-expanded crate
68#[derive(Debug)] 83#[derive(Debug, PartialEq, Eq)]
69pub(crate) struct CrateDefMap { 84pub struct CrateDefMap {
70 krate: Crate, 85 krate: Crate,
71 edition: Edition, 86 edition: Edition,
72 /// The prelude module for this crate. This either comes from an import 87 /// The prelude module for this crate. This either comes from an import
@@ -77,19 +92,85 @@ pub(crate) struct CrateDefMap {
77 root: ModuleId, 92 root: ModuleId,
78 modules: Arena<ModuleId, ModuleData>, 93 modules: Arena<ModuleId, ModuleData>,
79 public_macros: FxHashMap<Name, mbe::MacroRules>, 94 public_macros: FxHashMap<Name, mbe::MacroRules>,
95 problems: CrateDefMapProblems,
96}
97
98#[derive(Default, Debug, PartialEq, Eq)]
99pub(crate) struct CrateDefMapProblems {
100 problems: Vec<(SourceItemId, Problem)>,
101}
102
103impl CrateDefMapProblems {
104 fn add(&mut self, source_item_id: SourceItemId, problem: Problem) {
105 self.problems.push((source_item_id, problem))
106 }
107
108 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a SourceItemId, &'a Problem)> + 'a {
109 self.problems.iter().map(|(s, p)| (s, p))
110 }
80} 111}
81 112
82impl std::ops::Index<ModuleId> for CrateDefMap { 113impl std::ops::Index<ModuleId> for CrateDefMap {
83 type Output = ModuleScope; 114 type Output = ModuleData;
84 fn index(&self, id: ModuleId) -> &ModuleScope { 115 fn index(&self, id: ModuleId) -> &ModuleData {
85 &self.modules[id].scope 116 &self.modules[id]
86 } 117 }
87} 118}
88 119
89impl CrateDefMap { 120impl CrateDefMap {
121 pub(crate) fn crate_def_map_query(
122 db: &impl PersistentHirDatabase,
123 krate: Crate,
124 ) -> Arc<CrateDefMap> {
125 let def_map = {
126 let edition = krate.edition(db);
127 let mut modules: Arena<ModuleId, ModuleData> = Arena::default();
128 let root = modules.alloc(ModuleData::default());
129 CrateDefMap {
130 krate,
131 edition,
132 extern_prelude: FxHashMap::default(),
133 prelude: None,
134 root,
135 modules,
136 public_macros: FxHashMap::default(),
137 problems: CrateDefMapProblems::default(),
138 }
139 };
140 let def_map = collector::collect_defs(db, def_map);
141 Arc::new(def_map)
142 }
143
144 pub(crate) fn root(&self) -> ModuleId {
145 self.root
146 }
147
148 pub(crate) fn problems(&self) -> &CrateDefMapProblems {
149 &self.problems
150 }
151
152 pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
153 self.modules.iter().map(|(id, _data)| id)
154 }
155
156 pub(crate) fn find_module_by_source(
157 &self,
158 file_id: HirFileId,
159 decl_id: Option<SourceFileItemId>,
160 ) -> Option<ModuleId> {
161 let decl_id = decl_id.map(|it| it.with_file_id(file_id));
162 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
163 if decl_id.is_some() {
164 module_data.declaration == decl_id
165 } else {
166 module_data.definition.map(|it| it.into()) == Some(file_id)
167 }
168 })?;
169 Some(module_id)
170 }
171
90 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 172 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
91 // the result. 173 // the result.
92 #[allow(unused)]
93 fn resolve_path_fp( 174 fn resolve_path_fp(
94 &self, 175 &self,
95 db: &impl PersistentHirDatabase, 176 db: &impl PersistentHirDatabase,
@@ -182,7 +263,7 @@ impl CrateDefMap {
182 ); 263 );
183 } 264 }
184 265
185 match self[module.module_id].items.get(&segment.name) { 266 match self[module.module_id].scope.items.get(&segment.name) {
186 Some(res) if !res.def.is_none() => res.def, 267 Some(res) if !res.def.is_none() => res.def,
187 _ => { 268 _ => {
188 log::debug!("path segment {:?} not found", segment.name); 269 log::debug!("path segment {:?} not found", segment.name);
@@ -225,7 +306,8 @@ impl CrateDefMap {
225 } 306 }
226 307
227 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { 308 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
228 let from_crate_root = self[self.root].items.get(name).map_or(PerNs::none(), |it| it.def); 309 let from_crate_root =
310 self[self.root].scope.items.get(name).map_or(PerNs::none(), |it| it.def);
229 let from_extern_prelude = self.resolve_name_in_extern_prelude(name); 311 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
230 312
231 from_crate_root.or(from_extern_prelude) 313 from_crate_root.or(from_extern_prelude)
@@ -241,7 +323,7 @@ impl CrateDefMap {
241 // - current module / scope 323 // - current module / scope
242 // - extern prelude 324 // - extern prelude
243 // - std prelude 325 // - std prelude
244 let from_scope = self[module].items.get(name).map_or(PerNs::none(), |it| it.def); 326 let from_scope = self[module].scope.items.get(name).map_or(PerNs::none(), |it| it.def);
245 let from_extern_prelude = 327 let from_extern_prelude =
246 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); 328 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
247 let from_prelude = self.resolve_in_prelude(db, name); 329 let from_prelude = self.resolve_in_prelude(db, name);
@@ -256,7 +338,7 @@ impl CrateDefMap {
256 fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> { 338 fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> {
257 if let Some(prelude) = self.prelude { 339 if let Some(prelude) = self.prelude {
258 let resolution = if prelude.krate == self.krate { 340 let resolution = if prelude.krate == self.krate {
259 self[prelude.module_id].items.get(name).cloned() 341 self[prelude.module_id].scope.items.get(name).cloned()
260 } else { 342 } else {
261 db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned() 343 db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned()
262 }; 344 };