aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/tests/test/main.rs2
-rw-r--r--crates/ra_hir/src/code_model_impl/krate.rs12
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs6
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/module_tree.rs245
-rw-r--r--crates/ra_hir/src/nameres.rs4
-rw-r--r--crates/ra_hir/src/query_definitions.rs13
-rw-r--r--crates/ra_hir/src/source_binder.rs64
8 files changed, 156 insertions, 194 deletions
diff --git a/crates/ra_analysis/tests/test/main.rs b/crates/ra_analysis/tests/test/main.rs
index 85911de92..1f70af12a 100644
--- a/crates/ra_analysis/tests/test/main.rs
+++ b/crates/ra_analysis/tests/test/main.rs
@@ -70,7 +70,7 @@ fn test_resolve_parent_module_for_inline() {
70 ); 70 );
71 let symbols = analysis.parent_module(pos).unwrap(); 71 let symbols = analysis.parent_module(pos).unwrap();
72 assert_eq_dbg( 72 assert_eq_dbg(
73 r#"[NavigationTarget { file_id: FileId(1), name: "bar", kind: MODULE, range: [18; 21), ptr: None }]"#, 73 r#"[NavigationTarget { file_id: FileId(1), name: "baz", kind: MODULE, range: [36; 39), ptr: None }]"#,
74 &symbols, 74 &symbols,
75 ); 75 );
76} 76}
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs
index 591a81597..3275eafed 100644
--- a/crates/ra_hir/src/code_model_impl/krate.rs
+++ b/crates/ra_hir/src/code_model_impl/krate.rs
@@ -1,7 +1,7 @@
1use ra_db::{CrateId, Cancelable}; 1use ra_db::{CrateId, Cancelable};
2 2
3use crate::{ 3use crate::{
4 HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, 4 HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, SourceItemId,
5 db::HirDatabase, 5 db::HirDatabase,
6}; 6};
7 7
@@ -27,15 +27,17 @@ impl Crate {
27 let file_id = HirFileId::from(file_id); 27 let file_id = HirFileId::from(file_id);
28 let module_tree = db.module_tree(source_root_id)?; 28 let module_tree = db.module_tree(source_root_id)?;
29 // FIXME: teach module tree about crate roots instead of guessing 29 // FIXME: teach module tree about crate roots instead of guessing
30 let (module_id, _) = ctry!(module_tree 30 let source = SourceItemId {
31 .modules_with_sources() 31 file_id,
32 .find(|(_, src)| src.file_id() == file_id)); 32 item_id: None,
33 };
34 let module_id = ctry!(module_tree.find_module_by_source(source));
33 35
34 let def_loc = DefLoc { 36 let def_loc = DefLoc {
35 kind: DefKind::Module, 37 kind: DefKind::Module,
36 source_root_id, 38 source_root_id,
37 module_id, 39 module_id,
38 source_item_id: module_id.source(&module_tree).0, 40 source_item_id: module_id.source(&module_tree),
39 }; 41 };
40 let def_id = def_loc.id(db); 42 let def_id = def_loc.id(db);
41 43
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 02078f188..eb35779f1 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -22,7 +22,7 @@ impl Module {
22 kind: DefKind::Module, 22 kind: DefKind::Module,
23 source_root_id, 23 source_root_id,
24 module_id, 24 module_id,
25 source_item_id: module_id.source(&module_tree).0, 25 source_item_id: module_id.source(&module_tree),
26 }; 26 };
27 let def_id = def_loc.id(db); 27 let def_id = def_loc.id(db);
28 let module = Module::new(def_id); 28 let module = Module::new(def_id);
@@ -63,9 +63,9 @@ impl Module {
63 let file_id = link 63 let file_id = link
64 .owner(&module_tree) 64 .owner(&module_tree)
65 .source(&module_tree) 65 .source(&module_tree)
66 .file_id() 66 .file_id
67 .as_original_file(); 67 .as_original_file();
68 let src = link.bind_source(&module_tree, db); 68 let src = link.source(&module_tree, db);
69 Ok(Some((file_id, src))) 69 Ok(Some((file_id, src)))
70 } 70 }
71 71
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index e4249de14..033f9d25f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -9,7 +9,7 @@ use crate::{
9 query_definitions, 9 query_definitions,
10 FnSignature, FnScopes, 10 FnSignature, FnScopes,
11 macros::MacroExpansion, 11 macros::MacroExpansion,
12 module_tree::{ModuleId, ModuleTree, ModuleSource}, 12 module_tree::{ModuleId, ModuleTree},
13 nameres::{ItemMap, InputModuleItems}, 13 nameres::{ItemMap, InputModuleItems},
14 ty::{InferenceResult, Ty}, 14 ty::{InferenceResult, Ty},
15 adt::{StructData, EnumData}, 15 adt::{StructData, EnumData},
@@ -71,7 +71,7 @@ pub trait HirDatabase: SyntaxDatabase
71 use fn query_definitions::file_item; 71 use fn query_definitions::file_item;
72 } 72 }
73 73
74 fn submodules(source: ModuleSource) -> Cancelable<Arc<Vec<crate::module_tree::Submodule>>> { 74 fn submodules(source: SourceItemId) -> Cancelable<Arc<Vec<crate::module_tree::Submodule>>> {
75 type SubmodulesQuery; 75 type SubmodulesQuery;
76 use fn crate::module_tree::Submodule::submodules_query; 76 use fn crate::module_tree::Submodule::submodules_query;
77 } 77 }
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index b7912ba5e..c7a442319 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -11,55 +11,70 @@ use ra_syntax::{
11}; 11};
12use ra_arena::{Arena, RawId, impl_arena_id}; 12use ra_arena::{Arena, RawId, impl_arena_id};
13 13
14use crate::{Name, AsName, HirDatabase, SourceItemId, SourceFileItemId, HirFileId, Problem}; 14use crate::{Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource};
15
16impl ModuleSource {
17 pub fn from_source_item_id(
18 db: &impl HirDatabase,
19 source_item_id: SourceItemId,
20 ) -> ModuleSource {
21 let module_syntax = db.file_item(source_item_id);
22 let module_syntax = module_syntax.borrowed();
23 if let Some(source_file) = ast::SourceFile::cast(module_syntax) {
24 ModuleSource::SourceFile(source_file.owned())
25 } else if let Some(module) = ast::Module::cast(module_syntax) {
26 assert!(module.item_list().is_some(), "expected inline module");
27 ModuleSource::Module(module.owned())
28 } else {
29 panic!("expected file or inline module")
30 }
31 }
32}
15 33
16#[derive(Clone, Hash, PartialEq, Eq, Debug)] 34#[derive(Clone, Hash, PartialEq, Eq, Debug)]
17pub enum Submodule { 35pub struct Submodule {
18 Declaration(Name), 36 name: Name,
19 Definition(Name, ModuleSource), 37 is_declaration: bool,
38 source: SourceItemId,
20} 39}
21 40
22impl Submodule { 41impl Submodule {
23 pub(crate) fn submodules_query( 42 pub(crate) fn submodules_query(
24 db: &impl HirDatabase, 43 db: &impl HirDatabase,
25 source: ModuleSource, 44 source: SourceItemId,
26 ) -> Cancelable<Arc<Vec<Submodule>>> { 45 ) -> Cancelable<Arc<Vec<Submodule>>> {
27 db.check_canceled()?; 46 db.check_canceled()?;
28 let file_id = source.file_id(); 47 let file_id = source.file_id;
29 let submodules = match source.resolve(db) { 48 let file_items = db.file_items(file_id);
30 ModuleSourceNode::SourceFile(it) => collect_submodules(db, file_id, it.borrowed()), 49 let module_source = ModuleSource::from_source_item_id(db, source);
31 ModuleSourceNode::Module(it) => it 50 let submodules = match module_source {
32 .borrowed() 51 ModuleSource::SourceFile(source_file) => {
33 .item_list() 52 collect_submodules(file_id, &file_items, source_file.borrowed())
34 .map(|it| collect_submodules(db, file_id, it)) 53 }
35 .unwrap_or_else(Vec::new), 54 ModuleSource::Module(module) => {
55 let module = module.borrowed();
56 collect_submodules(file_id, &file_items, module.item_list().unwrap())
57 }
36 }; 58 };
37 return Ok(Arc::new(submodules)); 59 return Ok(Arc::new(submodules));
38 60
39 fn collect_submodules<'a>( 61 fn collect_submodules<'a>(
40 db: &impl HirDatabase,
41 file_id: HirFileId, 62 file_id: HirFileId,
63 file_items: &SourceFileItems,
42 root: impl ast::ModuleItemOwner<'a>, 64 root: impl ast::ModuleItemOwner<'a>,
43 ) -> Vec<Submodule> { 65 ) -> Vec<Submodule> {
44 modules(root) 66 modules(root)
45 .map(|(name, m)| { 67 .map(|(name, m)| Submodule {
46 if m.has_semi() { 68 name,
47 Submodule::Declaration(name) 69 is_declaration: m.has_semi(),
48 } else { 70 source: SourceItemId {
49 let src = ModuleSource::new_inline(db, file_id, m); 71 file_id,
50 Submodule::Definition(name, src) 72 item_id: Some(file_items.id_of(file_id, m.syntax())),
51 } 73 },
52 }) 74 })
53 .collect() 75 .collect()
54 } 76 }
55 } 77 }
56
57 fn name(&self) -> &Name {
58 match self {
59 Submodule::Declaration(name) => name,
60 Submodule::Definition(name, _) => name,
61 }
62 }
63} 78}
64 79
65#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 80#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -85,13 +100,14 @@ pub struct ModuleTree {
85 100
86#[derive(Debug, PartialEq, Eq, Hash)] 101#[derive(Debug, PartialEq, Eq, Hash)]
87pub struct ModuleData { 102pub struct ModuleData {
88 source: ModuleSource, 103 source: SourceItemId,
89 parent: Option<LinkId>, 104 parent: Option<LinkId>,
90 children: Vec<LinkId>, 105 children: Vec<LinkId>,
91} 106}
92 107
93#[derive(Hash, Debug, PartialEq, Eq)] 108#[derive(Hash, Debug, PartialEq, Eq)]
94struct LinkData { 109struct LinkData {
110 source: SourceItemId,
95 owner: ModuleId, 111 owner: ModuleId,
96 name: Name, 112 name: Name,
97 points_to: Vec<ModuleId>, 113 points_to: Vec<ModuleId>,
@@ -112,27 +128,14 @@ impl ModuleTree {
112 self.mods.iter().map(|(id, _)| id) 128 self.mods.iter().map(|(id, _)| id)
113 } 129 }
114 130
115 pub(crate) fn modules_with_sources<'a>( 131 pub(crate) fn find_module_by_source(&self, source: SourceItemId) -> Option<ModuleId> {
116 &'a self, 132 let (res, _) = self.mods.iter().find(|(_, m)| m.source == source)?;
117 ) -> impl Iterator<Item = (ModuleId, ModuleSource)> + 'a { 133 Some(res)
118 self.mods.iter().map(|(id, m)| (id, m.source))
119 } 134 }
120} 135}
121 136
122/// `ModuleSource` is the syntax tree element that produced this module:
123/// either a file, or an inlinde module.
124#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
125pub struct ModuleSource(pub(crate) SourceItemId);
126
127/// An owned syntax node for a module. Unlike `ModuleSource`,
128/// this holds onto the AST for the whole file.
129pub(crate) enum ModuleSourceNode {
130 SourceFile(ast::SourceFileNode),
131 Module(ast::ModuleNode),
132}
133
134impl ModuleId { 137impl ModuleId {
135 pub(crate) fn source(self, tree: &ModuleTree) -> ModuleSource { 138 pub(crate) fn source(self, tree: &ModuleTree) -> SourceItemId {
136 tree.mods[self].source 139 tree.mods[self].source
137 } 140 }
138 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { 141 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
@@ -173,9 +176,9 @@ impl ModuleId {
173 tree.mods[self] 176 tree.mods[self]
174 .children 177 .children
175 .iter() 178 .iter()
176 .filter_map(|&it| { 179 .filter_map(|&link| {
177 let p = tree.links[it].problem.clone()?; 180 let p = tree.links[link].problem.clone()?;
178 let s = it.bind_source(tree, db); 181 let s = link.source(tree, db);
179 let s = s.borrowed().name().unwrap().syntax().owned(); 182 let s = s.borrowed().name().unwrap().syntax().owned();
180 Some((s, p)) 183 Some((s, p))
181 }) 184 })
@@ -190,59 +193,11 @@ impl LinkId {
190 pub(crate) fn name(self, tree: &ModuleTree) -> &Name { 193 pub(crate) fn name(self, tree: &ModuleTree) -> &Name {
191 &tree.links[self].name 194 &tree.links[self].name
192 } 195 }
193 pub(crate) fn bind_source<'a>( 196 pub(crate) fn source(self, tree: &ModuleTree, db: &impl HirDatabase) -> ast::ModuleNode {
194 self, 197 let syntax_node = db.file_item(tree.links[self].source);
195 tree: &ModuleTree, 198 ast::ModuleNode::cast(syntax_node.borrowed())
196 db: &impl HirDatabase, 199 .unwrap()
197 ) -> ast::ModuleNode { 200 .owned()
198 let owner = self.owner(tree);
199 match owner.source(tree).resolve(db) {
200 ModuleSourceNode::SourceFile(root) => {
201 let ast = modules(root.borrowed())
202 .find(|(name, _)| name == &tree.links[self].name)
203 .unwrap()
204 .1;
205 ast.owned()
206 }
207 ModuleSourceNode::Module(it) => it,
208 }
209 }
210}
211
212impl ModuleSource {
213 // precondition: item_id **must** point to module
214 fn new(file_id: HirFileId, item_id: Option<SourceFileItemId>) -> ModuleSource {
215 let source_item_id = SourceItemId { file_id, item_id };
216 ModuleSource(source_item_id)
217 }
218
219 pub(crate) fn new_file(file_id: HirFileId) -> ModuleSource {
220 ModuleSource::new(file_id, None)
221 }
222
223 pub(crate) fn new_inline(
224 db: &impl HirDatabase,
225 file_id: HirFileId,
226 m: ast::Module,
227 ) -> ModuleSource {
228 assert!(!m.has_semi());
229 let file_items = db.file_items(file_id);
230 let item_id = file_items.id_of(file_id, m.syntax());
231 ModuleSource::new(file_id, Some(item_id))
232 }
233
234 pub(crate) fn file_id(self) -> HirFileId {
235 self.0.file_id
236 }
237
238 pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode {
239 let syntax_node = db.file_item(self.0);
240 let syntax_node = syntax_node.borrowed();
241 if let Some(file) = ast::SourceFile::cast(syntax_node) {
242 return ModuleSourceNode::SourceFile(file.owned());
243 }
244 let module = ast::Module::cast(syntax_node).unwrap();
245 ModuleSourceNode::Module(module.owned())
246 } 201 }
247} 202}
248 203
@@ -283,7 +238,10 @@ fn create_module_tree<'a>(
283 238
284 let source_root = db.source_root(source_root); 239 let source_root = db.source_root(source_root);
285 for &file_id in source_root.files.values() { 240 for &file_id in source_root.files.values() {
286 let source = ModuleSource::new_file(file_id.into()); 241 let source = SourceItemId {
242 file_id: file_id.into(),
243 item_id: None,
244 };
287 if visited.contains(&source) { 245 if visited.contains(&source) {
288 continue; // TODO: use explicit crate_roots here 246 continue; // TODO: use explicit crate_roots here
289 } 247 }
@@ -306,10 +264,10 @@ fn build_subtree(
306 db: &impl HirDatabase, 264 db: &impl HirDatabase,
307 source_root: &SourceRoot, 265 source_root: &SourceRoot,
308 tree: &mut ModuleTree, 266 tree: &mut ModuleTree,
309 visited: &mut FxHashSet<ModuleSource>, 267 visited: &mut FxHashSet<SourceItemId>,
310 roots: &mut FxHashMap<FileId, ModuleId>, 268 roots: &mut FxHashMap<FileId, ModuleId>,
311 parent: Option<LinkId>, 269 parent: Option<LinkId>,
312 source: ModuleSource, 270 source: SourceItemId,
313) -> Cancelable<ModuleId> { 271) -> Cancelable<ModuleId> {
314 visited.insert(source); 272 visited.insert(source);
315 let id = tree.push_mod(ModuleData { 273 let id = tree.push_mod(ModuleData {
@@ -319,47 +277,48 @@ fn build_subtree(
319 }); 277 });
320 for sub in db.submodules(source)?.iter() { 278 for sub in db.submodules(source)?.iter() {
321 let link = tree.push_link(LinkData { 279 let link = tree.push_link(LinkData {
322 name: sub.name().clone(), 280 source: sub.source,
281 name: sub.name.clone(),
323 owner: id, 282 owner: id,
324 points_to: Vec::new(), 283 points_to: Vec::new(),
325 problem: None, 284 problem: None,
326 }); 285 });
327 286
328 let (points_to, problem) = match sub { 287 let (points_to, problem) = if sub.is_declaration {
329 Submodule::Declaration(name) => { 288 let (points_to, problem) = resolve_submodule(db, source.file_id, &sub.name);
330 let (points_to, problem) = resolve_submodule(db, source, &name); 289 let points_to = points_to
331 let points_to = points_to 290 .into_iter()
332 .into_iter() 291 .map(|file_id| match roots.remove(&file_id) {
333 .map(|file_id| match roots.remove(&file_id) { 292 Some(module_id) => {
334 Some(module_id) => { 293 tree.mods[module_id].parent = Some(link);
335 tree.mods[module_id].parent = Some(link); 294 Ok(module_id)
336 Ok(module_id) 295 }
337 } 296 None => build_subtree(
338 None => build_subtree( 297 db,
339 db, 298 source_root,
340 source_root, 299 tree,
341 tree, 300 visited,
342 visited, 301 roots,
343 roots, 302 Some(link),
344 Some(link), 303 SourceItemId {
345 ModuleSource::new_file(file_id.into()), 304 file_id: file_id.into(),
346 ), 305 item_id: None,
347 }) 306 },
348 .collect::<Cancelable<Vec<_>>>()?; 307 ),
349 (points_to, problem) 308 })
350 } 309 .collect::<Cancelable<Vec<_>>>()?;
351 Submodule::Definition(_name, submodule_source) => { 310 (points_to, problem)
352 let points_to = build_subtree( 311 } else {
353 db, 312 let points_to = build_subtree(
354 source_root, 313 db,
355 tree, 314 source_root,
356 visited, 315 tree,
357 roots, 316 visited,
358 Some(link), 317 roots,
359 *submodule_source, 318 Some(link),
360 )?; 319 sub.source,
361 (vec![points_to], None) 320 )?;
362 } 321 (vec![points_to], None)
363 }; 322 };
364 323
365 tree.links[link].points_to = points_to; 324 tree.links[link].points_to = points_to;
@@ -370,11 +329,11 @@ fn build_subtree(
370 329
371fn resolve_submodule( 330fn resolve_submodule(
372 db: &impl HirDatabase, 331 db: &impl HirDatabase,
373 source: ModuleSource, 332 file_id: HirFileId,
374 name: &Name, 333 name: &Name,
375) -> (Vec<FileId>, Option<Problem>) { 334) -> (Vec<FileId>, Option<Problem>) {
376 // FIXME: handle submodules of inline modules properly 335 // FIXME: handle submodules of inline modules properly
377 let file_id = source.file_id().original_file(db); 336 let file_id = file_id.original_file(db);
378 let source_root_id = db.file_source_root(file_id); 337 let source_root_id = db.file_source_root(file_id);
379 let path = db.file_relative_path(file_id); 338 let path = db.file_relative_path(file_id);
380 let root = RelativePathBuf::default(); 339 let root = RelativePathBuf::default();
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index e65cbcb27..9a412bc82 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -339,7 +339,7 @@ where
339 // Populate extern crates prelude 339 // Populate extern crates prelude
340 { 340 {
341 let root_id = module_id.crate_root(&self.module_tree); 341 let root_id = module_id.crate_root(&self.module_tree);
342 let file_id = root_id.source(&self.module_tree).file_id(); 342 let file_id = root_id.source(&self.module_tree).file_id;
343 let crate_graph = self.db.crate_graph(); 343 let crate_graph = self.db.crate_graph();
344 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) 344 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file())
345 { 345 {
@@ -399,7 +399,7 @@ where
399 kind: DefKind::Module, 399 kind: DefKind::Module,
400 source_root_id: self.source_root, 400 source_root_id: self.source_root,
401 module_id, 401 module_id,
402 source_item_id: module_id.source(&self.module_tree).0, 402 source_item_id: module_id.source(&self.module_tree),
403 }; 403 };
404 let def_id = def_loc.id(self.db); 404 let def_id = def_loc.id(self.db);
405 self.add_module_item(&mut module_items, name, PerNs::types(def_id)); 405 self.add_module_item(&mut module_items, name, PerNs::types(def_id));
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index f4b380022..8f2c40669 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -11,11 +11,11 @@ use ra_syntax::{
11use ra_db::{SourceRootId, Cancelable,}; 11use ra_db::{SourceRootId, Cancelable,};
12 12
13use crate::{ 13use crate::{
14 SourceFileItems, SourceItemId, DefKind, DefId, HirFileId, 14 SourceFileItems, SourceItemId, DefKind, DefId, HirFileId, ModuleSource,
15 MacroCallLoc, 15 MacroCallLoc,
16 db::HirDatabase, 16 db::HirDatabase,
17 function::FnScopes, 17 function::FnScopes,
18 module_tree::{ModuleId, ModuleSourceNode}, 18 module_tree::ModuleId,
19 nameres::{InputModuleItems, ItemMap, Resolver}, 19 nameres::{InputModuleItems, ItemMap, Resolver},
20 adt::{StructData, EnumData}, 20 adt::{StructData, EnumData},
21}; 21};
@@ -65,7 +65,8 @@ pub(super) fn input_module_items(
65) -> Cancelable<Arc<InputModuleItems>> { 65) -> Cancelable<Arc<InputModuleItems>> {
66 let module_tree = db.module_tree(source_root_id)?; 66 let module_tree = db.module_tree(source_root_id)?;
67 let source = module_id.source(&module_tree); 67 let source = module_id.source(&module_tree);
68 let file_id = source.file_id(); 68 let file_id = source.file_id;
69 let source = ModuleSource::from_source_item_id(db, source);
69 let file_items = db.file_items(file_id); 70 let file_items = db.file_items(file_id);
70 let fill = |acc: &mut InputModuleItems, items: &mut Iterator<Item = ast::ItemOrMacro>| { 71 let fill = |acc: &mut InputModuleItems, items: &mut Iterator<Item = ast::ItemOrMacro>| {
71 for item in items { 72 for item in items {
@@ -96,9 +97,9 @@ pub(super) fn input_module_items(
96 }; 97 };
97 98
98 let mut res = InputModuleItems::default(); 99 let mut res = InputModuleItems::default();
99 match source.resolve(db) { 100 match source {
100 ModuleSourceNode::SourceFile(it) => fill(&mut res, &mut it.borrowed().items_with_macros()), 101 ModuleSource::SourceFile(it) => fill(&mut res, &mut it.borrowed().items_with_macros()),
101 ModuleSourceNode::Module(it) => { 102 ModuleSource::Module(it) => {
102 if let Some(item_list) = it.borrowed().item_list() { 103 if let Some(item_list) = it.borrowed().item_list() {
103 fill(&mut res, &mut item_list.items_with_macros()) 104 fill(&mut res, &mut item_list.items_with_macros())
104 } 105 }
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index b7e3ff9b0..4c14650c0 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -14,15 +14,15 @@ use ra_syntax::{
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, SourceItemId, 16 HirDatabase, Function, SourceItemId,
17 module_tree::ModuleSource, 17 DefKind, DefLoc, AsName, Module,
18 DefKind, DefLoc, AsName,
19}; 18};
20 19
21use crate::code_model_api::Module;
22
23/// Locates the module by `FileId`. Picks topmost module in the file. 20/// Locates the module by `FileId`. Picks topmost module in the file.
24pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> { 21pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> {
25 let module_source = ModuleSource::new_file(file_id.into()); 22 let module_source = SourceItemId {
23 file_id: file_id.into(),
24 item_id: None,
25 };
26 module_from_source(db, module_source) 26 module_from_source(db, module_source)
27} 27}
28 28
@@ -51,11 +51,26 @@ pub fn module_from_position(
51 position: FilePosition, 51 position: FilePosition,
52) -> Cancelable<Option<Module>> { 52) -> Cancelable<Option<Module>> {
53 let file = db.source_file(position.file_id); 53 let file = db.source_file(position.file_id);
54 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) { 54 match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) {
55 Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id.into(), m), 55 Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m),
56 _ => ModuleSource::new_file(position.file_id.into()), 56 _ => module_from_file_id(db, position.file_id.into()),
57 }
58}
59
60fn module_from_inline(
61 db: &impl HirDatabase,
62 file_id: FileId,
63 module: ast::Module,
64) -> Cancelable<Option<Module>> {
65 assert!(!module.has_semi());
66 let file_id = file_id.into();
67 let file_items = db.file_items(file_id);
68 let item_id = file_items.id_of(file_id, module.syntax());
69 let source = SourceItemId {
70 file_id,
71 item_id: Some(item_id),
57 }; 72 };
58 module_from_source(db, module_source) 73 module_from_source(db, source)
59} 74}
60 75
61/// Locates the module by child syntax element within the module 76/// Locates the module by child syntax element within the module
@@ -64,37 +79,22 @@ pub fn module_from_child_node(
64 file_id: FileId, 79 file_id: FileId,
65 child: SyntaxNodeRef, 80 child: SyntaxNodeRef,
66) -> Cancelable<Option<Module>> { 81) -> Cancelable<Option<Module>> {
67 let module_source = if let Some(m) = child 82 if let Some(m) = child
68 .ancestors() 83 .ancestors()
69 .filter_map(ast::Module::cast) 84 .filter_map(ast::Module::cast)
70 .find(|it| !it.has_semi()) 85 .find(|it| !it.has_semi())
71 { 86 {
72 ModuleSource::new_inline(db, file_id.into(), m) 87 module_from_inline(db, file_id.into(), m)
73 } else { 88 } else {
74 ModuleSource::new_file(file_id.into()) 89 module_from_file_id(db, file_id.into())
75 }; 90 }
76 module_from_source(db, module_source)
77} 91}
78 92
79fn module_from_source( 93fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Cancelable<Option<Module>> {
80 db: &impl HirDatabase, 94 let source_root_id = db.file_source_root(source.file_id.as_original_file());
81 module_source: ModuleSource,
82) -> Cancelable<Option<Module>> {
83 let source_root_id = db.file_source_root(module_source.file_id().as_original_file());
84 let module_tree = db.module_tree(source_root_id)?; 95 let module_tree = db.module_tree(source_root_id)?;
85 let m = module_tree 96 let module_id = ctry!(module_tree.find_module_by_source(source));
86 .modules_with_sources() 97 Ok(Some(Module::from_module_id(db, source_root_id, module_id)?))
87 .find(|(_id, src)| src == &module_source);
88 let module_id = ctry!(m).0;
89 let def_loc = DefLoc {
90 kind: DefKind::Module,
91 source_root_id,
92 module_id,
93 source_item_id: module_source.0,
94 };
95 let def_id = def_loc.id(db);
96
97 Ok(Some(Module::new(def_id)))
98} 98}
99 99
100pub fn function_from_position( 100pub fn function_from_position(