diff options
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 80 |
1 files changed, 52 insertions, 28 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 85bd84469..4c14650c0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -13,14 +13,16 @@ use ra_syntax::{ | |||
13 | }; | 13 | }; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | HirDatabase, Module, Function, SourceItemId, | 16 | HirDatabase, Function, SourceItemId, |
17 | module::ModuleSource, | 17 | DefKind, DefLoc, AsName, Module, |
18 | DefKind, DefLoc, AsName, | ||
19 | }; | 18 | }; |
20 | 19 | ||
21 | /// Locates the module by `FileId`. Picks topmost module in the file. | 20 | /// Locates the module by `FileId`. Picks topmost module in the file. |
22 | pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> { | 21 | pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> { |
23 | 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 | }; | ||
24 | module_from_source(db, module_source) | 26 | module_from_source(db, module_source) |
25 | } | 27 | } |
26 | 28 | ||
@@ -34,7 +36,7 @@ pub fn module_from_declaration( | |||
34 | let child_name = decl.name(); | 36 | let child_name = decl.name(); |
35 | match (parent_module, child_name) { | 37 | match (parent_module, child_name) { |
36 | (Some(parent_module), Some(child_name)) => { | 38 | (Some(parent_module), Some(child_name)) => { |
37 | if let Some(child) = parent_module.child(&child_name.as_name()) { | 39 | if let Some(child) = parent_module.child(db, &child_name.as_name())? { |
38 | return Ok(Some(child)); | 40 | return Ok(Some(child)); |
39 | } | 41 | } |
40 | } | 42 | } |
@@ -49,11 +51,26 @@ pub fn module_from_position( | |||
49 | position: FilePosition, | 51 | position: FilePosition, |
50 | ) -> Cancelable<Option<Module>> { | 52 | ) -> Cancelable<Option<Module>> { |
51 | let file = db.source_file(position.file_id); | 53 | let file = db.source_file(position.file_id); |
52 | 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) { |
53 | 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), |
54 | _ => ModuleSource::new_file(position.file_id.into()), | 56 | _ => module_from_file_id(db, position.file_id.into()), |
57 | } | ||
58 | } | ||
59 | |||
60 | fn 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), | ||
55 | }; | 72 | }; |
56 | module_from_source(db, module_source) | 73 | module_from_source(db, source) |
57 | } | 74 | } |
58 | 75 | ||
59 | /// Locates the module by child syntax element within the module | 76 | /// Locates the module by child syntax element within the module |
@@ -62,29 +79,34 @@ pub fn module_from_child_node( | |||
62 | file_id: FileId, | 79 | file_id: FileId, |
63 | child: SyntaxNodeRef, | 80 | child: SyntaxNodeRef, |
64 | ) -> Cancelable<Option<Module>> { | 81 | ) -> Cancelable<Option<Module>> { |
65 | let module_source = if let Some(m) = child | 82 | if let Some(m) = child |
66 | .ancestors() | 83 | .ancestors() |
67 | .filter_map(ast::Module::cast) | 84 | .filter_map(ast::Module::cast) |
68 | .find(|it| !it.has_semi()) | 85 | .find(|it| !it.has_semi()) |
69 | { | 86 | { |
70 | ModuleSource::new_inline(db, file_id.into(), m) | 87 | module_from_inline(db, file_id.into(), m) |
71 | } else { | 88 | } else { |
72 | ModuleSource::new_file(file_id.into()) | 89 | module_from_file_id(db, file_id.into()) |
73 | }; | 90 | } |
74 | module_from_source(db, module_source) | ||
75 | } | 91 | } |
76 | 92 | ||
77 | fn module_from_source( | 93 | fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Cancelable<Option<Module>> { |
78 | db: &impl HirDatabase, | 94 | let source_root_id = db.file_source_root(source.file_id.as_original_file()); |
79 | module_source: ModuleSource, | ||
80 | ) -> Cancelable<Option<Module>> { | ||
81 | let source_root_id = db.file_source_root(module_source.file_id().as_original_file()); | ||
82 | let module_tree = db.module_tree(source_root_id)?; | 95 | let module_tree = db.module_tree(source_root_id)?; |
83 | let m = module_tree | 96 | let module_id = ctry!(module_tree.find_module_by_source(source)); |
84 | .modules_with_sources() | 97 | Ok(Some(Module::from_module_id(db, source_root_id, module_id)?)) |
85 | .find(|(_id, src)| src == &module_source); | 98 | } |
86 | let module_id = ctry!(m).0; | 99 | |
87 | Ok(Some(Module::new(db, source_root_id, module_id)?)) | 100 | pub fn function_from_position( |
101 | db: &impl HirDatabase, | ||
102 | position: FilePosition, | ||
103 | ) -> Cancelable<Option<Function>> { | ||
104 | let file = db.source_file(position.file_id); | ||
105 | let fn_def = ctry!(find_node_at_offset::<ast::FnDef>( | ||
106 | file.syntax(), | ||
107 | position.offset | ||
108 | )); | ||
109 | function_from_source(db, position.file_id, fn_def) | ||
88 | } | 110 | } |
89 | 111 | ||
90 | pub fn function_from_source( | 112 | pub fn function_from_source( |
@@ -102,7 +124,8 @@ pub fn function_from_module( | |||
102 | module: &Module, | 124 | module: &Module, |
103 | fn_def: ast::FnDef, | 125 | fn_def: ast::FnDef, |
104 | ) -> Function { | 126 | ) -> Function { |
105 | let file_id = module.source().file_id(); | 127 | let loc = module.def_id.loc(db); |
128 | let file_id = loc.source_item_id.file_id; | ||
106 | let file_items = db.file_items(file_id); | 129 | let file_items = db.file_items(file_id); |
107 | let item_id = file_items.id_of(file_id, fn_def.syntax()); | 130 | let item_id = file_items.id_of(file_id, fn_def.syntax()); |
108 | let source_item_id = SourceItemId { | 131 | let source_item_id = SourceItemId { |
@@ -111,8 +134,8 @@ pub fn function_from_module( | |||
111 | }; | 134 | }; |
112 | let def_loc = DefLoc { | 135 | let def_loc = DefLoc { |
113 | kind: DefKind::Function, | 136 | kind: DefKind::Function, |
114 | source_root_id: module.source_root_id, | 137 | source_root_id: loc.source_root_id, |
115 | module_id: module.module_id, | 138 | module_id: loc.module_id, |
116 | source_item_id, | 139 | source_item_id, |
117 | }; | 140 | }; |
118 | Function::new(def_loc.id(db)) | 141 | Function::new(def_loc.id(db)) |
@@ -135,7 +158,8 @@ pub fn macro_symbols( | |||
135 | Some(it) => it, | 158 | Some(it) => it, |
136 | None => return Ok(Vec::new()), | 159 | None => return Ok(Vec::new()), |
137 | }; | 160 | }; |
138 | let items = db.input_module_items(module.source_root_id, module.module_id)?; | 161 | let loc = module.def_id.loc(db); |
162 | let items = db.input_module_items(loc.source_root_id, loc.module_id)?; | ||
139 | let mut res = Vec::new(); | 163 | let mut res = Vec::new(); |
140 | 164 | ||
141 | for macro_call_id in items | 165 | for macro_call_id in items |