diff options
author | Aleksey Kladov <[email protected]> | 2019-01-06 14:33:27 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-06 14:36:10 +0000 |
commit | fd4456d0ec88e3433a7a8be6f27d8af9afedefe5 (patch) | |
tree | 37f1225b085e22756cbfd65875595c60205cc93a /crates/ra_hir/src/module.rs | |
parent | 5a505189a8f7ed274893a45aed0d0249083d1277 (diff) |
flatten module structure
Diffstat (limited to 'crates/ra_hir/src/module.rs')
-rw-r--r-- | crates/ra_hir/src/module.rs | 209 |
1 files changed, 0 insertions, 209 deletions
diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs deleted file mode 100644 index ebaf5f47a..000000000 --- a/crates/ra_hir/src/module.rs +++ /dev/null | |||
@@ -1,209 +0,0 @@ | |||
1 | pub(super) mod imp; | ||
2 | pub(super) mod nameres; | ||
3 | |||
4 | use ra_syntax::{ | ||
5 | algo::generate, | ||
6 | ast::{self, AstNode, NameOwner}, | ||
7 | SyntaxNode, | ||
8 | }; | ||
9 | use ra_arena::{Arena, RawId, impl_arena_id}; | ||
10 | use relative_path::RelativePathBuf; | ||
11 | |||
12 | use crate::{Name, HirDatabase, SourceItemId, SourceFileItemId, HirFileId}; | ||
13 | |||
14 | pub use self::nameres::{ModuleScope, Resolution, Namespace, PerNs}; | ||
15 | |||
16 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
17 | pub struct ModuleId(RawId); | ||
18 | impl_arena_id!(ModuleId); | ||
19 | |||
20 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
21 | pub struct LinkId(RawId); | ||
22 | impl_arena_id!(LinkId); | ||
23 | |||
24 | /// Physically, rust source is organized as a set of files, but logically it is | ||
25 | /// organized as a tree of modules. Usually, a single file corresponds to a | ||
26 | /// single module, but it is not nessary the case. | ||
27 | /// | ||
28 | /// Module encapsulate the logic of transitioning from the fuzzy world of files | ||
29 | /// (which can have multiple parents) to the precise world of modules (which | ||
30 | /// always have one parent). | ||
31 | #[derive(Default, Debug, PartialEq, Eq)] | ||
32 | pub struct ModuleTree { | ||
33 | mods: Arena<ModuleId, ModuleData>, | ||
34 | links: Arena<LinkId, LinkData>, | ||
35 | } | ||
36 | |||
37 | impl ModuleTree { | ||
38 | pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a { | ||
39 | self.mods.iter().map(|(id, _)| id) | ||
40 | } | ||
41 | |||
42 | pub(crate) fn modules_with_sources<'a>( | ||
43 | &'a self, | ||
44 | ) -> impl Iterator<Item = (ModuleId, ModuleSource)> + 'a { | ||
45 | self.mods.iter().map(|(id, m)| (id, m.source)) | ||
46 | } | ||
47 | } | ||
48 | |||
49 | /// `ModuleSource` is the syntax tree element that produced this module: | ||
50 | /// either a file, or an inlinde module. | ||
51 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
52 | pub struct ModuleSource(pub(crate) SourceItemId); | ||
53 | |||
54 | /// An owned syntax node for a module. Unlike `ModuleSource`, | ||
55 | /// this holds onto the AST for the whole file. | ||
56 | pub(crate) enum ModuleSourceNode { | ||
57 | SourceFile(ast::SourceFileNode), | ||
58 | Module(ast::ModuleNode), | ||
59 | } | ||
60 | |||
61 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | ||
62 | pub enum Problem { | ||
63 | UnresolvedModule { | ||
64 | candidate: RelativePathBuf, | ||
65 | }, | ||
66 | NotDirOwner { | ||
67 | move_to: RelativePathBuf, | ||
68 | candidate: RelativePathBuf, | ||
69 | }, | ||
70 | } | ||
71 | |||
72 | impl ModuleId { | ||
73 | pub(crate) fn source(self, tree: &ModuleTree) -> ModuleSource { | ||
74 | tree.mods[self].source | ||
75 | } | ||
76 | pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { | ||
77 | tree.mods[self].parent | ||
78 | } | ||
79 | pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { | ||
80 | let link = self.parent_link(tree)?; | ||
81 | Some(tree.links[link].owner) | ||
82 | } | ||
83 | pub(crate) fn crate_root(self, tree: &ModuleTree) -> ModuleId { | ||
84 | generate(Some(self), move |it| it.parent(tree)) | ||
85 | .last() | ||
86 | .unwrap() | ||
87 | } | ||
88 | pub(crate) fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> { | ||
89 | let link = tree.mods[self] | ||
90 | .children | ||
91 | .iter() | ||
92 | .map(|&it| &tree.links[it]) | ||
93 | .find(|it| it.name == *name)?; | ||
94 | Some(*link.points_to.first()?) | ||
95 | } | ||
96 | fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator<Item = (Name, ModuleId)> + 'a { | ||
97 | tree.mods[self].children.iter().filter_map(move |&it| { | ||
98 | let link = &tree.links[it]; | ||
99 | let module = *link.points_to.first()?; | ||
100 | Some((link.name.clone(), module)) | ||
101 | }) | ||
102 | } | ||
103 | pub(crate) fn problems( | ||
104 | self, | ||
105 | tree: &ModuleTree, | ||
106 | db: &impl HirDatabase, | ||
107 | ) -> Vec<(SyntaxNode, Problem)> { | ||
108 | tree.mods[self] | ||
109 | .children | ||
110 | .iter() | ||
111 | .filter_map(|&it| { | ||
112 | let p = tree.links[it].problem.clone()?; | ||
113 | let s = it.bind_source(tree, db); | ||
114 | let s = s.borrowed().name().unwrap().syntax().owned(); | ||
115 | Some((s, p)) | ||
116 | }) | ||
117 | .collect() | ||
118 | } | ||
119 | } | ||
120 | |||
121 | impl LinkId { | ||
122 | pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { | ||
123 | tree.links[self].owner | ||
124 | } | ||
125 | pub(crate) fn name(self, tree: &ModuleTree) -> &Name { | ||
126 | &tree.links[self].name | ||
127 | } | ||
128 | pub(crate) fn bind_source<'a>( | ||
129 | self, | ||
130 | tree: &ModuleTree, | ||
131 | db: &impl HirDatabase, | ||
132 | ) -> ast::ModuleNode { | ||
133 | let owner = self.owner(tree); | ||
134 | match owner.source(tree).resolve(db) { | ||
135 | ModuleSourceNode::SourceFile(root) => { | ||
136 | let ast = imp::modules(root.borrowed()) | ||
137 | .find(|(name, _)| name == &tree.links[self].name) | ||
138 | .unwrap() | ||
139 | .1; | ||
140 | ast.owned() | ||
141 | } | ||
142 | ModuleSourceNode::Module(it) => it, | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | |||
147 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
148 | pub struct ModuleData { | ||
149 | source: ModuleSource, | ||
150 | parent: Option<LinkId>, | ||
151 | children: Vec<LinkId>, | ||
152 | } | ||
153 | |||
154 | impl ModuleSource { | ||
155 | // precondition: item_id **must** point to module | ||
156 | fn new(file_id: HirFileId, item_id: Option<SourceFileItemId>) -> ModuleSource { | ||
157 | let source_item_id = SourceItemId { file_id, item_id }; | ||
158 | ModuleSource(source_item_id) | ||
159 | } | ||
160 | |||
161 | pub(crate) fn new_file(file_id: HirFileId) -> ModuleSource { | ||
162 | ModuleSource::new(file_id, None) | ||
163 | } | ||
164 | |||
165 | pub(crate) fn new_inline( | ||
166 | db: &impl HirDatabase, | ||
167 | file_id: HirFileId, | ||
168 | m: ast::Module, | ||
169 | ) -> ModuleSource { | ||
170 | assert!(!m.has_semi()); | ||
171 | let file_items = db.file_items(file_id); | ||
172 | let item_id = file_items.id_of(file_id, m.syntax()); | ||
173 | ModuleSource::new(file_id, Some(item_id)) | ||
174 | } | ||
175 | |||
176 | pub(crate) fn file_id(self) -> HirFileId { | ||
177 | self.0.file_id | ||
178 | } | ||
179 | |||
180 | pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode { | ||
181 | let syntax_node = db.file_item(self.0); | ||
182 | let syntax_node = syntax_node.borrowed(); | ||
183 | if let Some(file) = ast::SourceFile::cast(syntax_node) { | ||
184 | return ModuleSourceNode::SourceFile(file.owned()); | ||
185 | } | ||
186 | let module = ast::Module::cast(syntax_node).unwrap(); | ||
187 | ModuleSourceNode::Module(module.owned()) | ||
188 | } | ||
189 | } | ||
190 | |||
191 | #[derive(Hash, Debug, PartialEq, Eq)] | ||
192 | struct LinkData { | ||
193 | owner: ModuleId, | ||
194 | name: Name, | ||
195 | points_to: Vec<ModuleId>, | ||
196 | problem: Option<Problem>, | ||
197 | } | ||
198 | |||
199 | impl ModuleTree { | ||
200 | fn push_mod(&mut self, data: ModuleData) -> ModuleId { | ||
201 | self.mods.alloc(data) | ||
202 | } | ||
203 | fn push_link(&mut self, data: LinkData) -> LinkId { | ||
204 | let owner = data.owner; | ||
205 | let id = self.links.alloc(data); | ||
206 | self.mods[owner].children.push(id); | ||
207 | id | ||
208 | } | ||
209 | } | ||