diff options
Diffstat (limited to 'crates/ra_analysis')
-rw-r--r-- | crates/ra_analysis/src/completion/mod.rs | 10 | ||||
-rw-r--r-- | crates/ra_analysis/src/completion/reference_completion.rs | 26 | ||||
-rw-r--r-- | crates/ra_analysis/src/db.rs | 3 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/mod.rs | 6 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/imp.rs | 21 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/mod.rs | 9 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/nameres.rs | 60 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/scope.rs | 124 | ||||
-rw-r--r-- | crates/ra_analysis/tests/tests.rs | 8 |
9 files changed, 69 insertions, 198 deletions
diff --git a/crates/ra_analysis/src/completion/mod.rs b/crates/ra_analysis/src/completion/mod.rs index 5e3ee79dd..a8a752fc7 100644 --- a/crates/ra_analysis/src/completion/mod.rs +++ b/crates/ra_analysis/src/completion/mod.rs | |||
@@ -204,9 +204,9 @@ mod tests { | |||
204 | <|> | 204 | <|> |
205 | } | 205 | } |
206 | ", | 206 | ", |
207 | r#"[CompletionItem { label: "Foo", lookup: None, snippet: None }, | 207 | r#"[CompletionItem { label: "quux", lookup: None, snippet: None }, |
208 | CompletionItem { label: "Baz", lookup: None, snippet: None }, | 208 | CompletionItem { label: "Foo", lookup: None, snippet: None }, |
209 | CompletionItem { label: "quux", lookup: None, snippet: None }]"#, | 209 | CompletionItem { label: "Baz", lookup: None, snippet: None }]"#, |
210 | ); | 210 | ); |
211 | } | 211 | } |
212 | 212 | ||
@@ -230,8 +230,8 @@ mod tests { | |||
230 | fn quux() { <|> } | 230 | fn quux() { <|> } |
231 | } | 231 | } |
232 | ", | 232 | ", |
233 | r#"[CompletionItem { label: "Bar", lookup: None, snippet: None }, | 233 | r#"[CompletionItem { label: "quux", lookup: None, snippet: None }, |
234 | CompletionItem { label: "quux", lookup: None, snippet: None }]"#, | 234 | CompletionItem { label: "Bar", lookup: None, snippet: None }]"#, |
235 | ); | 235 | ); |
236 | } | 236 | } |
237 | 237 | ||
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs index c94d9af75..84383b547 100644 --- a/crates/ra_analysis/src/completion/reference_completion.rs +++ b/crates/ra_analysis/src/completion/reference_completion.rs | |||
@@ -39,14 +39,17 @@ pub(super) fn completions( | |||
39 | let module_scope = module.scope(db)?; | 39 | let module_scope = module.scope(db)?; |
40 | acc.extend( | 40 | acc.extend( |
41 | module_scope | 41 | module_scope |
42 | .entries() | 42 | .items |
43 | .iter() | 43 | .iter() |
44 | .filter(|entry| { | 44 | .filter(|(_name, res)| { |
45 | // Don't expose this item | 45 | // Don't expose this item |
46 | !entry.ptr().range().is_subrange(&name_ref.syntax().range()) | 46 | match res.import_name { |
47 | None => true, | ||
48 | Some(ptr) => !ptr.range().is_subrange(&name_ref.syntax().range()), | ||
49 | } | ||
47 | }) | 50 | }) |
48 | .map(|entry| CompletionItem { | 51 | .map(|(name, _res)| CompletionItem { |
49 | label: entry.name().to_string(), | 52 | label: name.to_string(), |
50 | lookup: None, | 53 | lookup: None, |
51 | snippet: None, | 54 | snippet: None, |
52 | }), | 55 | }), |
@@ -173,11 +176,14 @@ fn complete_path( | |||
173 | Some(it) => it, | 176 | Some(it) => it, |
174 | }; | 177 | }; |
175 | let module_scope = target_module.scope(db)?; | 178 | let module_scope = target_module.scope(db)?; |
176 | let completions = module_scope.entries().iter().map(|entry| CompletionItem { | 179 | let completions = module_scope |
177 | label: entry.name().to_string(), | 180 | .items |
178 | lookup: None, | 181 | .iter() |
179 | snippet: None, | 182 | .map(|(name, _res)| CompletionItem { |
180 | }); | 183 | label: name.to_string(), |
184 | lookup: None, | ||
185 | snippet: None, | ||
186 | }); | ||
181 | acc.extend(completions); | 187 | acc.extend(completions); |
182 | Ok(()) | 188 | Ok(()) |
183 | } | 189 | } |
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index 9a5cd4b24..887d687ea 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -7,7 +7,7 @@ use salsa::{self, Database}; | |||
7 | use crate::{ | 7 | use crate::{ |
8 | db, | 8 | db, |
9 | descriptors::{ | 9 | descriptors::{ |
10 | DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, | 10 | DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleTreeQuery, |
11 | SubmodulesQuery, ItemMapQuery, InputModuleItemsQuery, | 11 | SubmodulesQuery, ItemMapQuery, InputModuleItemsQuery, |
12 | }, | 12 | }, |
13 | symbol_index::SymbolIndex, | 13 | symbol_index::SymbolIndex, |
@@ -88,7 +88,6 @@ salsa::database_storage! { | |||
88 | fn fn_scopes() for FnScopesQuery; | 88 | fn fn_scopes() for FnScopesQuery; |
89 | fn _input_module_items() for InputModuleItemsQuery; | 89 | fn _input_module_items() for InputModuleItemsQuery; |
90 | fn _item_map() for ItemMapQuery; | 90 | fn _item_map() for ItemMapQuery; |
91 | fn _module_scope() for ModuleScopeQuery; | ||
92 | fn _fn_syntax() for FnSyntaxQuery; | 91 | fn _fn_syntax() for FnSyntaxQuery; |
93 | fn _submodules() for SubmodulesQuery; | 92 | fn _submodules() for SubmodulesQuery; |
94 | } | 93 | } |
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs index a32042b84..6b56d92e1 100644 --- a/crates/ra_analysis/src/descriptors/mod.rs +++ b/crates/ra_analysis/src/descriptors/mod.rs | |||
@@ -11,7 +11,7 @@ use ra_syntax::{ | |||
11 | use crate::{ | 11 | use crate::{ |
12 | db::SyntaxDatabase, | 12 | db::SyntaxDatabase, |
13 | descriptors::function::{resolve_local_name, FnId, FnScopes}, | 13 | descriptors::function::{resolve_local_name, FnId, FnScopes}, |
14 | descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}}, | 14 | descriptors::module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}}, |
15 | input::SourceRootId, | 15 | input::SourceRootId, |
16 | loc2id::IdDatabase, | 16 | loc2id::IdDatabase, |
17 | syntax_ptr::LocalSyntaxPtr, | 17 | syntax_ptr::LocalSyntaxPtr, |
@@ -37,10 +37,6 @@ salsa::query_group! { | |||
37 | type ModuleTreeQuery; | 37 | type ModuleTreeQuery; |
38 | use fn module::imp::module_tree; | 38 | use fn module::imp::module_tree; |
39 | } | 39 | } |
40 | fn _module_scope(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<ModuleScope>> { | ||
41 | type ModuleScopeQuery; | ||
42 | use fn module::imp::module_scope; | ||
43 | } | ||
44 | fn _fn_syntax(fn_id: FnId) -> FnDefNode { | 40 | fn _fn_syntax(fn_id: FnId) -> FnDefNode { |
45 | type FnSyntaxQuery; | 41 | type FnSyntaxQuery; |
46 | // Don't retain syntax trees in memory | 42 | // Don't retain syntax trees in memory |
diff --git a/crates/ra_analysis/src/descriptors/module/imp.rs b/crates/ra_analysis/src/descriptors/module/imp.rs index defe87216..d4dce861f 100644 --- a/crates/ra_analysis/src/descriptors/module/imp.rs +++ b/crates/ra_analysis/src/descriptors/module/imp.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | ast::{self, ModuleItemOwner, NameOwner}, | 4 | ast::{self, NameOwner}, |
5 | SmolStr, | 5 | SmolStr, |
6 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | 7 | use relative_path::RelativePathBuf; |
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | }; | 15 | }; |
16 | 16 | ||
17 | use super::{ | 17 | use super::{ |
18 | LinkData, LinkId, ModuleData, ModuleId, ModuleScope, ModuleSource, ModuleSourceNode, | 18 | LinkData, LinkId, ModuleData, ModuleId, ModuleSource, ModuleSourceNode, |
19 | ModuleTree, Problem, | 19 | ModuleTree, Problem, |
20 | }; | 20 | }; |
21 | 21 | ||
@@ -81,23 +81,6 @@ pub(crate) fn modules<'a>( | |||
81 | }) | 81 | }) |
82 | } | 82 | } |
83 | 83 | ||
84 | pub(crate) fn module_scope( | ||
85 | db: &impl DescriptorDatabase, | ||
86 | source_root_id: SourceRootId, | ||
87 | module_id: ModuleId, | ||
88 | ) -> Cancelable<Arc<ModuleScope>> { | ||
89 | let tree = db._module_tree(source_root_id)?; | ||
90 | let source = module_id.source(&tree).resolve(db); | ||
91 | let res = match source { | ||
92 | ModuleSourceNode::SourceFile(it) => ModuleScope::new(it.borrowed().items()), | ||
93 | ModuleSourceNode::Module(it) => match it.borrowed().item_list() { | ||
94 | Some(items) => ModuleScope::new(items.items()), | ||
95 | None => ModuleScope::new(std::iter::empty()), | ||
96 | }, | ||
97 | }; | ||
98 | Ok(Arc::new(res)) | ||
99 | } | ||
100 | |||
101 | pub(crate) fn module_tree( | 84 | pub(crate) fn module_tree( |
102 | db: &impl DescriptorDatabase, | 85 | db: &impl DescriptorDatabase, |
103 | source_root: SourceRootId, | 86 | source_root: SourceRootId, |
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index 95d9bcc27..cfdffcdbc 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs | |||
@@ -1,5 +1,4 @@ | |||
1 | pub(super) mod imp; | 1 | pub(super) mod imp; |
2 | mod scope; | ||
3 | pub(super) mod nameres; | 2 | pub(super) mod nameres; |
4 | 3 | ||
5 | use std::sync::Arc; | 4 | use std::sync::Arc; |
@@ -19,7 +18,7 @@ use crate::{ | |||
19 | input::SourceRootId | 18 | input::SourceRootId |
20 | }; | 19 | }; |
21 | 20 | ||
22 | pub(crate) use self::scope::ModuleScope; | 21 | pub(crate) use self::{nameres::ModuleScope}; |
23 | 22 | ||
24 | /// `ModuleDescriptor` is API entry point to get all the information | 23 | /// `ModuleDescriptor` is API entry point to get all the information |
25 | /// about a particular module. | 24 | /// about a particular module. |
@@ -126,8 +125,10 @@ impl ModuleDescriptor { | |||
126 | } | 125 | } |
127 | 126 | ||
128 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 127 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
129 | pub fn scope(&self, db: &impl DescriptorDatabase) -> Cancelable<Arc<ModuleScope>> { | 128 | pub(crate) fn scope(&self, db: &impl DescriptorDatabase) -> Cancelable<ModuleScope> { |
130 | db._module_scope(self.source_root_id, self.module_id) | 129 | let item_map = db._item_map(self.source_root_id)?; |
130 | let res = item_map.per_module[&self.module_id].clone(); | ||
131 | Ok(res) | ||
131 | } | 132 | } |
132 | 133 | ||
133 | pub fn problems(&self, db: &impl DescriptorDatabase) -> Vec<(SyntaxNode, Problem)> { | 134 | pub fn problems(&self, db: &impl DescriptorDatabase) -> Vec<(SyntaxNode, Problem)> { |
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 34127e78f..c5bf467ca 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs | |||
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; | |||
8 | 8 | ||
9 | use ra_syntax::{ | 9 | use ra_syntax::{ |
10 | SmolStr, SyntaxKind::{self, *}, | 10 | SmolStr, SyntaxKind::{self, *}, |
11 | ast::{self, NameOwner, AstNode, ModuleItemOwner} | 11 | ast::{self, AstNode, ModuleItemOwner} |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
@@ -26,13 +26,13 @@ use crate::{ | |||
26 | /// module, the set of visible items. | 26 | /// module, the set of visible items. |
27 | #[derive(Default, Debug, PartialEq, Eq)] | 27 | #[derive(Default, Debug, PartialEq, Eq)] |
28 | pub(crate) struct ItemMap { | 28 | pub(crate) struct ItemMap { |
29 | per_module: FxHashMap<ModuleId, ModuleItems>, | 29 | pub(crate) per_module: FxHashMap<ModuleId, ModuleScope>, |
30 | } | 30 | } |
31 | 31 | ||
32 | #[derive(Debug, Default, PartialEq, Eq)] | 32 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
33 | struct ModuleItems { | 33 | pub(crate) struct ModuleScope { |
34 | items: FxHashMap<SmolStr, Resolution>, | 34 | pub(crate) items: FxHashMap<SmolStr, Resolution>, |
35 | import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>, | 35 | pub(crate) import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>, |
36 | } | 36 | } |
37 | 37 | ||
38 | /// A set of items and imports declared inside a module, without relation to | 38 | /// A set of items and imports declared inside a module, without relation to |
@@ -117,22 +117,25 @@ pub(crate) fn item_map( | |||
117 | /// Resolution is basically `DefId` atm, but it should account for stuff like | 117 | /// Resolution is basically `DefId` atm, but it should account for stuff like |
118 | /// multiple namespaces, ambiguity and errors. | 118 | /// multiple namespaces, ambiguity and errors. |
119 | #[derive(Debug, Clone, PartialEq, Eq)] | 119 | #[derive(Debug, Clone, PartialEq, Eq)] |
120 | struct Resolution { | 120 | pub(crate) struct Resolution { |
121 | /// None for unresolved | 121 | /// None for unresolved |
122 | def_id: Option<DefId>, | 122 | pub(crate) def_id: Option<DefId>, |
123 | /// ident by whitch this is imported into local scope. | ||
124 | /// TODO: make this offset-independent. | ||
125 | pub(crate) import_name: Option<LocalSyntaxPtr>, | ||
123 | } | 126 | } |
124 | 127 | ||
125 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | 128 | // #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
126 | enum Namespace { | 129 | // enum Namespace { |
127 | Types, | 130 | // Types, |
128 | Values, | 131 | // Values, |
129 | } | 132 | // } |
130 | 133 | ||
131 | #[derive(Debug)] | 134 | // #[derive(Debug)] |
132 | struct PerNs<T> { | 135 | // struct PerNs<T> { |
133 | types: Option<T>, | 136 | // types: Option<T>, |
134 | values: Option<T>, | 137 | // values: Option<T>, |
135 | } | 138 | // } |
136 | 139 | ||
137 | #[derive(Debug, PartialEq, Eq)] | 140 | #[derive(Debug, PartialEq, Eq)] |
138 | struct ModuleItem { | 141 | struct ModuleItem { |
@@ -144,7 +147,7 @@ struct ModuleItem { | |||
144 | 147 | ||
145 | #[derive(Debug, PartialEq, Eq)] | 148 | #[derive(Debug, PartialEq, Eq)] |
146 | enum Vis { | 149 | enum Vis { |
147 | Priv, | 150 | // Priv, |
148 | Other, | 151 | Other, |
149 | } | 152 | } |
150 | 153 | ||
@@ -302,13 +305,17 @@ where | |||
302 | fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) { | 305 | fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) { |
303 | let file_id = module_id.source(&self.module_tree).file_id(); | 306 | let file_id = module_id.source(&self.module_tree).file_id(); |
304 | 307 | ||
305 | let mut module_items = ModuleItems::default(); | 308 | let mut module_items = ModuleScope::default(); |
306 | 309 | ||
307 | for import in input.imports.iter() { | 310 | for import in input.imports.iter() { |
308 | if let Some((_, name)) = import.segments.last() { | 311 | if let Some((ptr, name)) = import.segments.last() { |
309 | module_items | 312 | module_items.items.insert( |
310 | .items | 313 | name.clone(), |
311 | .insert(name.clone(), Resolution { def_id: None }); | 314 | Resolution { |
315 | def_id: None, | ||
316 | import_name: Some(*ptr), | ||
317 | }, | ||
318 | ); | ||
312 | } | 319 | } |
313 | } | 320 | } |
314 | 321 | ||
@@ -322,6 +329,7 @@ where | |||
322 | let def_id = self.db.id_maps().def_id(def_loc); | 329 | let def_id = self.db.id_maps().def_id(def_loc); |
323 | let resolution = Resolution { | 330 | let resolution = Resolution { |
324 | def_id: Some(def_id), | 331 | def_id: Some(def_id), |
332 | import_name: None, | ||
325 | }; | 333 | }; |
326 | module_items.items.insert(item.name.clone(), resolution); | 334 | module_items.items.insert(item.name.clone(), resolution); |
327 | } | 335 | } |
@@ -334,6 +342,7 @@ where | |||
334 | let def_id = self.db.id_maps().def_id(def_loc); | 342 | let def_id = self.db.id_maps().def_id(def_loc); |
335 | let resolution = Resolution { | 343 | let resolution = Resolution { |
336 | def_id: Some(def_id), | 344 | def_id: Some(def_id), |
345 | import_name: None, | ||
337 | }; | 346 | }; |
338 | module_items.items.insert(name, resolution); | 347 | module_items.items.insert(name, resolution); |
339 | } | 348 | } |
@@ -386,6 +395,7 @@ where | |||
386 | self.update(module_id, |items| { | 395 | self.update(module_id, |items| { |
387 | let res = Resolution { | 396 | let res = Resolution { |
388 | def_id: Some(def_id), | 397 | def_id: Some(def_id), |
398 | import_name: Some(*ptr), | ||
389 | }; | 399 | }; |
390 | items.items.insert(name.clone(), res); | 400 | items.items.insert(name.clone(), res); |
391 | }) | 401 | }) |
@@ -393,7 +403,7 @@ where | |||
393 | } | 403 | } |
394 | } | 404 | } |
395 | 405 | ||
396 | fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleItems)) { | 406 | fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleScope)) { |
397 | let module_items = self.result.per_module.get_mut(&module_id).unwrap(); | 407 | let module_items = self.result.per_module.get_mut(&module_id).unwrap(); |
398 | f(module_items) | 408 | f(module_items) |
399 | } | 409 | } |
diff --git a/crates/ra_analysis/src/descriptors/module/scope.rs b/crates/ra_analysis/src/descriptors/module/scope.rs deleted file mode 100644 index 4490228e4..000000000 --- a/crates/ra_analysis/src/descriptors/module/scope.rs +++ /dev/null | |||
@@ -1,124 +0,0 @@ | |||
1 | //! Backend for module-level scope resolution & completion | ||
2 | |||
3 | use ra_syntax::{ast, AstNode, SmolStr}; | ||
4 | |||
5 | use crate::syntax_ptr::LocalSyntaxPtr; | ||
6 | |||
7 | /// `ModuleScope` contains all named items declared in the scope. | ||
8 | #[derive(Debug, PartialEq, Eq)] | ||
9 | pub(crate) struct ModuleScope { | ||
10 | entries: Vec<Entry>, | ||
11 | } | ||
12 | |||
13 | /// `Entry` is a single named declaration iside a module. | ||
14 | #[derive(Debug, PartialEq, Eq)] | ||
15 | pub(crate) struct Entry { | ||
16 | ptr: LocalSyntaxPtr, | ||
17 | kind: EntryKind, | ||
18 | name: SmolStr, | ||
19 | } | ||
20 | |||
21 | #[derive(Debug, PartialEq, Eq)] | ||
22 | enum EntryKind { | ||
23 | Item, | ||
24 | Import, | ||
25 | } | ||
26 | |||
27 | impl ModuleScope { | ||
28 | pub(super) fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> ModuleScope { | ||
29 | let mut entries = Vec::new(); | ||
30 | for item in items { | ||
31 | let entry = match item { | ||
32 | ast::ModuleItem::StructDef(item) => Entry::new(item), | ||
33 | ast::ModuleItem::EnumDef(item) => Entry::new(item), | ||
34 | ast::ModuleItem::FnDef(item) => Entry::new(item), | ||
35 | ast::ModuleItem::ConstDef(item) => Entry::new(item), | ||
36 | ast::ModuleItem::StaticDef(item) => Entry::new(item), | ||
37 | ast::ModuleItem::TraitDef(item) => Entry::new(item), | ||
38 | ast::ModuleItem::TypeDef(item) => Entry::new(item), | ||
39 | ast::ModuleItem::Module(item) => Entry::new(item), | ||
40 | ast::ModuleItem::UseItem(item) => { | ||
41 | if let Some(tree) = item.use_tree() { | ||
42 | collect_imports(tree, &mut entries); | ||
43 | } | ||
44 | continue; | ||
45 | } | ||
46 | ast::ModuleItem::ExternCrateItem(_) | ast::ModuleItem::ImplItem(_) => continue, | ||
47 | }; | ||
48 | entries.extend(entry) | ||
49 | } | ||
50 | |||
51 | ModuleScope { entries } | ||
52 | } | ||
53 | |||
54 | pub fn entries(&self) -> &[Entry] { | ||
55 | self.entries.as_slice() | ||
56 | } | ||
57 | } | ||
58 | |||
59 | impl Entry { | ||
60 | fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<Entry> { | ||
61 | let name = item.name()?; | ||
62 | Some(Entry { | ||
63 | name: name.text(), | ||
64 | ptr: LocalSyntaxPtr::new(name.syntax()), | ||
65 | kind: EntryKind::Item, | ||
66 | }) | ||
67 | } | ||
68 | fn new_import(path: ast::Path) -> Option<Entry> { | ||
69 | let name_ref = path.segment()?.name_ref()?; | ||
70 | Some(Entry { | ||
71 | name: name_ref.text(), | ||
72 | ptr: LocalSyntaxPtr::new(name_ref.syntax()), | ||
73 | kind: EntryKind::Import, | ||
74 | }) | ||
75 | } | ||
76 | pub fn name(&self) -> &SmolStr { | ||
77 | &self.name | ||
78 | } | ||
79 | pub fn ptr(&self) -> LocalSyntaxPtr { | ||
80 | self.ptr | ||
81 | } | ||
82 | } | ||
83 | |||
84 | fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) { | ||
85 | if let Some(use_tree_list) = tree.use_tree_list() { | ||
86 | return use_tree_list | ||
87 | .use_trees() | ||
88 | .for_each(|it| collect_imports(it, acc)); | ||
89 | } | ||
90 | if let Some(path) = tree.path() { | ||
91 | acc.extend(Entry::new_import(path)); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | #[cfg(test)] | ||
96 | mod tests { | ||
97 | use super::*; | ||
98 | use ra_syntax::{ast::ModuleItemOwner, SourceFileNode}; | ||
99 | |||
100 | fn do_check(code: &str, expected: &[&str]) { | ||
101 | let file = SourceFileNode::parse(&code); | ||
102 | let scope = ModuleScope::new(file.ast().items()); | ||
103 | let actual = scope.entries.iter().map(|it| it.name()).collect::<Vec<_>>(); | ||
104 | assert_eq!(expected, actual.as_slice()); | ||
105 | } | ||
106 | |||
107 | #[test] | ||
108 | fn test_module_scope() { | ||
109 | do_check( | ||
110 | " | ||
111 | struct Foo; | ||
112 | enum Bar {} | ||
113 | mod baz {} | ||
114 | fn quux() {} | ||
115 | use x::{ | ||
116 | y::z, | ||
117 | t, | ||
118 | }; | ||
119 | type T = (); | ||
120 | ", | ||
121 | &["Foo", "Bar", "baz", "quux", "z", "t", "T"], | ||
122 | ) | ||
123 | } | ||
124 | } | ||
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 719c166b5..72b2ebf97 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs | |||
@@ -447,8 +447,8 @@ fn test_complete_crate_path() { | |||
447 | ); | 447 | ); |
448 | let completions = analysis.completions(position).unwrap().unwrap(); | 448 | let completions = analysis.completions(position).unwrap().unwrap(); |
449 | assert_eq_dbg( | 449 | assert_eq_dbg( |
450 | r#"[CompletionItem { label: "foo", lookup: None, snippet: None }, | 450 | r#"[CompletionItem { label: "Spam", lookup: None, snippet: None }, |
451 | CompletionItem { label: "Spam", lookup: None, snippet: None }]"#, | 451 | CompletionItem { label: "foo", lookup: None, snippet: None }]"#, |
452 | &completions, | 452 | &completions, |
453 | ); | 453 | ); |
454 | } | 454 | } |
@@ -466,8 +466,8 @@ fn test_complete_crate_path_with_braces() { | |||
466 | ); | 466 | ); |
467 | let completions = analysis.completions(position).unwrap().unwrap(); | 467 | let completions = analysis.completions(position).unwrap().unwrap(); |
468 | assert_eq_dbg( | 468 | assert_eq_dbg( |
469 | r#"[CompletionItem { label: "foo", lookup: None, snippet: None }, | 469 | r#"[CompletionItem { label: "Spam", lookup: None, snippet: None }, |
470 | CompletionItem { label: "Spam", lookup: None, snippet: None }]"#, | 470 | CompletionItem { label: "foo", lookup: None, snippet: None }]"#, |
471 | &completions, | 471 | &completions, |
472 | ); | 472 | ); |
473 | } | 473 | } |