aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs1
-rw-r--r--crates/ra_analysis/src/descriptors/module/nameres.rs156
-rw-r--r--crates/ra_syntax/src/ast/mod.rs6
3 files changed, 163 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs
index 091c150e5..958487541 100644
--- a/crates/ra_analysis/src/descriptors/module/mod.rs
+++ b/crates/ra_analysis/src/descriptors/module/mod.rs
@@ -1,5 +1,6 @@
1pub(super) mod imp; 1pub(super) mod imp;
2mod scope; 2mod scope;
3mod nameres;
3 4
4use std::sync::Arc; 5use std::sync::Arc;
5 6
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs
new file mode 100644
index 000000000..137aa8b17
--- /dev/null
+++ b/crates/ra_analysis/src/descriptors/module/nameres.rs
@@ -0,0 +1,156 @@
1//! Name resolution algorithm
2use rustc_hash::FxHashMap;
3
4use ra_syntax::{
5 SmolStr, SyntaxKind,
6 ast::{self, NameOwner}
7};
8
9use crate::{
10 descriptors::module::ModuleId,
11 syntax_ptr::LocalSyntaxPtr,
12};
13
14/// A set of items and imports declared inside a module, without relation to
15/// other modules.
16///
17/// This stands in-between raw syntax and name resolution and alow us to avoid
18/// recomputing name res: if `InputModuleItems` are the same, we can avoid
19/// running name resolution.
20#[derive(Debug, Default)]
21struct InputModuleItems {
22 items: Vec<ModuleItem>,
23 glob_imports: Vec<Path>,
24 imports: Vec<Path>,
25}
26
27#[derive(Debug, Clone)]
28struct Path {
29 kind: PathKind,
30 segments: Vec<SmolStr>,
31}
32
33#[derive(Debug, Clone, Copy)]
34enum PathKind {
35 Abs,
36 Self_,
37 Super,
38 Crate,
39}
40
41#[derive(Debug)]
42struct ItemMap {
43 per_module: FxHashMap<ModuleId, ModuleItems>,
44}
45
46#[derive(Debug)]
47struct ModuleItems {
48 items: FxHashMap<SmolStr, PerNs<ModuleItem>>,
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
52enum Namespace {
53 Types,
54 Values,
55}
56
57#[derive(Debug)]
58struct PerNs<T> {
59 types: Option<T>,
60 values: Option<T>,
61}
62
63#[derive(Debug)]
64struct ModuleItem {
65 ptr: LocalSyntaxPtr,
66 name: SmolStr,
67 kind: SyntaxKind,
68 vis: Vis,
69}
70
71#[derive(Debug)]
72enum Vis {
73 Priv,
74 Other,
75}
76
77impl InputModuleItems {
78 fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> InputModuleItems {
79 let mut res = InputModuleItems::default();
80 for item in items {
81 res.add_item(item);
82 }
83 res
84 }
85
86 fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> {
87 match item {
88 ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(it)?),
89 ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(it)?),
90 ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?),
91 ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?),
92 ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?),
93 ast::ModuleItem::ImplItem(it) => {
94 // impls don't define items
95 }
96 ast::ModuleItem::UseItem(it) => self.add_use_item(it),
97 ast::ModuleItem::ExternCrateItem(it) => (),
98 ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?),
99 ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?),
100 ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?),
101 }
102 Some(())
103 }
104
105 fn add_use_item(&mut self, item: ast::UseItem) {
106 if let Some(tree) = item.use_tree() {
107 self.add_use_tree(None, tree);
108 }
109 }
110
111 fn add_use_tree(&mut self, prefix: Option<Path>, tree: ast::UseTree) {
112 if let Some(use_tree_list) = tree.use_tree_list() {
113 let prefix = match tree.path() {
114 None => prefix,
115 Some(path) => match convert_path(prefix, path) {
116 Some(it) => Some(it),
117 None => return, // TODO: report errors somewhere
118 },
119 };
120 for tree in use_tree_list.use_trees() {
121 self.add_use_tree(prefix.clone(), tree);
122 }
123 } else {
124 if let Some(path) = tree.path() {
125 if let Some(path) = convert_path(prefix, path) {
126 if tree.has_star() {
127 &mut self.glob_imports
128 } else {
129 &mut self.imports
130 }
131 .push(path);
132 }
133 }
134 }
135 }
136}
137
138fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
139 prefix
140}
141
142impl ModuleItem {
143 fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
144 let name = item.name()?.text();
145 let ptr = LocalSyntaxPtr::new(item.syntax());
146 let kind = item.syntax().kind();
147 let vis = Vis::Other;
148 let res = ModuleItem {
149 ptr,
150 name,
151 kind,
152 vis,
153 };
154 Some(res)
155 }
156}
diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast/mod.rs
index 7077e3492..91c67119f 100644
--- a/crates/ra_syntax/src/ast/mod.rs
+++ b/crates/ra_syntax/src/ast/mod.rs
@@ -315,6 +315,12 @@ impl<'a> PathSegment<'a> {
315 } 315 }
316} 316}
317 317
318impl<'a> UseTree<'a> {
319 pub fn has_star(self) -> bool {
320 self.syntax().children().any(|it| it.kind() == STAR)
321 }
322}
323
318impl<'a> UseTreeList<'a> { 324impl<'a> UseTreeList<'a> {
319 pub fn parent_use_tree(self) -> UseTree<'a> { 325 pub fn parent_use_tree(self) -> UseTree<'a> {
320 self.syntax() 326 self.syntax()