diff options
author | Aleksey Kladov <[email protected]> | 2018-11-21 09:57:05 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-11-21 09:57:05 +0000 |
commit | 049f8df93cca05af395ce873738dc85d5a25f3fc (patch) | |
tree | 55614a697cc531a53f2836c994d3211c6cd756c2 /crates/ra_analysis/src/descriptors/module | |
parent | b70b6bce19981df5d0cda6a0193fb9b07da6ea51 (diff) |
switch completion to new scope
Diffstat (limited to 'crates/ra_analysis/src/descriptors/module')
-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 |
4 files changed, 42 insertions, 172 deletions
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 | } | ||