diff options
author | ice1000 <[email protected]> | 2019-12-03 19:58:29 +0000 |
---|---|---|
committer | ice1000 <[email protected]> | 2019-12-04 23:30:42 +0000 |
commit | 1bb59a7d08d10d247da265ef58835f9979ec36b7 (patch) | |
tree | 2e7af139e0703c959b236cca94e9996ec8ec04d5 | |
parent | ace661bb10dbfd596a444c235f80fa43a2845239 (diff) |
Three-state enum for module origin
-rw-r--r-- | crates/ra_hir_def/src/nameres.rs | 91 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 7 |
2 files changed, 78 insertions, 20 deletions
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index faf3566f4..cf2a83191 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -100,19 +100,83 @@ impl std::ops::Index<LocalModuleId> for CrateDefMap { | |||
100 | } | 100 | } |
101 | } | 101 | } |
102 | 102 | ||
103 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | ||
104 | pub enum ModuleOrigin { | ||
105 | /// It should not be `None` after collecting definitions. | ||
106 | Root(Option<FileId>), | ||
107 | /// Note that non-inline modules, by definition, live inside non-macro file. | ||
108 | File(AstId<ast::Module>, FileId), | ||
109 | Inline(AstId<ast::Module>), | ||
110 | Block(AstId<ast::Block>), | ||
111 | } | ||
112 | |||
113 | impl Default for ModuleOrigin { | ||
114 | fn default() -> Self { | ||
115 | ModuleOrigin::Root(None) | ||
116 | } | ||
117 | } | ||
118 | |||
119 | impl ModuleOrigin { | ||
120 | pub fn root(file_id: FileId) -> Self { | ||
121 | ModuleOrigin::Root(Some(file_id)) | ||
122 | } | ||
123 | |||
124 | pub fn not_sure_file(file: Option<FileId>, module: AstId<ast::Module>) -> Self { | ||
125 | match file { | ||
126 | None => ModuleOrigin::Inline(module), | ||
127 | Some(file) => ModuleOrigin::File(module, file), | ||
128 | } | ||
129 | } | ||
130 | |||
131 | pub fn not_sure_mod(file: FileId, module: Option<AstId<ast::Module>>) -> Self { | ||
132 | match module { | ||
133 | None => ModuleOrigin::root(file), | ||
134 | Some(module) => ModuleOrigin::File(module, file), | ||
135 | } | ||
136 | } | ||
137 | |||
138 | pub fn declaration(&self) -> Option<AstId<ast::Module>> { | ||
139 | match self { | ||
140 | ModuleOrigin::File(m, _) | ModuleOrigin::Inline(m) => Some(*m), | ||
141 | ModuleOrigin::Root(_) | ModuleOrigin::Block(_) => None, | ||
142 | } | ||
143 | } | ||
144 | |||
145 | pub fn file_id(&self) -> Option<FileId> { | ||
146 | match self { | ||
147 | ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => Some(*file_id), | ||
148 | _ => None, | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /// Returns a node which defines this module. | ||
153 | /// That is, a file or a `mod foo {}` with items. | ||
154 | pub fn definition_source( | ||
155 | &self, | ||
156 | db: &impl DefDatabase, | ||
157 | ) -> InFile<Either<ast::SourceFile, ast::Module>> { | ||
158 | match self { | ||
159 | ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => { | ||
160 | let file_id = *file_id; | ||
161 | let sf = db.parse(file_id).tree(); | ||
162 | return InFile::new(file_id.into(), Either::Left(sf)); | ||
163 | } | ||
164 | ModuleOrigin::Root(None) => unreachable!(), | ||
165 | ModuleOrigin::Inline(m) => InFile::new(m.file_id, Either::Right(m.to_node(db))), | ||
166 | // FIXME: right now it's never constructed, so it's fine to omit | ||
167 | ModuleOrigin::Block(b) => unimplemented!(), | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | |||
103 | #[derive(Default, Debug, PartialEq, Eq)] | 172 | #[derive(Default, Debug, PartialEq, Eq)] |
104 | pub struct ModuleData { | 173 | pub struct ModuleData { |
105 | pub parent: Option<LocalModuleId>, | 174 | pub parent: Option<LocalModuleId>, |
106 | pub children: FxHashMap<Name, LocalModuleId>, | 175 | pub children: FxHashMap<Name, LocalModuleId>, |
107 | pub scope: ModuleScope, | 176 | pub scope: ModuleScope, |
108 | 177 | ||
109 | // FIXME: these can't be both null, we need a three-state enum here. | 178 | /// Where does this module come from? |
110 | /// None for root | 179 | pub origin: ModuleOrigin, |
111 | pub declaration: Option<AstId<ast::Module>>, | ||
112 | /// None for inline modules. | ||
113 | /// | ||
114 | /// Note that non-inline modules, by definition, live inside non-macro file. | ||
115 | pub definition: Option<FileId>, | ||
116 | 180 | ||
117 | pub impls: Vec<ImplId>, | 181 | pub impls: Vec<ImplId>, |
118 | } | 182 | } |
@@ -262,7 +326,7 @@ impl CrateDefMap { | |||
262 | pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ { | 326 | pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ { |
263 | self.modules | 327 | self.modules |
264 | .iter() | 328 | .iter() |
265 | .filter(move |(_id, data)| data.definition == Some(file_id)) | 329 | .filter(move |(_id, data)| data.origin.file_id() == Some(file_id)) |
266 | .map(|(id, _data)| id) | 330 | .map(|(id, _data)| id) |
267 | } | 331 | } |
268 | 332 | ||
@@ -285,18 +349,13 @@ impl ModuleData { | |||
285 | &self, | 349 | &self, |
286 | db: &impl DefDatabase, | 350 | db: &impl DefDatabase, |
287 | ) -> InFile<Either<ast::SourceFile, ast::Module>> { | 351 | ) -> InFile<Either<ast::SourceFile, ast::Module>> { |
288 | if let Some(file_id) = self.definition { | 352 | self.origin.definition_source(db) |
289 | let sf = db.parse(file_id).tree(); | ||
290 | return InFile::new(file_id.into(), Either::Left(sf)); | ||
291 | } | ||
292 | let decl = self.declaration.unwrap(); | ||
293 | InFile::new(decl.file_id, Either::Right(decl.to_node(db))) | ||
294 | } | 353 | } |
295 | 354 | ||
296 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. | 355 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. |
297 | /// `None` for the crate root. | 356 | /// `None` for the crate root or block. |
298 | pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> { | 357 | pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> { |
299 | let decl = self.declaration?; | 358 | let decl = self.origin.declaration()?; |
300 | let value = decl.to_node(db); | 359 | let value = decl.to_node(db); |
301 | Some(InFile { file_id: decl.file_id, value }) | 360 | Some(InFile { file_id: decl.file_id, value }) |
302 | } | 361 | } |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d4bfcae1d..6f4a3e42e 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -19,7 +19,7 @@ use crate::{ | |||
19 | db::DefDatabase, | 19 | db::DefDatabase, |
20 | nameres::{ | 20 | nameres::{ |
21 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, | 21 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, |
22 | raw, BuiltinShadowMode, CrateDefMap, ModuleData, Resolution, ResolveMode, | 22 | raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode, |
23 | }, | 23 | }, |
24 | path::{Path, PathKind}, | 24 | path::{Path, PathKind}, |
25 | per_ns::PerNs, | 25 | per_ns::PerNs, |
@@ -131,7 +131,7 @@ where | |||
131 | let file_id = crate_graph.crate_root(self.def_map.krate); | 131 | let file_id = crate_graph.crate_root(self.def_map.krate); |
132 | let raw_items = self.db.raw_items(file_id.into()); | 132 | let raw_items = self.db.raw_items(file_id.into()); |
133 | let module_id = self.def_map.root; | 133 | let module_id = self.def_map.root; |
134 | self.def_map.modules[module_id].definition = Some(file_id); | 134 | self.def_map.modules[module_id].origin = ModuleOrigin::root(file_id); |
135 | ModCollector { | 135 | ModCollector { |
136 | def_collector: &mut *self, | 136 | def_collector: &mut *self, |
137 | module_id, | 137 | module_id, |
@@ -669,8 +669,7 @@ where | |||
669 | let modules = &mut self.def_collector.def_map.modules; | 669 | let modules = &mut self.def_collector.def_map.modules; |
670 | let res = modules.alloc(ModuleData::default()); | 670 | let res = modules.alloc(ModuleData::default()); |
671 | modules[res].parent = Some(self.module_id); | 671 | modules[res].parent = Some(self.module_id); |
672 | modules[res].declaration = Some(declaration); | 672 | modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration); |
673 | modules[res].definition = definition; | ||
674 | modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); | 673 | modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); |
675 | modules[self.module_id].children.insert(name.clone(), res); | 674 | modules[self.module_id].children.insert(name.clone(), res); |
676 | let resolution = Resolution { | 675 | let resolution = Resolution { |