aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors/module/scope.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/descriptors/module/scope.rs')
-rw-r--r--crates/ra_analysis/src/descriptors/module/scope.rs124
1 files changed, 0 insertions, 124 deletions
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
3use ra_syntax::{ast, AstNode, SmolStr};
4
5use crate::syntax_ptr::LocalSyntaxPtr;
6
7/// `ModuleScope` contains all named items declared in the scope.
8#[derive(Debug, PartialEq, Eq)]
9pub(crate) struct ModuleScope {
10 entries: Vec<Entry>,
11}
12
13/// `Entry` is a single named declaration iside a module.
14#[derive(Debug, PartialEq, Eq)]
15pub(crate) struct Entry {
16 ptr: LocalSyntaxPtr,
17 kind: EntryKind,
18 name: SmolStr,
19}
20
21#[derive(Debug, PartialEq, Eq)]
22enum EntryKind {
23 Item,
24 Import,
25}
26
27impl 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
59impl 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
84fn 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)]
96mod 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}