aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorice1000 <[email protected]>2019-12-03 19:58:29 +0000
committerice1000 <[email protected]>2019-12-04 23:30:42 +0000
commit1bb59a7d08d10d247da265ef58835f9979ec36b7 (patch)
tree2e7af139e0703c959b236cca94e9996ec8ec04d5
parentace661bb10dbfd596a444c235f80fa43a2845239 (diff)
Three-state enum for module origin
-rw-r--r--crates/ra_hir_def/src/nameres.rs91
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs7
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)]
104pub 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
113impl Default for ModuleOrigin {
114 fn default() -> Self {
115 ModuleOrigin::Root(None)
116 }
117}
118
119impl 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)]
104pub struct ModuleData { 173pub 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 {