aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/module
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/module')
-rw-r--r--crates/ra_hir/src/module/imp.rs13
-rw-r--r--crates/ra_hir/src/module/mod.rs107
-rw-r--r--crates/ra_hir/src/module/nameres.rs23
3 files changed, 82 insertions, 61 deletions
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs
index 76ea129a7..0eec38797 100644
--- a/crates/ra_hir/src/module/imp.rs
+++ b/crates/ra_hir/src/module/imp.rs
@@ -66,7 +66,7 @@ fn create_module_tree<'a>(
66 66
67 let source_root = db.source_root(source_root); 67 let source_root = db.source_root(source_root);
68 for &file_id in source_root.files.iter() { 68 for &file_id in source_root.files.iter() {
69 let source = ModuleSource::SourceFile(file_id); 69 let source = ModuleSource::new_file(db, file_id);
70 if visited.contains(&source) { 70 if visited.contains(&source) {
71 continue; // TODO: use explicit crate_roots here 71 continue; // TODO: use explicit crate_roots here
72 } 72 }
@@ -126,7 +126,7 @@ fn build_subtree(
126 visited, 126 visited,
127 roots, 127 roots,
128 Some(link), 128 Some(link),
129 ModuleSource::SourceFile(file_id), 129 ModuleSource::new_file(db, file_id),
130 ), 130 ),
131 }) 131 })
132 .collect::<Cancelable<Vec<_>>>()?; 132 .collect::<Cancelable<Vec<_>>>()?;
@@ -157,13 +157,8 @@ fn resolve_submodule(
157 name: &SmolStr, 157 name: &SmolStr,
158 file_resolver: &FileResolverImp, 158 file_resolver: &FileResolverImp,
159) -> (Vec<FileId>, Option<Problem>) { 159) -> (Vec<FileId>, Option<Problem>) {
160 let file_id = match source { 160 // TODO: handle submodules of inline modules properly
161 ModuleSource::SourceFile(it) => it, 161 let file_id = source.file_id();
162 ModuleSource::Module(..) => {
163 // TODO
164 return (Vec::new(), None);
165 }
166 };
167 let mod_name = file_resolver.file_stem(file_id); 162 let mod_name = file_resolver.file_stem(file_id);
168 let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; 163 let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main";
169 164
diff --git a/crates/ra_hir/src/module/mod.rs b/crates/ra_hir/src/module/mod.rs
index 3ae83d8cb..11e6e8e75 100644
--- a/crates/ra_hir/src/module/mod.rs
+++ b/crates/ra_hir/src/module/mod.rs
@@ -8,13 +8,13 @@ use ra_editor::find_node_at_offset;
8use ra_syntax::{ 8use ra_syntax::{
9 algo::generate, 9 algo::generate,
10 ast::{self, AstNode, NameOwner}, 10 ast::{self, AstNode, NameOwner},
11 SmolStr, SyntaxNode, 11 SmolStr, SyntaxNode, SyntaxNodeRef,
12}; 12};
13use ra_db::{SourceRootId, FileId, FilePosition, Cancelable}; 13use ra_db::{SourceRootId, FileId, FilePosition, Cancelable};
14use relative_path::RelativePathBuf; 14use relative_path::RelativePathBuf;
15 15
16use crate::{ 16use crate::{
17 DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, 17 DefKind, DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId,
18 arena::{Arena, Id}, 18 arena::{Arena, Id},
19}; 19};
20 20
@@ -25,8 +25,8 @@ pub use self::nameres::ModuleScope;
25#[derive(Debug, Clone)] 25#[derive(Debug, Clone)]
26pub struct Module { 26pub struct Module {
27 tree: Arc<ModuleTree>, 27 tree: Arc<ModuleTree>,
28 source_root_id: SourceRootId, 28 pub(crate) source_root_id: SourceRootId,
29 module_id: ModuleId, 29 pub(crate) module_id: ModuleId,
30} 30}
31 31
32impl Module { 32impl Module {
@@ -37,7 +37,8 @@ impl Module {
37 db: &impl HirDatabase, 37 db: &impl HirDatabase,
38 file_id: FileId, 38 file_id: FileId,
39 ) -> Cancelable<Option<Module>> { 39 ) -> Cancelable<Option<Module>> {
40 Module::guess_from_source(db, file_id, ModuleSource::SourceFile(file_id)) 40 let module_source = ModuleSource::new_file(db, file_id);
41 Module::guess_from_source(db, module_source)
41 } 42 }
42 43
43 /// Lookup `Module` by position in the source code. Note that this 44 /// Lookup `Module` by position in the source code. Note that this
@@ -51,17 +52,33 @@ impl Module {
51 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) 52 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset)
52 { 53 {
53 Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m), 54 Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m),
54 _ => ModuleSource::SourceFile(position.file_id), 55 _ => ModuleSource::new_file(db, position.file_id),
55 }; 56 };
56 Module::guess_from_source(db, position.file_id, module_source) 57 Module::guess_from_source(db, module_source)
57 } 58 }
58 59
59 fn guess_from_source( 60 pub fn guess_from_child_node(
60 db: &impl HirDatabase, 61 db: &impl HirDatabase,
61 file_id: FileId, 62 file_id: FileId,
63 node: SyntaxNodeRef,
64 ) -> Cancelable<Option<Module>> {
65 let module_source = if let Some(m) = node
66 .ancestors()
67 .filter_map(ast::Module::cast)
68 .find(|it| !it.has_semi())
69 {
70 ModuleSource::new_inline(db, file_id, m)
71 } else {
72 ModuleSource::new_file(db, file_id)
73 };
74 Module::guess_from_source(db, module_source)
75 }
76
77 fn guess_from_source(
78 db: &impl HirDatabase,
62 module_source: ModuleSource, 79 module_source: ModuleSource,
63 ) -> Cancelable<Option<Module>> { 80 ) -> Cancelable<Option<Module>> {
64 let source_root_id = db.file_source_root(file_id); 81 let source_root_id = db.file_source_root(module_source.file_id());
65 let module_tree = db.module_tree(source_root_id)?; 82 let module_tree = db.module_tree(source_root_id)?;
66 83
67 let res = match module_tree.any_module_for_source(module_source) { 84 let res = match module_tree.any_module_for_source(module_source) {
@@ -127,9 +144,11 @@ impl Module {
127 } 144 }
128 145
129 pub fn def_id(&self, db: &impl HirDatabase) -> DefId { 146 pub fn def_id(&self, db: &impl HirDatabase) -> DefId {
130 let def_loc = DefLoc::Module { 147 let def_loc = DefLoc {
131 id: self.module_id, 148 kind: DefKind::Module,
132 source_root: self.source_root_id, 149 source_root_id: self.source_root_id,
150 module_id: self.module_id,
151 source_item_id: self.module_id.source(&self.tree).0,
133 }; 152 };
134 def_loc.id(db) 153 def_loc.id(db)
135 } 154 }
@@ -161,7 +180,12 @@ impl Module {
161 let segments = path.segments; 180 let segments = path.segments;
162 for name in segments.iter() { 181 for name in segments.iter() {
163 let module = match curr.loc(db) { 182 let module = match curr.loc(db) {
164 DefLoc::Module { id, source_root } => Module::new(db, source_root, id)?, 183 DefLoc {
184 kind: DefKind::Module,
185 source_root_id,
186 module_id,
187 ..
188 } => Module::new(db, source_root_id, module_id)?,
165 _ => return Ok(None), 189 _ => return Ok(None),
166 }; 190 };
167 let scope = module.scope(db)?; 191 let scope = module.scope(db)?;
@@ -209,10 +233,7 @@ impl ModuleTree {
209/// `ModuleSource` is the syntax tree element that produced this module: 233/// `ModuleSource` is the syntax tree element that produced this module:
210/// either a file, or an inlinde module. 234/// either a file, or an inlinde module.
211#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 235#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
212pub enum ModuleSource { 236pub struct ModuleSource(SourceItemId);
213 SourceFile(FileId),
214 Module(SourceItemId),
215}
216 237
217/// An owned syntax node for a module. Unlike `ModuleSource`, 238/// An owned syntax node for a module. Unlike `ModuleSource`,
218/// this holds onto the AST for the whole file. 239/// this holds onto the AST for the whole file.
@@ -310,45 +331,41 @@ pub struct ModuleData {
310} 331}
311 332
312impl ModuleSource { 333impl ModuleSource {
334 // precondition: item_id **must** point to module
335 fn new(file_id: FileId, item_id: SourceFileItemId) -> ModuleSource {
336 let source_item_id = SourceItemId { file_id, item_id };
337 ModuleSource(source_item_id)
338 }
339
340 pub(crate) fn new_file(db: &impl HirDatabase, file_id: FileId) -> ModuleSource {
341 let file_items = db.file_items(file_id);
342 let item_id = file_items.id_of_source_file();
343 ModuleSource::new(file_id, item_id)
344 }
345
313 pub(crate) fn new_inline( 346 pub(crate) fn new_inline(
314 db: &impl HirDatabase, 347 db: &impl HirDatabase,
315 file_id: FileId, 348 file_id: FileId,
316 module: ast::Module, 349 m: ast::Module,
317 ) -> ModuleSource { 350 ) -> ModuleSource {
318 assert!(!module.has_semi()); 351 assert!(!m.has_semi());
319 let items = db.file_items(file_id); 352 let file_items = db.file_items(file_id);
320 let item_id = items.id_of(module.syntax()); 353 let item_id = file_items.id_of(m.syntax());
321 let id = SourceItemId { file_id, item_id }; 354 ModuleSource::new(file_id, item_id)
322 ModuleSource::Module(id)
323 }
324
325 pub fn as_file(self) -> Option<FileId> {
326 match self {
327 ModuleSource::SourceFile(f) => Some(f),
328 ModuleSource::Module(..) => None,
329 }
330 } 355 }
331 356
332 pub fn file_id(self) -> FileId { 357 pub fn file_id(self) -> FileId {
333 match self { 358 self.0.file_id
334 ModuleSource::SourceFile(f) => f,
335 ModuleSource::Module(source_item_id) => source_item_id.file_id,
336 }
337 } 359 }
338 360
339 pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode { 361 pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode {
340 match self { 362 let syntax_node = db.file_item(self.0);
341 ModuleSource::SourceFile(file_id) => { 363 let syntax_node = syntax_node.borrowed();
342 let syntax = db.source_file(file_id); 364 if let Some(file) = ast::SourceFile::cast(syntax_node) {
343 ModuleSourceNode::SourceFile(syntax.ast().owned()) 365 return ModuleSourceNode::SourceFile(file.owned());
344 }
345 ModuleSource::Module(item_id) => {
346 let syntax = db.file_item(item_id);
347 let syntax = syntax.borrowed();
348 let module = ast::Module::cast(syntax).unwrap();
349 ModuleSourceNode::Module(module.owned())
350 }
351 } 366 }
367 let module = ast::Module::cast(syntax_node).unwrap();
368 ModuleSourceNode::Module(module.owned())
352 } 369 }
353} 370}
354 371
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs
index 8529e16b3..c2b380a80 100644
--- a/crates/ra_hir/src/module/nameres.rs
+++ b/crates/ra_hir/src/module/nameres.rs
@@ -28,7 +28,7 @@ use ra_db::SourceRootId;
28 28
29use crate::{ 29use crate::{
30 Cancelable, FileId, 30 Cancelable, FileId,
31 DefId, DefLoc, 31 DefId, DefLoc, DefKind,
32 SourceItemId, SourceFileItemId, SourceFileItems, 32 SourceItemId, SourceFileItemId, SourceFileItems,
33 Path, PathKind, 33 Path, PathKind,
34 HirDatabase, 34 HirDatabase,
@@ -247,7 +247,10 @@ where
247 // handle submodules separatelly 247 // handle submodules separatelly
248 continue; 248 continue;
249 } 249 }
250 let def_loc = DefLoc::Item { 250 let def_loc = DefLoc {
251 kind: DefKind::Item,
252 source_root_id: self.source_root,
253 module_id,
251 source_item_id: SourceItemId { 254 source_item_id: SourceItemId {
252 file_id, 255 file_id,
253 item_id: item.id, 256 item_id: item.id,
@@ -261,10 +264,12 @@ where
261 module_items.items.insert(item.name.clone(), resolution); 264 module_items.items.insert(item.name.clone(), resolution);
262 } 265 }
263 266
264 for (name, mod_id) in module_id.children(&self.module_tree) { 267 for (name, module_id) in module_id.children(&self.module_tree) {
265 let def_loc = DefLoc::Module { 268 let def_loc = DefLoc {
266 id: mod_id, 269 kind: DefKind::Module,
267 source_root: self.source_root, 270 source_root_id: self.source_root,
271 module_id,
272 source_item_id: module_id.source(&self.module_tree).0,
268 }; 273 };
269 let def_id = def_loc.id(self.db); 274 let def_id = def_loc.id(self.db);
270 let resolution = Resolution { 275 let resolution = Resolution {
@@ -316,7 +321,11 @@ where
316 321
317 if !is_last { 322 if !is_last {
318 curr = match def_id.loc(self.db) { 323 curr = match def_id.loc(self.db) {
319 DefLoc::Module { id, .. } => id, 324 DefLoc {
325 kind: DefKind::Module,
326 module_id,
327 ..
328 } => module_id,
320 _ => return, 329 _ => return,
321 } 330 }
322 } else { 331 } else {