diff options
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 44 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 213 | ||||
-rw-r--r-- | crates/ra_hir/src/path.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/query_definitions.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_scope.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide_api/src/db.rs | 3 |
9 files changed, 284 insertions, 65 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 0cf7deac9..865e5e809 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -7,7 +7,7 @@ use ra_syntax::{ast, TreeArc, SyntaxNode}; | |||
7 | use crate::{ | 7 | use crate::{ |
8 | Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, | 8 | Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, |
9 | type_ref::TypeRef, | 9 | type_ref::TypeRef, |
10 | nameres::ModuleScope, | 10 | nameres::{ModuleScope, lower::LoweredImport}, |
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | expr::BodySyntaxMapping, | 12 | expr::BodySyntaxMapping, |
13 | ty::InferenceResult, | 13 | ty::InferenceResult, |
@@ -96,6 +96,15 @@ impl Module { | |||
96 | self.declaration_source_impl(db) | 96 | self.declaration_source_impl(db) |
97 | } | 97 | } |
98 | 98 | ||
99 | /// Returns the syntax of the last path segment corresponding to this import | ||
100 | pub fn import_source( | ||
101 | &self, | ||
102 | db: &impl HirDatabase, | ||
103 | import: LoweredImport, | ||
104 | ) -> TreeArc<ast::PathSegment> { | ||
105 | self.import_source_impl(db, import) | ||
106 | } | ||
107 | |||
99 | /// Returns the crate this module is part of. | 108 | /// Returns the crate this module is part of. |
100 | pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { | 109 | pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { |
101 | self.krate_impl(db) | 110 | self.krate_impl(db) |
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index a5c032d69..f110548c6 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -5,7 +5,7 @@ use crate::{ | |||
5 | Module, ModuleSource, Problem, | 5 | Module, ModuleSource, Problem, |
6 | Crate, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, | 6 | Crate, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, |
7 | module_tree::ModuleId, | 7 | module_tree::ModuleId, |
8 | nameres::ModuleScope, | 8 | nameres::{ModuleScope, lower::LoweredImport}, |
9 | db::HirDatabase, | 9 | db::HirDatabase, |
10 | }; | 10 | }; |
11 | 11 | ||
@@ -37,7 +37,7 @@ impl Module { | |||
37 | Some(link.name(&module_tree).clone()) | 37 | Some(link.name(&module_tree).clone()) |
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { | 40 | pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { |
41 | let loc = self.def_id.loc(db); | 41 | let loc = self.def_id.loc(db); |
42 | let file_id = loc.source_item_id.file_id.as_original_file(); | 42 | let file_id = loc.source_item_id.file_id.as_original_file(); |
43 | let syntax_node = db.file_item(loc.source_item_id); | 43 | let syntax_node = db.file_item(loc.source_item_id); |
@@ -50,7 +50,7 @@ impl Module { | |||
50 | (file_id, module_source) | 50 | (file_id, module_source) |
51 | } | 51 | } |
52 | 52 | ||
53 | pub fn declaration_source_impl( | 53 | pub(crate) fn declaration_source_impl( |
54 | &self, | 54 | &self, |
55 | db: &impl HirDatabase, | 55 | db: &impl HirDatabase, |
56 | ) -> Option<(FileId, TreeArc<ast::Module>)> { | 56 | ) -> Option<(FileId, TreeArc<ast::Module>)> { |
@@ -66,6 +66,17 @@ impl Module { | |||
66 | Some((file_id, src)) | 66 | Some((file_id, src)) |
67 | } | 67 | } |
68 | 68 | ||
69 | pub(crate) fn import_source_impl( | ||
70 | &self, | ||
71 | db: &impl HirDatabase, | ||
72 | import: LoweredImport, | ||
73 | ) -> TreeArc<ast::PathSegment> { | ||
74 | let loc = self.def_id.loc(db); | ||
75 | let source_map = db.lower_module_source_map(loc.source_root_id, loc.module_id); | ||
76 | let (_, source) = self.definition_source(db); | ||
77 | source_map.get(&source, import) | ||
78 | } | ||
79 | |||
69 | pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Option<Crate> { | 80 | pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Option<Crate> { |
70 | let root = self.crate_root(db); | 81 | let root = self.crate_root(db); |
71 | let loc = root.def_id.loc(db); | 82 | let loc = root.def_id.loc(db); |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 4a3e0fed2..ccc53c454 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | FnSignature, FnScopes, | 10 | FnSignature, FnScopes, |
11 | macros::MacroExpansion, | 11 | macros::MacroExpansion, |
12 | module_tree::{ModuleId, ModuleTree}, | 12 | module_tree::{ModuleId, ModuleTree}, |
13 | nameres::{ItemMap, lower::InputModuleItems}, | 13 | nameres::{ItemMap, lower::{InputModuleItems, LoweredModule, ImportSourceMap}}, |
14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, | 14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, |
15 | adt::{StructData, EnumData, EnumVariantData}, | 15 | adt::{StructData, EnumData, EnumVariantData}, |
16 | impl_block::ModuleImplBlocks, | 16 | impl_block::ModuleImplBlocks, |
@@ -65,6 +65,27 @@ pub trait HirDatabase: | |||
65 | module_id: ModuleId, | 65 | module_id: ModuleId, |
66 | ) -> Arc<InputModuleItems>; | 66 | ) -> Arc<InputModuleItems>; |
67 | 67 | ||
68 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] | ||
69 | fn lower_module( | ||
70 | &self, | ||
71 | source_root_id: SourceRootId, | ||
72 | module_id: ModuleId, | ||
73 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>); | ||
74 | |||
75 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_module_query)] | ||
76 | fn lower_module_module( | ||
77 | &self, | ||
78 | source_root_id: SourceRootId, | ||
79 | module_id: ModuleId, | ||
80 | ) -> Arc<LoweredModule>; | ||
81 | |||
82 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)] | ||
83 | fn lower_module_source_map( | ||
84 | &self, | ||
85 | source_root_id: SourceRootId, | ||
86 | module_id: ModuleId, | ||
87 | ) -> Arc<ImportSourceMap>; | ||
88 | |||
68 | #[salsa::invoke(query_definitions::item_map)] | 89 | #[salsa::invoke(query_definitions::item_map)] |
69 | fn item_map(&self, source_root_id: SourceRootId) -> Arc<ItemMap>; | 90 | fn item_map(&self, source_root_id: SourceRootId) -> Arc<ItemMap>; |
70 | 91 | ||
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index aea95e08c..ab0a9041d 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -60,7 +60,7 @@ pub struct Resolution { | |||
60 | /// None for unresolved | 60 | /// None for unresolved |
61 | pub def_id: PerNs<DefId>, | 61 | pub def_id: PerNs<DefId>, |
62 | /// ident by whitch this is imported into local scope. | 62 | /// ident by whitch this is imported into local scope. |
63 | pub import: Option<NamedImport>, | 63 | pub import: Option<LoweredImport>, |
64 | } | 64 | } |
65 | 65 | ||
66 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | 66 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
@@ -151,10 +151,10 @@ impl<T> PerNs<T> { | |||
151 | 151 | ||
152 | pub(crate) struct Resolver<'a, DB> { | 152 | pub(crate) struct Resolver<'a, DB> { |
153 | db: &'a DB, | 153 | db: &'a DB, |
154 | input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>, | 154 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, |
155 | source_root: SourceRootId, | 155 | source_root: SourceRootId, |
156 | module_tree: Arc<ModuleTree>, | 156 | module_tree: Arc<ModuleTree>, |
157 | processed_imports: FxHashSet<(ModuleId, usize)>, | 157 | processed_imports: FxHashSet<(ModuleId, LoweredImport)>, |
158 | result: ItemMap, | 158 | result: ItemMap, |
159 | } | 159 | } |
160 | 160 | ||
@@ -164,7 +164,7 @@ where | |||
164 | { | 164 | { |
165 | pub(crate) fn new( | 165 | pub(crate) fn new( |
166 | db: &'a DB, | 166 | db: &'a DB, |
167 | input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>, | 167 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, |
168 | source_root: SourceRootId, | 168 | source_root: SourceRootId, |
169 | module_tree: Arc<ModuleTree>, | 169 | module_tree: Arc<ModuleTree>, |
170 | ) -> Resolver<'a, DB> { | 170 | ) -> Resolver<'a, DB> { |
@@ -197,7 +197,7 @@ where | |||
197 | self.result | 197 | self.result |
198 | } | 198 | } |
199 | 199 | ||
200 | fn populate_module(&mut self, module_id: ModuleId, input: Arc<InputModuleItems>) { | 200 | fn populate_module(&mut self, module_id: ModuleId, input: Arc<LoweredModule>) { |
201 | let mut module_items = ModuleScope::default(); | 201 | let mut module_items = ModuleScope::default(); |
202 | 202 | ||
203 | // Populate extern crates prelude | 203 | // Populate extern crates prelude |
@@ -220,14 +220,14 @@ where | |||
220 | } | 220 | } |
221 | }; | 221 | }; |
222 | } | 222 | } |
223 | for import in input.imports.iter() { | 223 | for (import_id, import_data) in input.imports.iter() { |
224 | if let Some(name) = import.path.segments.iter().last() { | 224 | if let Some(name) = import_data.path.segments.iter().last() { |
225 | if let ImportKind::Named(import) = import.kind { | 225 | if !import_data.is_glob { |
226 | module_items.items.insert( | 226 | module_items.items.insert( |
227 | name.clone(), | 227 | name.clone(), |
228 | Resolution { | 228 | Resolution { |
229 | def_id: PerNs::none(), | 229 | def_id: PerNs::none(), |
230 | import: Some(import), | 230 | import: Some(import_id), |
231 | }, | 231 | }, |
232 | ); | 232 | ); |
233 | } | 233 | } |
@@ -281,23 +281,27 @@ where | |||
281 | } | 281 | } |
282 | 282 | ||
283 | fn resolve_imports(&mut self, module_id: ModuleId) { | 283 | fn resolve_imports(&mut self, module_id: ModuleId) { |
284 | for (i, import) in self.input[&module_id].imports.iter().enumerate() { | 284 | for (import_id, import_data) in self.input[&module_id].imports.iter() { |
285 | if self.processed_imports.contains(&(module_id, i)) { | 285 | if self.processed_imports.contains(&(module_id, import_id)) { |
286 | // already done | 286 | // already done |
287 | continue; | 287 | continue; |
288 | } | 288 | } |
289 | if self.resolve_import(module_id, import) { | 289 | if self.resolve_import(module_id, import_id, import_data) { |
290 | log::debug!("import {:?} resolved (or definite error)", import); | 290 | log::debug!("import {:?} resolved (or definite error)", import_id); |
291 | self.processed_imports.insert((module_id, i)); | 291 | self.processed_imports.insert((module_id, import_id)); |
292 | } | 292 | } |
293 | } | 293 | } |
294 | } | 294 | } |
295 | 295 | ||
296 | fn resolve_import(&mut self, module_id: ModuleId, import: &Import) -> bool { | 296 | fn resolve_import( |
297 | &mut self, | ||
298 | module_id: ModuleId, | ||
299 | import_id: LoweredImport, | ||
300 | import: &ImportData, | ||
301 | ) -> bool { | ||
297 | log::debug!("resolving import: {:?}", import); | 302 | log::debug!("resolving import: {:?}", import); |
298 | let ptr = match import.kind { | 303 | if import.is_glob { |
299 | ImportKind::Glob => return false, | 304 | return false; |
300 | ImportKind::Named(ptr) => ptr, | ||
301 | }; | 305 | }; |
302 | 306 | ||
303 | let mut curr: ModuleId = match import.path.kind { | 307 | let mut curr: ModuleId = match import.path.kind { |
@@ -358,7 +362,7 @@ where | |||
358 | self.update(module_id, |items| { | 362 | self.update(module_id, |items| { |
359 | let res = Resolution { | 363 | let res = Resolution { |
360 | def_id, | 364 | def_id, |
361 | import: Some(ptr), | 365 | import: Some(import_id), |
362 | }; | 366 | }; |
363 | items.items.insert(name.clone(), res); | 367 | items.items.insert(name.clone(), res); |
364 | }); | 368 | }); |
@@ -394,7 +398,7 @@ where | |||
394 | self.update(module_id, |items| { | 398 | self.update(module_id, |items| { |
395 | let res = Resolution { | 399 | let res = Resolution { |
396 | def_id, | 400 | def_id, |
397 | import: Some(ptr), | 401 | import: Some(import_id), |
398 | }; | 402 | }; |
399 | items.items.insert(name.clone(), res); | 403 | items.items.insert(name.clone(), res); |
400 | }) | 404 | }) |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 35bdbafbf..6bca14444 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | TextRange, SyntaxKind, AstNode, | 4 | TextRange, SyntaxKind, AstNode, SourceFile, TreeArc, |
5 | ast::{self, ModuleItemOwner}, | 5 | ast::{self, ModuleItemOwner}, |
6 | }; | 6 | }; |
7 | use ra_db::{FileId, SourceRootId}; | 7 | use ra_db::{SourceRootId, LocalSyntaxPtr}; |
8 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | ||
8 | 9 | ||
9 | use crate::{ | 10 | use crate::{ |
10 | SourceItemId, SourceFileItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, | 11 | SourceItemId, SourceFileItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, |
@@ -139,12 +140,12 @@ impl InputModuleItems { | |||
139 | fn add_use_item(&mut self, file_items: &SourceFileItems, item: &ast::UseItem) { | 140 | fn add_use_item(&mut self, file_items: &SourceFileItems, item: &ast::UseItem) { |
140 | let file_item_id = file_items.id_of_unchecked(item.syntax()); | 141 | let file_item_id = file_items.id_of_unchecked(item.syntax()); |
141 | let start_offset = item.syntax().range().start(); | 142 | let start_offset = item.syntax().range().start(); |
142 | Path::expand_use_item(item, |path, range| { | 143 | Path::expand_use_item(item, |path, segment| { |
143 | let kind = match range { | 144 | let kind = match segment { |
144 | None => ImportKind::Glob, | 145 | None => ImportKind::Glob, |
145 | Some(range) => ImportKind::Named(NamedImport { | 146 | Some(segment) => ImportKind::Named(NamedImport { |
146 | file_item_id, | 147 | file_item_id, |
147 | relative_range: range - start_offset, | 148 | relative_range: segment.syntax().range() - start_offset, |
148 | }), | 149 | }), |
149 | }; | 150 | }; |
150 | self.imports.push(Import { kind, path }) | 151 | self.imports.push(Import { kind, path }) |
@@ -199,22 +200,194 @@ pub struct NamedImport { | |||
199 | pub relative_range: TextRange, | 200 | pub relative_range: TextRange, |
200 | } | 201 | } |
201 | 202 | ||
202 | impl NamedImport { | ||
203 | // FIXME: this is only here for one use-case in completion. Seems like a | ||
204 | // pretty gross special case. | ||
205 | pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { | ||
206 | let source_item_id = SourceItemId { | ||
207 | file_id: file_id.into(), | ||
208 | item_id: Some(self.file_item_id), | ||
209 | }; | ||
210 | let syntax = db.file_item(source_item_id); | ||
211 | let offset = syntax.range().start(); | ||
212 | self.relative_range + offset | ||
213 | } | ||
214 | } | ||
215 | |||
216 | #[derive(Debug, Clone, PartialEq, Eq)] | 203 | #[derive(Debug, Clone, PartialEq, Eq)] |
217 | pub(super) enum ImportKind { | 204 | pub(super) enum ImportKind { |
218 | Glob, | 205 | Glob, |
219 | Named(NamedImport), | 206 | Named(NamedImport), |
220 | } | 207 | } |
208 | |||
209 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
210 | pub struct LoweredImport(RawId); | ||
211 | impl_arena_id!(LoweredImport); | ||
212 | |||
213 | #[derive(Debug, PartialEq, Eq)] | ||
214 | pub(super) struct ImportData { | ||
215 | pub(super) path: Path, | ||
216 | pub(super) is_glob: bool, | ||
217 | } | ||
218 | |||
219 | #[derive(Debug, Default, PartialEq, Eq)] | ||
220 | pub struct LoweredModule { | ||
221 | pub(super) items: Vec<ModuleItem>, | ||
222 | pub(super) imports: Arena<LoweredImport, ImportData>, | ||
223 | } | ||
224 | |||
225 | #[derive(Debug, Default, PartialEq, Eq)] | ||
226 | pub struct ImportSourceMap { | ||
227 | map: ArenaMap<LoweredImport, LocalSyntaxPtr>, | ||
228 | } | ||
229 | |||
230 | impl ImportSourceMap { | ||
231 | fn insert(&mut self, import: LoweredImport, segment: &ast::PathSegment) { | ||
232 | self.map | ||
233 | .insert(import, LocalSyntaxPtr::new(segment.syntax())) | ||
234 | } | ||
235 | |||
236 | pub fn get(&self, source: &ModuleSource, import: LoweredImport) -> TreeArc<ast::PathSegment> { | ||
237 | let file = match source { | ||
238 | ModuleSource::SourceFile(file) => &*file, | ||
239 | ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), | ||
240 | }; | ||
241 | |||
242 | ast::PathSegment::cast(&self.map[import].resolve(file)) | ||
243 | .unwrap() | ||
244 | .to_owned() | ||
245 | } | ||
246 | } | ||
247 | |||
248 | impl LoweredModule { | ||
249 | pub(crate) fn lower_module_module_query( | ||
250 | db: &impl HirDatabase, | ||
251 | source_root_id: SourceRootId, | ||
252 | module_id: ModuleId, | ||
253 | ) -> Arc<LoweredModule> { | ||
254 | db.lower_module(source_root_id, module_id).0 | ||
255 | } | ||
256 | |||
257 | pub(crate) fn lower_module_source_map_query( | ||
258 | db: &impl HirDatabase, | ||
259 | source_root_id: SourceRootId, | ||
260 | module_id: ModuleId, | ||
261 | ) -> Arc<ImportSourceMap> { | ||
262 | db.lower_module(source_root_id, module_id).1 | ||
263 | } | ||
264 | |||
265 | pub(crate) fn lower_module_query( | ||
266 | db: &impl HirDatabase, | ||
267 | source_root_id: SourceRootId, | ||
268 | module_id: ModuleId, | ||
269 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { | ||
270 | let module_tree = db.module_tree(source_root_id); | ||
271 | let source = module_id.source(&module_tree); | ||
272 | let file_id = source.file_id; | ||
273 | let source = ModuleSource::from_source_item_id(db, source); | ||
274 | let mut source_map = ImportSourceMap::default(); | ||
275 | let mut res = LoweredModule::default(); | ||
276 | match source { | ||
277 | ModuleSource::SourceFile(it) => res.fill( | ||
278 | &mut source_map, | ||
279 | db, | ||
280 | source_root_id, | ||
281 | module_id, | ||
282 | file_id, | ||
283 | &mut it.items_with_macros(), | ||
284 | ), | ||
285 | ModuleSource::Module(it) => { | ||
286 | if let Some(item_list) = it.item_list() { | ||
287 | res.fill( | ||
288 | &mut source_map, | ||
289 | db, | ||
290 | source_root_id, | ||
291 | module_id, | ||
292 | file_id, | ||
293 | &mut item_list.items_with_macros(), | ||
294 | ) | ||
295 | } | ||
296 | } | ||
297 | }; | ||
298 | (Arc::new(res), Arc::new(source_map)) | ||
299 | } | ||
300 | |||
301 | fn fill( | ||
302 | &mut self, | ||
303 | source_map: &mut ImportSourceMap, | ||
304 | db: &impl HirDatabase, | ||
305 | source_root_id: SourceRootId, | ||
306 | module_id: ModuleId, | ||
307 | file_id: HirFileId, | ||
308 | items: &mut Iterator<Item = ast::ItemOrMacro>, | ||
309 | ) { | ||
310 | let file_items = db.file_items(file_id); | ||
311 | |||
312 | for item in items { | ||
313 | match item { | ||
314 | ast::ItemOrMacro::Item(it) => { | ||
315 | self.add_item(source_map, file_id, &file_items, it); | ||
316 | } | ||
317 | ast::ItemOrMacro::Macro(macro_call) => { | ||
318 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | ||
319 | let loc = MacroCallLoc { | ||
320 | source_root_id, | ||
321 | module_id, | ||
322 | source_item_id: SourceItemId { | ||
323 | file_id, | ||
324 | item_id: Some(item_id), | ||
325 | }, | ||
326 | }; | ||
327 | let id = loc.id(db); | ||
328 | let file_id = HirFileId::from(id); | ||
329 | let file_items = db.file_items(file_id); | ||
330 | //FIXME: expand recursively | ||
331 | for item in db.hir_source_file(file_id).items() { | ||
332 | self.add_item(source_map, file_id, &file_items, item); | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | fn add_item( | ||
340 | &mut self, | ||
341 | source_map: &mut ImportSourceMap, | ||
342 | file_id: HirFileId, | ||
343 | file_items: &SourceFileItems, | ||
344 | item: &ast::ModuleItem, | ||
345 | ) -> Option<()> { | ||
346 | match item.kind() { | ||
347 | ast::ModuleItemKind::StructDef(it) => { | ||
348 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
349 | } | ||
350 | ast::ModuleItemKind::EnumDef(it) => { | ||
351 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
352 | } | ||
353 | ast::ModuleItemKind::FnDef(it) => { | ||
354 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
355 | } | ||
356 | ast::ModuleItemKind::TraitDef(it) => { | ||
357 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
358 | } | ||
359 | ast::ModuleItemKind::TypeDef(it) => { | ||
360 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
361 | } | ||
362 | ast::ModuleItemKind::ImplBlock(_) => { | ||
363 | // impls don't define items | ||
364 | } | ||
365 | ast::ModuleItemKind::UseItem(it) => self.add_use_item(source_map, it), | ||
366 | ast::ModuleItemKind::ExternCrateItem(_) => { | ||
367 | // TODO | ||
368 | } | ||
369 | ast::ModuleItemKind::ConstDef(it) => { | ||
370 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
371 | } | ||
372 | ast::ModuleItemKind::StaticDef(it) => { | ||
373 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
374 | } | ||
375 | ast::ModuleItemKind::Module(it) => { | ||
376 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
377 | } | ||
378 | } | ||
379 | Some(()) | ||
380 | } | ||
381 | |||
382 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { | ||
383 | Path::expand_use_item(item, |path, segment| { | ||
384 | let import = self.imports.alloc(ImportData { | ||
385 | path, | ||
386 | is_glob: segment.is_none(), | ||
387 | }); | ||
388 | if let Some(segment) = segment { | ||
389 | source_map.insert(import, segment) | ||
390 | } | ||
391 | }) | ||
392 | } | ||
393 | } | ||
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index 370e10bb8..7b0ce3b61 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use ra_syntax::{ast, AstNode, TextRange}; | 1 | use ra_syntax::{ast, AstNode}; |
2 | 2 | ||
3 | use crate::{Name, AsName}; | 3 | use crate::{Name, AsName}; |
4 | 4 | ||
@@ -18,7 +18,10 @@ pub enum PathKind { | |||
18 | 18 | ||
19 | impl Path { | 19 | impl Path { |
20 | /// Calls `cb` with all paths, represented by this use item. | 20 | /// Calls `cb` with all paths, represented by this use item. |
21 | pub fn expand_use_item(item: &ast::UseItem, mut cb: impl FnMut(Path, Option<TextRange>)) { | 21 | pub fn expand_use_item<'a>( |
22 | item: &'a ast::UseItem, | ||
23 | mut cb: impl FnMut(Path, Option<&'a ast::PathSegment>), | ||
24 | ) { | ||
22 | if let Some(tree) = item.use_tree() { | 25 | if let Some(tree) = item.use_tree() { |
23 | expand_use_tree(None, tree, &mut cb); | 26 | expand_use_tree(None, tree, &mut cb); |
24 | } | 27 | } |
@@ -98,10 +101,10 @@ impl From<Name> for Path { | |||
98 | } | 101 | } |
99 | } | 102 | } |
100 | 103 | ||
101 | fn expand_use_tree( | 104 | fn expand_use_tree<'a>( |
102 | prefix: Option<Path>, | 105 | prefix: Option<Path>, |
103 | tree: &ast::UseTree, | 106 | tree: &'a ast::UseTree, |
104 | cb: &mut impl FnMut(Path, Option<TextRange>), | 107 | cb: &mut impl FnMut(Path, Option<&'a ast::PathSegment>), |
105 | ) { | 108 | ) { |
106 | if let Some(use_tree_list) = tree.use_tree_list() { | 109 | if let Some(use_tree_list) = tree.use_tree_list() { |
107 | let prefix = match tree.path() { | 110 | let prefix = match tree.path() { |
@@ -125,20 +128,18 @@ fn expand_use_tree( | |||
125 | if let Some(segment) = ast_path.segment() { | 128 | if let Some(segment) = ast_path.segment() { |
126 | if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { | 129 | if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { |
127 | if let Some(prefix) = prefix { | 130 | if let Some(prefix) = prefix { |
128 | cb(prefix, Some(segment.syntax().range())); | 131 | cb(prefix, Some(segment)); |
129 | return; | 132 | return; |
130 | } | 133 | } |
131 | } | 134 | } |
132 | } | 135 | } |
133 | } | 136 | } |
134 | if let Some(path) = convert_path(prefix, ast_path) { | 137 | if let Some(path) = convert_path(prefix, ast_path) { |
135 | let range = if tree.has_star() { | 138 | if tree.has_star() { |
136 | None | 139 | cb(path, None) |
137 | } else { | 140 | } else if let Some(segment) = ast_path.segment() { |
138 | let range = ast_path.segment().unwrap().syntax().range(); | 141 | cb(path, Some(segment)) |
139 | Some(range) | ||
140 | }; | 142 | }; |
141 | cb(path, range) | ||
142 | } | 143 | } |
143 | // TODO: report errors somewhere | 144 | // TODO: report errors somewhere |
144 | // We get here if we do | 145 | // We get here if we do |
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 985a02410..074153862 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -46,7 +46,7 @@ pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc< | |||
46 | let module_tree = db.module_tree(source_root); | 46 | let module_tree = db.module_tree(source_root); |
47 | let input = module_tree | 47 | let input = module_tree |
48 | .modules() | 48 | .modules() |
49 | .map(|id| (id, db.input_module_items(source_root, id))) | 49 | .map(|id| (id, db.lower_module_module(source_root, id))) |
50 | .collect::<FxHashMap<_, _>>(); | 50 | .collect::<FxHashMap<_, _>>(); |
51 | 51 | ||
52 | let resolver = Resolver::new(db, &input, source_root, module_tree); | 52 | let resolver = Resolver::new(db, &input, source_root, module_tree); |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 699680748..4276e47e8 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use rustc_hash::FxHashSet; | 1 | use rustc_hash::FxHashSet; |
2 | use ra_syntax::TextUnit; | 2 | use ra_syntax::{AstNode, TextUnit}; |
3 | 3 | ||
4 | use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}; | 4 | use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}; |
5 | 5 | ||
@@ -17,18 +17,15 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { | |||
17 | } | 17 | } |
18 | 18 | ||
19 | let module_scope = module.scope(ctx.db); | 19 | let module_scope = module.scope(ctx.db); |
20 | let (file_id, _) = module.definition_source(ctx.db); | ||
21 | module_scope | 20 | module_scope |
22 | .entries() | 21 | .entries() |
23 | .filter(|(_name, res)| { | 22 | .filter(|(_name, res)| { |
24 | // Don't expose this item | 23 | // For cases like `use self::foo<|>` don't suggest foo itself. |
25 | // FIXME: this penetrates through all kinds of abstractions, | ||
26 | // we need to figura out the way to do it less ugly. | ||
27 | match res.import { | 24 | match res.import { |
28 | None => true, | 25 | None => true, |
29 | Some(import) => { | 26 | Some(import) => { |
30 | let range = import.range(ctx.db, file_id); | 27 | let source = module.import_source(ctx.db, import); |
31 | !range.is_subrange(&ctx.leaf.range()) | 28 | !source.syntax().range().is_subrange(&ctx.leaf.range()) |
32 | } | 29 | } |
33 | } | 30 | } |
34 | }) | 31 | }) |
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index 36778b955..a1d3333b2 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs | |||
@@ -114,6 +114,9 @@ salsa::database_storage! { | |||
114 | fn file_items() for hir::db::FileItemsQuery; | 114 | fn file_items() for hir::db::FileItemsQuery; |
115 | fn file_item() for hir::db::FileItemQuery; | 115 | fn file_item() for hir::db::FileItemQuery; |
116 | fn input_module_items() for hir::db::InputModuleItemsQuery; | 116 | fn input_module_items() for hir::db::InputModuleItemsQuery; |
117 | fn lower_module() for hir::db::LowerModuleQuery; | ||
118 | fn lower_module_module() for hir::db::LowerModuleModuleQuery; | ||
119 | fn lower_module_source_map() for hir::db::LowerModuleSourceMapQuery; | ||
117 | fn item_map() for hir::db::ItemMapQuery; | 120 | fn item_map() for hir::db::ItemMapQuery; |
118 | fn submodules() for hir::db::SubmodulesQuery; | 121 | fn submodules() for hir::db::SubmodulesQuery; |
119 | fn infer() for hir::db::InferQuery; | 122 | fn infer() for hir::db::InferQuery; |