diff options
author | Aleksey Kladov <[email protected]> | 2018-09-16 10:54:24 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-09-16 11:07:39 +0100 |
commit | b5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch) | |
tree | 9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_editor/src/scope/mod_scope.rs | |
parent | ba0bfeee12e19da40b5eabc8d0408639af10e96f (diff) |
rename all things
Diffstat (limited to 'crates/ra_editor/src/scope/mod_scope.rs')
-rw-r--r-- | crates/ra_editor/src/scope/mod_scope.rs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/crates/ra_editor/src/scope/mod_scope.rs b/crates/ra_editor/src/scope/mod_scope.rs new file mode 100644 index 000000000..d2a3e7c58 --- /dev/null +++ b/crates/ra_editor/src/scope/mod_scope.rs | |||
@@ -0,0 +1,115 @@ | |||
1 | use ra_syntax::{ | ||
2 | AstNode, SyntaxNode, SyntaxNodeRef, SmolStr, | ||
3 | ast::{self, AstChildren}, | ||
4 | }; | ||
5 | |||
6 | pub struct ModuleScope { | ||
7 | entries: Vec<Entry>, | ||
8 | } | ||
9 | |||
10 | pub struct Entry { | ||
11 | node: SyntaxNode, | ||
12 | kind: EntryKind, | ||
13 | } | ||
14 | |||
15 | enum EntryKind { | ||
16 | Item, Import, | ||
17 | } | ||
18 | |||
19 | impl ModuleScope { | ||
20 | pub fn new(items: AstChildren<ast::ModuleItem>) -> ModuleScope { | ||
21 | let mut entries = Vec::new(); | ||
22 | for item in items { | ||
23 | let entry = match item { | ||
24 | ast::ModuleItem::StructDef(item) => Entry::new(item), | ||
25 | ast::ModuleItem::EnumDef(item) => Entry::new(item), | ||
26 | ast::ModuleItem::FnDef(item) => Entry::new(item), | ||
27 | ast::ModuleItem::ConstDef(item) => Entry::new(item), | ||
28 | ast::ModuleItem::StaticDef(item) => Entry::new(item), | ||
29 | ast::ModuleItem::TraitDef(item) => Entry::new(item), | ||
30 | ast::ModuleItem::TypeDef(item) => Entry::new(item), | ||
31 | ast::ModuleItem::Module(item) => Entry::new(item), | ||
32 | ast::ModuleItem::UseItem(item) => { | ||
33 | if let Some(tree) = item.use_tree() { | ||
34 | collect_imports(tree, &mut entries); | ||
35 | } | ||
36 | continue; | ||
37 | }, | ||
38 | ast::ModuleItem::ExternCrateItem(_) | | ||
39 | ast::ModuleItem::ImplItem(_) => continue, | ||
40 | }; | ||
41 | entries.extend(entry) | ||
42 | } | ||
43 | |||
44 | ModuleScope { entries } | ||
45 | } | ||
46 | |||
47 | pub fn entries(&self) -> &[Entry] { | ||
48 | self.entries.as_slice() | ||
49 | } | ||
50 | } | ||
51 | |||
52 | impl Entry { | ||
53 | fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<Entry> { | ||
54 | let name = item.name()?; | ||
55 | Some(Entry { node: name.syntax().owned(), kind: EntryKind::Item }) | ||
56 | } | ||
57 | fn new_import(path: ast::Path) -> Option<Entry> { | ||
58 | let name_ref = path.segment()?.name_ref()?; | ||
59 | Some(Entry { node: name_ref.syntax().owned(), kind: EntryKind::Import }) | ||
60 | } | ||
61 | pub fn name(&self) -> SmolStr { | ||
62 | match self.kind { | ||
63 | EntryKind::Item => | ||
64 | ast::Name::cast(self.node.borrowed()).unwrap() | ||
65 | .text(), | ||
66 | EntryKind::Import => | ||
67 | ast::NameRef::cast(self.node.borrowed()).unwrap() | ||
68 | .text(), | ||
69 | } | ||
70 | } | ||
71 | pub fn syntax(&self) -> SyntaxNodeRef { | ||
72 | self.node.borrowed() | ||
73 | } | ||
74 | } | ||
75 | |||
76 | fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) { | ||
77 | if let Some(use_tree_list) = tree.use_tree_list() { | ||
78 | return use_tree_list.use_trees().for_each(|it| collect_imports(it, acc)); | ||
79 | } | ||
80 | if let Some(path) = tree.path() { | ||
81 | acc.extend(Entry::new_import(path)); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | |||
86 | #[cfg(test)] | ||
87 | mod tests { | ||
88 | use super::*; | ||
89 | use ra_syntax::{File, ast::ModuleItemOwner}; | ||
90 | |||
91 | fn do_check(code: &str, expected: &[&str]) { | ||
92 | let file = File::parse(&code); | ||
93 | let scope = ModuleScope::new(file.ast().items()); | ||
94 | let actual = scope.entries | ||
95 | .iter() | ||
96 | .map(|it| it.name()) | ||
97 | .collect::<Vec<_>>(); | ||
98 | assert_eq!(expected, actual.as_slice()); | ||
99 | } | ||
100 | |||
101 | #[test] | ||
102 | fn test_module_scope() { | ||
103 | do_check(" | ||
104 | struct Foo; | ||
105 | enum Bar {} | ||
106 | mod baz {} | ||
107 | fn quux() {} | ||
108 | use x::{ | ||
109 | y::z, | ||
110 | t, | ||
111 | }; | ||
112 | type T = (); | ||
113 | ", &["Foo", "Bar", "baz", "quux", "z", "t", "T"]) | ||
114 | } | ||
115 | } | ||