diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-12-05 13:38:39 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-12-05 13:38:39 +0000 |
commit | 4c0bd068da39e74c66104206e27c270454e3562e (patch) | |
tree | 25e6c7005e04c3a63344f23a003614409cfda4c9 /crates/ra_hir_def | |
parent | ace661bb10dbfd596a444c235f80fa43a2845239 (diff) | |
parent | d15f300268fa955f8e9c04d51ca1dc528766f742 (diff) |
Merge #2474
2474: Move `ModuleSource`, create `ModuleOrigin` r=matklad a=ice1000
As title. This comes right after #2473
Co-authored-by: ice1000 <[email protected]>
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/nameres.rs | 132 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 7 |
2 files changed, 112 insertions, 27 deletions
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index faf3566f4..bd237a7b3 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -57,15 +57,17 @@ mod tests; | |||
57 | 57 | ||
58 | use std::sync::Arc; | 58 | use std::sync::Arc; |
59 | 59 | ||
60 | use either::Either; | ||
61 | use hir_expand::{ | 60 | use hir_expand::{ |
62 | ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId, | 61 | ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId, |
63 | }; | 62 | }; |
64 | use once_cell::sync::Lazy; | 63 | use once_cell::sync::Lazy; |
65 | use ra_arena::Arena; | 64 | use ra_arena::Arena; |
66 | use ra_db::{CrateId, Edition, FileId}; | 65 | use ra_db::{CrateId, Edition, FileId, FilePosition}; |
67 | use ra_prof::profile; | 66 | use ra_prof::profile; |
68 | use ra_syntax::ast; | 67 | use ra_syntax::{ |
68 | ast::{self, AstNode}, | ||
69 | SyntaxNode, | ||
70 | }; | ||
69 | use rustc_hash::FxHashMap; | 71 | use rustc_hash::FxHashMap; |
70 | 72 | ||
71 | use crate::{ | 73 | use crate::{ |
@@ -100,19 +102,76 @@ impl std::ops::Index<LocalModuleId> for CrateDefMap { | |||
100 | } | 102 | } |
101 | } | 103 | } |
102 | 104 | ||
105 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | ||
106 | pub enum ModuleOrigin { | ||
107 | CrateRoot { | ||
108 | definition: FileId, | ||
109 | }, | ||
110 | /// Note that non-inline modules, by definition, live inside non-macro file. | ||
111 | File { | ||
112 | declaration: AstId<ast::Module>, | ||
113 | definition: FileId, | ||
114 | }, | ||
115 | Inline { | ||
116 | definition: AstId<ast::Module>, | ||
117 | }, | ||
118 | } | ||
119 | |||
120 | impl Default for ModuleOrigin { | ||
121 | fn default() -> Self { | ||
122 | ModuleOrigin::CrateRoot { definition: FileId(0) } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | impl ModuleOrigin { | ||
127 | pub(crate) fn not_sure_file(file: Option<FileId>, declaration: AstId<ast::Module>) -> Self { | ||
128 | match file { | ||
129 | None => ModuleOrigin::Inline { definition: declaration }, | ||
130 | Some(definition) => ModuleOrigin::File { declaration, definition }, | ||
131 | } | ||
132 | } | ||
133 | |||
134 | fn declaration(&self) -> Option<AstId<ast::Module>> { | ||
135 | match self { | ||
136 | ModuleOrigin::File { declaration: module, .. } | ||
137 | | ModuleOrigin::Inline { definition: module, .. } => Some(*module), | ||
138 | ModuleOrigin::CrateRoot { .. } => None, | ||
139 | } | ||
140 | } | ||
141 | |||
142 | pub fn file_id(&self) -> Option<FileId> { | ||
143 | match self { | ||
144 | ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => { | ||
145 | Some(*definition) | ||
146 | } | ||
147 | _ => None, | ||
148 | } | ||
149 | } | ||
150 | |||
151 | /// Returns a node which defines this module. | ||
152 | /// That is, a file or a `mod foo {}` with items. | ||
153 | fn definition_source(&self, db: &impl DefDatabase) -> InFile<ModuleSource> { | ||
154 | match self { | ||
155 | ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => { | ||
156 | let file_id = *definition; | ||
157 | let sf = db.parse(file_id).tree(); | ||
158 | return InFile::new(file_id.into(), ModuleSource::SourceFile(sf)); | ||
159 | } | ||
160 | ModuleOrigin::Inline { definition } => { | ||
161 | InFile::new(definition.file_id, ModuleSource::Module(definition.to_node(db))) | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | } | ||
166 | |||
103 | #[derive(Default, Debug, PartialEq, Eq)] | 167 | #[derive(Default, Debug, PartialEq, Eq)] |
104 | pub struct ModuleData { | 168 | pub struct ModuleData { |
105 | pub parent: Option<LocalModuleId>, | 169 | pub parent: Option<LocalModuleId>, |
106 | pub children: FxHashMap<Name, LocalModuleId>, | 170 | pub children: FxHashMap<Name, LocalModuleId>, |
107 | pub scope: ModuleScope, | 171 | pub scope: ModuleScope, |
108 | 172 | ||
109 | // FIXME: these can't be both null, we need a three-state enum here. | 173 | /// Where does this module come from? |
110 | /// None for root | 174 | 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 | 175 | ||
117 | pub impls: Vec<ImplId>, | 176 | pub impls: Vec<ImplId>, |
118 | } | 177 | } |
@@ -262,7 +321,7 @@ impl CrateDefMap { | |||
262 | pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ { | 321 | pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ { |
263 | self.modules | 322 | self.modules |
264 | .iter() | 323 | .iter() |
265 | .filter(move |(_id, data)| data.definition == Some(file_id)) | 324 | .filter(move |(_id, data)| data.origin.file_id() == Some(file_id)) |
266 | .map(|(id, _data)| id) | 325 | .map(|(id, _data)| id) |
267 | } | 326 | } |
268 | 327 | ||
@@ -281,27 +340,54 @@ impl CrateDefMap { | |||
281 | 340 | ||
282 | impl ModuleData { | 341 | impl ModuleData { |
283 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. | 342 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. |
284 | pub fn definition_source( | 343 | pub fn definition_source(&self, db: &impl DefDatabase) -> InFile<ModuleSource> { |
285 | &self, | 344 | self.origin.definition_source(db) |
286 | db: &impl DefDatabase, | ||
287 | ) -> InFile<Either<ast::SourceFile, ast::Module>> { | ||
288 | if let Some(file_id) = self.definition { | ||
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 | } | 345 | } |
295 | 346 | ||
296 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. | 347 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. |
297 | /// `None` for the crate root. | 348 | /// `None` for the crate root or block. |
298 | pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> { | 349 | pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> { |
299 | let decl = self.declaration?; | 350 | let decl = self.origin.declaration()?; |
300 | let value = decl.to_node(db); | 351 | let value = decl.to_node(db); |
301 | Some(InFile { file_id: decl.file_id, value }) | 352 | Some(InFile { file_id: decl.file_id, value }) |
302 | } | 353 | } |
303 | } | 354 | } |
304 | 355 | ||
356 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
357 | pub enum ModuleSource { | ||
358 | SourceFile(ast::SourceFile), | ||
359 | Module(ast::Module), | ||
360 | } | ||
361 | |||
362 | impl ModuleSource { | ||
363 | // FIXME: this methods do not belong here | ||
364 | pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource { | ||
365 | let parse = db.parse(position.file_id); | ||
366 | match &ra_syntax::algo::find_node_at_offset::<ast::Module>( | ||
367 | parse.tree().syntax(), | ||
368 | position.offset, | ||
369 | ) { | ||
370 | Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), | ||
371 | _ => { | ||
372 | let source_file = parse.tree(); | ||
373 | ModuleSource::SourceFile(source_file) | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | |||
378 | pub fn from_child_node(db: &impl DefDatabase, child: InFile<&SyntaxNode>) -> ModuleSource { | ||
379 | if let Some(m) = | ||
380 | child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) | ||
381 | { | ||
382 | ModuleSource::Module(m) | ||
383 | } else { | ||
384 | let file_id = child.file_id.original_file(db); | ||
385 | let source_file = db.parse(file_id).tree(); | ||
386 | ModuleSource::SourceFile(source_file) | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | |||
305 | mod diagnostics { | 391 | mod diagnostics { |
306 | use hir_expand::diagnostics::DiagnosticSink; | 392 | use hir_expand::diagnostics::DiagnosticSink; |
307 | use ra_db::RelativePathBuf; | 393 | use ra_db::RelativePathBuf; |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d4bfcae1d..9d948d4f4 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::CrateRoot { definition: 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 { |