diff options
Diffstat (limited to 'crates/ra_hir/src/nameres/crate_def_map.rs')
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map.rs | 118 |
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 | ||
49 | use rustc_hash::FxHashMap; | 49 | use rustc_hash::FxHashMap; |
50 | use test_utils::tested_by; | 50 | use test_utils::tested_by; |
51 | use ra_arena::Arena; | 51 | use ra_arena::{Arena, RawId, impl_arena_id}; |
52 | use ra_db::FileId; | ||
53 | |||
54 | use std::sync::Arc; | ||
52 | 55 | ||
53 | use crate::{ | 56 | use 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)] | 63 | pub(crate) use self::raw::RawItems; |
61 | struct ModuleData { | 64 | |
62 | parent: Option<ModuleId>, | 65 | #[derive(Default, Debug, PartialEq, Eq)] |
63 | children: FxHashMap<Name, ModuleId>, | 66 | pub(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)] | ||
79 | pub(crate) struct ModuleId(RawId); | ||
80 | impl_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)] |
69 | pub(crate) struct CrateDefMap { | 84 | pub 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)] | ||
99 | pub(crate) struct CrateDefMapProblems { | ||
100 | problems: Vec<(SourceItemId, Problem)>, | ||
101 | } | ||
102 | |||
103 | impl 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 | ||
82 | impl std::ops::Index<ModuleId> for CrateDefMap { | 113 | impl 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 | ||
89 | impl CrateDefMap { | 120 | impl 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 | }; |