aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs2
-rw-r--r--crates/ra_analysis/src/db.rs9
-rw-r--r--crates/ra_analysis/src/imp.rs46
-rw-r--r--crates/ra_analysis/src/lib.rs2
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/function/mod.rs45
-rw-r--r--crates/ra_hir/src/lib.rs61
-rw-r--r--crates/ra_hir/src/mock.rs9
-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
-rw-r--r--crates/ra_hir/src/query_definitions.rs25
12 files changed, 186 insertions, 160 deletions
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index 8ea7478a8..f483ed045 100644
--- a/crates/ra_analysis/src/completion/reference_completion.rs
+++ b/crates/ra_analysis/src/completion/reference_completion.rs
@@ -163,7 +163,7 @@ fn complete_path(
163 }; 163 };
164 let target_module = match def_id.resolve(db)? { 164 let target_module = match def_id.resolve(db)? {
165 Def::Module(it) => it, 165 Def::Module(it) => it,
166 Def::Item => return Ok(()), 166 _ => return Ok(()),
167 }; 167 };
168 let module_scope = target_module.scope(db)?; 168 let module_scope = target_module.scope(db)?;
169 let completions = module_scope.entries().map(|(name, _res)| CompletionItem { 169 let completions = module_scope.entries().map(|(name, _res)| CompletionItem {
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index df2ef293d..b8d774eb5 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use salsa::{self, Database}; 2use salsa::{self, Database};
3use ra_db::{LocationIntener, BaseDatabase}; 3use ra_db::{LocationIntener, BaseDatabase};
4use hir::{self, DefId, DefLoc, FnId, SourceItemId}; 4use hir::{self, DefId, DefLoc};
5 5
6use crate::{ 6use crate::{
7 symbol_index, 7 symbol_index,
@@ -15,7 +15,6 @@ pub(crate) struct RootDatabase {
15 15
16#[derive(Debug, Default)] 16#[derive(Debug, Default)]
17struct IdMaps { 17struct IdMaps {
18 fns: LocationIntener<SourceItemId, FnId>,
19 defs: LocationIntener<DefLoc, DefId>, 18 defs: LocationIntener<DefLoc, DefId>,
20} 19}
21 20
@@ -58,12 +57,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
58 } 57 }
59} 58}
60 59
61impl AsRef<LocationIntener<hir::SourceItemId, FnId>> for RootDatabase {
62 fn as_ref(&self) -> &LocationIntener<hir::SourceItemId, FnId> {
63 &self.id_maps.fns
64 }
65}
66
67salsa::database_storage! { 60salsa::database_storage! {
68 pub(crate) struct RootDatabaseStorage for RootDatabase { 61 pub(crate) struct RootDatabaseStorage for RootDatabase {
69 impl ra_db::FilesDatabase { 62 impl ra_db::FilesDatabase {
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index f5cb3550e..fe1dfefea 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -190,10 +190,7 @@ impl AnalysisImpl {
190 Some(it) => it, 190 Some(it) => it,
191 }; 191 };
192 let root = descr.crate_root(); 192 let root = descr.crate_root();
193 let file_id = root 193 let file_id = root.source().file_id();
194 .source()
195 .as_file()
196 .expect("root module always has a file as a source");
197 194
198 let crate_graph = self.db.crate_graph(); 195 let crate_graph = self.db.crate_graph();
199 let crate_id = crate_graph.crate_id_for_crate_root(file_id); 196 let crate_id = crate_graph.crate_id_for_crate_root(file_id);
@@ -213,7 +210,7 @@ impl AnalysisImpl {
213 let syntax = file.syntax(); 210 let syntax = file.syntax();
214 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { 211 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
215 if let Some(fn_descr) = 212 if let Some(fn_descr) =
216 hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref) 213 hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref)?
217 { 214 {
218 let scope = fn_descr.scope(&*self.db); 215 let scope = fn_descr.scope(&*self.db);
219 // First try to resolve the symbol locally 216 // First try to resolve the symbol locally
@@ -260,11 +257,11 @@ impl AnalysisImpl {
260 Ok(vec![]) 257 Ok(vec![])
261 } 258 }
262 259
263 pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { 260 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
264 let file = self.db.source_file(position.file_id); 261 let file = self.db.source_file(position.file_id);
265 // Find the binding associated with the offset 262 // Find the binding associated with the offset
266 let (binding, descr) = match find_binding(&self.db, &file, position) { 263 let (binding, descr) = match find_binding(&self.db, &file, position)? {
267 None => return Vec::new(), 264 None => return Ok(Vec::new()),
268 Some(it) => it, 265 Some(it) => it,
269 }; 266 };
270 267
@@ -277,25 +274,36 @@ impl AnalysisImpl {
277 .map(|ref_desc| (position.file_id, ref_desc.range)), 274 .map(|ref_desc| (position.file_id, ref_desc.range)),
278 ); 275 );
279 276
280 return ret; 277 return Ok(ret);
281 278
282 fn find_binding<'a>( 279 fn find_binding<'a>(
283 db: &db::RootDatabase, 280 db: &db::RootDatabase,
284 source_file: &'a SourceFileNode, 281 source_file: &'a SourceFileNode,
285 position: FilePosition, 282 position: FilePosition,
286 ) -> Option<(ast::BindPat<'a>, hir::Function)> { 283 ) -> Cancelable<Option<(ast::BindPat<'a>, hir::Function)>> {
287 let syntax = source_file.syntax(); 284 let syntax = source_file.syntax();
288 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) { 285 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
289 let descr = hir::Function::guess_for_bind_pat(db, position.file_id, binding)?; 286 let descr = ctry!(hir::Function::guess_for_bind_pat(
290 return Some((binding, descr)); 287 db,
288 position.file_id,
289 binding
290 )?);
291 return Ok(Some((binding, descr)));
291 }; 292 };
292 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?; 293 let name_ref = ctry!(find_node_at_offset::<ast::NameRef>(syntax, position.offset));
293 let descr = hir::Function::guess_for_name_ref(db, position.file_id, name_ref)?; 294 let descr = ctry!(hir::Function::guess_for_name_ref(
295 db,
296 position.file_id,
297 name_ref
298 )?);
294 let scope = descr.scope(db); 299 let scope = descr.scope(db);
295 let resolved = scope.resolve_local_name(name_ref)?; 300 let resolved = ctry!(scope.resolve_local_name(name_ref));
296 let resolved = resolved.ptr().resolve(source_file); 301 let resolved = resolved.ptr().resolve(source_file);
297 let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?; 302 let binding = ctry!(find_node_at_offset::<ast::BindPat>(
298 Some((binding, descr)) 303 syntax,
304 resolved.range().end()
305 ));
306 Ok(Some((binding, descr)))
299 } 307 }
300 } 308 }
301 309
@@ -411,7 +419,9 @@ impl AnalysisImpl {
411 if fs.kind == FN_DEF { 419 if fs.kind == FN_DEF {
412 let fn_file = self.db.source_file(fn_file_id); 420 let fn_file = self.db.source_file(fn_file_id);
413 if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) { 421 if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) {
414 let descr = hir::Function::guess_from_source(&*self.db, fn_file_id, fn_def); 422 let descr = ctry!(hir::Function::guess_from_source(
423 &*self.db, fn_file_id, fn_def
424 )?);
415 if let Some(descriptor) = descr.signature_info(&*self.db) { 425 if let Some(descriptor) = descr.signature_info(&*self.db) {
416 // If we have a calling expression let's find which argument we are on 426 // If we have a calling expression let's find which argument we are on
417 let mut current_parameter = None; 427 let mut current_parameter = None;
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 12df580ba..90528edfd 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -248,7 +248,7 @@ impl Analysis {
248 self.imp.approximately_resolve_symbol(position) 248 self.imp.approximately_resolve_symbol(position)
249 } 249 }
250 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { 250 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
251 Ok(self.imp.find_all_refs(position)) 251 self.imp.find_all_refs(position)
252 } 252 }
253 pub fn doc_comment_for( 253 pub fn doc_comment_for(
254 &self, 254 &self,
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 2f01bae6d..ff41fd326 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -7,10 +7,11 @@ use ra_syntax::{
7use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable}; 7use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable};
8 8
9use crate::{ 9use crate::{
10 DefLoc, DefId, FnId, 10 DefLoc, DefId,
11 SourceFileItems, SourceItemId, 11 SourceFileItems, SourceItemId,
12 query_definitions, 12 query_definitions,
13 FnScopes, 13 FnScopes,
14 function::FnId,
14 module::{ModuleId, ModuleTree, ModuleSource, 15 module::{ModuleId, ModuleTree, ModuleSource,
15 nameres::{ItemMap, InputModuleItems}}, 16 nameres::{ItemMap, InputModuleItems}},
16}; 17};
@@ -19,7 +20,6 @@ salsa::query_group! {
19 20
20pub trait HirDatabase: SyntaxDatabase 21pub trait HirDatabase: SyntaxDatabase
21 + AsRef<LocationIntener<DefLoc, DefId>> 22 + AsRef<LocationIntener<DefLoc, DefId>>
22 + AsRef<LocationIntener<SourceItemId, FnId>>
23{ 23{
24 fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> { 24 fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
25 type FnScopesQuery; 25 type FnScopesQuery;
diff --git a/crates/ra_hir/src/function/mod.rs b/crates/ra_hir/src/function/mod.rs
index c8af2e54f..e00bca6e3 100644
--- a/crates/ra_hir/src/function/mod.rs
+++ b/crates/ra_hir/src/function/mod.rs
@@ -12,39 +12,49 @@ use ra_syntax::{
12use ra_db::FileId; 12use ra_db::FileId;
13 13
14use crate::{ 14use crate::{
15 FnId, HirDatabase, SourceItemId, 15 Cancelable,
16 DefLoc, DefKind, DefId, HirDatabase, SourceItemId,
17 Module,
16}; 18};
17 19
18pub use self::scope::FnScopes; 20pub use self::scope::FnScopes;
19 21
20impl FnId { 22#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
21 pub fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId { 23pub struct FnId(pub(crate) DefId);
22 let file_items = db.file_items(file_id);
23 let item_id = file_items.id_of(fn_def.syntax());
24 let item_id = SourceItemId { file_id, item_id };
25 FnId::from_loc(db, &item_id)
26 }
27}
28 24
29pub struct Function { 25pub struct Function {
30 fn_id: FnId, 26 fn_id: FnId,
31} 27}
32 28
33impl Function { 29impl Function {
30 pub(crate) fn new(def_id: DefId) -> Function {
31 let fn_id = FnId(def_id);
32 Function { fn_id }
33 }
34
34 pub fn guess_from_source( 35 pub fn guess_from_source(
35 db: &impl HirDatabase, 36 db: &impl HirDatabase,
36 file_id: FileId, 37 file_id: FileId,
37 fn_def: ast::FnDef, 38 fn_def: ast::FnDef,
38 ) -> Function { 39 ) -> Cancelable<Option<Function>> {
39 let fn_id = FnId::get(db, file_id, fn_def); 40 let module = ctry!(Module::guess_from_child_node(db, file_id, fn_def.syntax())?);
40 Function { fn_id } 41 let file_items = db.file_items(file_id);
42 let item_id = file_items.id_of(fn_def.syntax());
43 let source_item_id = SourceItemId { file_id, item_id };
44 let def_loc = DefLoc {
45 kind: DefKind::Function,
46 source_root_id: module.source_root_id,
47 module_id: module.module_id,
48 source_item_id,
49 };
50 Ok(Some(Function::new(def_loc.id(db))))
41 } 51 }
42 52
43 pub fn guess_for_name_ref( 53 pub fn guess_for_name_ref(
44 db: &impl HirDatabase, 54 db: &impl HirDatabase,
45 file_id: FileId, 55 file_id: FileId,
46 name_ref: ast::NameRef, 56 name_ref: ast::NameRef,
47 ) -> Option<Function> { 57 ) -> Cancelable<Option<Function>> {
48 Function::guess_for_node(db, file_id, name_ref.syntax()) 58 Function::guess_for_node(db, file_id, name_ref.syntax())
49 } 59 }
50 60
@@ -52,7 +62,7 @@ impl Function {
52 db: &impl HirDatabase, 62 db: &impl HirDatabase,
53 file_id: FileId, 63 file_id: FileId,
54 bind_pat: ast::BindPat, 64 bind_pat: ast::BindPat,
55 ) -> Option<Function> { 65 ) -> Cancelable<Option<Function>> {
56 Function::guess_for_node(db, file_id, bind_pat.syntax()) 66 Function::guess_for_node(db, file_id, bind_pat.syntax())
57 } 67 }
58 68
@@ -60,10 +70,9 @@ impl Function {
60 db: &impl HirDatabase, 70 db: &impl HirDatabase,
61 file_id: FileId, 71 file_id: FileId,
62 node: SyntaxNodeRef, 72 node: SyntaxNodeRef,
63 ) -> Option<Function> { 73 ) -> Cancelable<Option<Function>> {
64 let fn_def = node.ancestors().find_map(ast::FnDef::cast)?; 74 let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast));
65 let res = Function::guess_from_source(db, file_id, fn_def); 75 Function::guess_from_source(db, file_id, fn_def)
66 Some(res)
67 } 76 }
68 77
69 pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> { 78 pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index e7b6a81f4..9168dad3b 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -41,63 +41,58 @@ pub use self::{
41 41
42pub use self::function::FnSignatureInfo; 42pub use self::function::FnSignatureInfo;
43 43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 44/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
45pub struct FnId(u32); 45/// in a specific module.
46ra_db::impl_numeric_id!(FnId);
47
48impl FnId {
49 pub fn from_loc(
50 db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
51 loc: &SourceItemId,
52 ) -> FnId {
53 db.as_ref().loc2id(loc)
54 }
55 pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
56 db.as_ref().id2loc(self)
57 }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61pub struct DefId(u32); 47pub struct DefId(u32);
62ra_db::impl_numeric_id!(DefId); 48ra_db::impl_numeric_id!(DefId);
63 49
50#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
51pub(crate) enum DefKind {
52 Module,
53 Function,
54 Item,
55}
56
64#[derive(Clone, Debug, PartialEq, Eq, Hash)] 57#[derive(Clone, Debug, PartialEq, Eq, Hash)]
65pub enum DefLoc { 58pub struct DefLoc {
66 Module { 59 pub(crate) kind: DefKind,
67 id: ModuleId, 60 source_root_id: SourceRootId,
68 source_root: SourceRootId, 61 module_id: ModuleId,
69 }, 62 source_item_id: SourceItemId,
70 Item {
71 source_item_id: SourceItemId,
72 },
73} 63}
74 64
75impl DefId { 65impl DefId {
76 pub fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc { 66 pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
77 db.as_ref().id2loc(self) 67 db.as_ref().id2loc(self)
78 } 68 }
79} 69}
80 70
81impl DefLoc { 71impl DefLoc {
82 pub fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId { 72 pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
83 db.as_ref().loc2id(&self) 73 db.as_ref().loc2id(&self)
84 } 74 }
85} 75}
86 76
87pub enum Def { 77pub enum Def {
88 Module(Module), 78 Module(Module),
79 Function(Function),
89 Item, 80 Item,
90} 81}
91 82
92impl DefId { 83impl DefId {
93 pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> { 84 pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
94 let loc = self.loc(db); 85 let loc = self.loc(db);
95 let res = match loc { 86 let res = match loc.kind {
96 DefLoc::Module { id, source_root } => { 87 DefKind::Module => {
97 let descr = Module::new(db, source_root, id)?; 88 let module = Module::new(db, loc.source_root_id, loc.module_id)?;
98 Def::Module(descr) 89 Def::Module(module)
99 } 90 }
100 DefLoc::Item { .. } => Def::Item, 91 DefKind::Function => {
92 let function = Function::new(self);
93 Def::Function(function)
94 }
95 DefKind::Item => Def::Item,
101 }; 96 };
102 Ok(res) 97 Ok(res)
103 } 98 }
@@ -131,6 +126,10 @@ impl SourceFileItems {
131 .unwrap(); 126 .unwrap();
132 id 127 id
133 } 128 }
129 pub fn id_of_source_file(&self) -> SourceFileItemId {
130 let (id, _syntax) = self.arena.iter().next().unwrap();
131 id
132 }
134} 133}
135 134
136impl Index<SourceFileItemId> for SourceFileItems { 135impl Index<SourceFileItemId> for SourceFileItems {
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 8e256b89f..e855df11d 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -6,7 +6,7 @@ use ra_db::{LocationIntener, BaseDatabase, FilePosition, mock::FileMap, FileId,
6use relative_path::RelativePathBuf; 6use relative_path::RelativePathBuf;
7use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; 7use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
8 8
9use crate::{db, DefId, DefLoc, FnId, SourceItemId}; 9use crate::{db, DefId, DefLoc};
10 10
11#[derive(Debug)] 11#[derive(Debug)]
12pub(crate) struct MockDatabase { 12pub(crate) struct MockDatabase {
@@ -65,7 +65,6 @@ impl MockDatabase {
65 65
66#[derive(Debug, Default)] 66#[derive(Debug, Default)]
67struct IdMaps { 67struct IdMaps {
68 fns: LocationIntener<SourceItemId, FnId>,
69 defs: LocationIntener<DefLoc, DefId>, 68 defs: LocationIntener<DefLoc, DefId>,
70} 69}
71 70
@@ -117,12 +116,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for MockDatabase {
117 } 116 }
118} 117}
119 118
120impl AsRef<LocationIntener<SourceItemId, FnId>> for MockDatabase {
121 fn as_ref(&self) -> &LocationIntener<SourceItemId, FnId> {
122 &self.id_maps.fns
123 }
124}
125
126impl MockDatabase { 119impl MockDatabase {
127 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> { 120 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
128 *self.events.lock() = Some(Vec::new()); 121 *self.events.lock() = Some(Vec::new());
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 {
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index 6f602878c..e4d721601 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -11,21 +11,21 @@ use ra_syntax::{
11use ra_db::{SourceRootId, FileId, Cancelable,}; 11use ra_db::{SourceRootId, FileId, Cancelable,};
12 12
13use crate::{ 13use crate::{
14 FnId, 14 SourceFileItems, SourceItemId, DefKind,
15 SourceFileItems, SourceItemId, 15 db::HirDatabase,
16 db::HirDatabase, 16 function::{FnScopes, FnId},
17 function::FnScopes, 17 module::{
18 module::{ 18 ModuleSource, ModuleSourceNode, ModuleId,
19 ModuleSource, ModuleSourceNode, ModuleId, 19 imp::Submodule,
20 imp::Submodule, 20 nameres::{InputModuleItems, ItemMap, Resolver},
21 nameres::{InputModuleItems, ItemMap, Resolver}, 21 },
22 },
23}; 22};
24 23
25/// Resolve `FnId` to the corresponding `SyntaxNode` 24/// Resolve `FnId` to the corresponding `SyntaxNode`
26pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode { 25pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode {
27 let item_id = fn_id.loc(db); 26 let def_loc = fn_id.0.loc(db);
28 let syntax = db.file_item(item_id); 27 assert!(def_loc.kind == DefKind::Function);
28 let syntax = db.file_item(def_loc.source_item_id);
29 FnDef::cast(syntax.borrowed()).unwrap().owned() 29 FnDef::cast(syntax.borrowed()).unwrap().owned()
30} 30}
31 31
@@ -36,9 +36,10 @@ pub(super) fn fn_scopes(db: &impl HirDatabase, fn_id: FnId) -> Arc<FnScopes> {
36} 36}
37 37
38pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { 38pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> {
39 let mut res = SourceFileItems::default();
39 let source_file = db.source_file(file_id); 40 let source_file = db.source_file(file_id);
41 res.alloc(source_file.syntax().owned());
40 let source_file = source_file.borrowed(); 42 let source_file = source_file.borrowed();
41 let mut res = SourceFileItems::default();
42 source_file 43 source_file
43 .syntax() 44 .syntax()
44 .descendants() 45 .descendants()