diff options
Diffstat (limited to 'crates/ra_analysis/src/descriptors/module/mod.rs')
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/mod.rs | 84 |
1 files changed, 65 insertions, 19 deletions
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index cbccdb2e2..e22489fc1 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs | |||
@@ -7,7 +7,7 @@ use ra_syntax::{ | |||
7 | }; | 7 | }; |
8 | use relative_path::RelativePathBuf; | 8 | use relative_path::RelativePathBuf; |
9 | 9 | ||
10 | use crate::FileId; | 10 | use crate::{db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId}; |
11 | 11 | ||
12 | pub(crate) use self::scope::ModuleScope; | 12 | pub(crate) use self::scope::ModuleScope; |
13 | 13 | ||
@@ -39,6 +39,23 @@ impl ModuleTree { | |||
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | /// `ModuleSource` is the syntax tree element that produced this module: | ||
43 | /// either a file, or an inlinde module. | ||
44 | /// TODO: we don't produce Inline modules yet | ||
45 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
46 | pub(crate) enum ModuleSource { | ||
47 | File(FileId), | ||
48 | #[allow(dead_code)] | ||
49 | Inline(SyntaxPtr), | ||
50 | } | ||
51 | |||
52 | /// An owned syntax node for a module. Unlike `ModuleSource`, | ||
53 | /// this holds onto the AST for the whole file. | ||
54 | enum ModuleSourceNode { | ||
55 | Root(ast::RootNode), | ||
56 | Inline(ast::ModuleNode), | ||
57 | } | ||
58 | |||
42 | #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] | 59 | #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] |
43 | pub(crate) struct ModuleId(u32); | 60 | pub(crate) struct ModuleId(u32); |
44 | 61 | ||
@@ -89,14 +106,18 @@ impl ModuleId { | |||
89 | .find(|it| it.name == name)?; | 106 | .find(|it| it.name == name)?; |
90 | Some(*link.points_to.first()?) | 107 | Some(*link.points_to.first()?) |
91 | } | 108 | } |
92 | pub(crate) fn problems(self, tree: &ModuleTree, root: ast::Root) -> Vec<(SyntaxNode, Problem)> { | 109 | pub(crate) fn problems( |
110 | self, | ||
111 | tree: &ModuleTree, | ||
112 | db: &impl SyntaxDatabase, | ||
113 | ) -> Vec<(SyntaxNode, Problem)> { | ||
93 | tree.module(self) | 114 | tree.module(self) |
94 | .children | 115 | .children |
95 | .iter() | 116 | .iter() |
96 | .filter_map(|&it| { | 117 | .filter_map(|&it| { |
97 | let p = tree.link(it).problem.clone()?; | 118 | let p = tree.link(it).problem.clone()?; |
98 | let s = it.bind_source(tree, root); | 119 | let s = it.bind_source(tree, db); |
99 | let s = s.name().unwrap().syntax().owned(); | 120 | let s = s.ast().name().unwrap().syntax().owned(); |
100 | Some((s, p)) | 121 | Some((s, p)) |
101 | }) | 122 | }) |
102 | .collect() | 123 | .collect() |
@@ -107,11 +128,24 @@ impl LinkId { | |||
107 | pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { | 128 | pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { |
108 | tree.link(self).owner | 129 | tree.link(self).owner |
109 | } | 130 | } |
110 | pub(crate) fn bind_source<'a>(self, tree: &ModuleTree, root: ast::Root<'a>) -> ast::Module<'a> { | 131 | pub(crate) fn bind_source<'a>( |
111 | imp::modules(root) | 132 | self, |
112 | .find(|(name, _)| name == &tree.link(self).name) | 133 | tree: &ModuleTree, |
113 | .unwrap() | 134 | db: &impl SyntaxDatabase, |
114 | .1 | 135 | ) -> ast::ModuleNode { |
136 | let owner = self.owner(tree); | ||
137 | match owner.source(tree).resolve(db) { | ||
138 | ModuleSourceNode::Root(root) => { | ||
139 | let ast = imp::modules(root.ast()) | ||
140 | .find(|(name, _)| name == &tree.link(self).name) | ||
141 | .unwrap() | ||
142 | .1; | ||
143 | ast.into() | ||
144 | } | ||
145 | ModuleSourceNode::Inline(..) => { | ||
146 | unimplemented!("https://github.com/rust-analyzer/rust-analyzer/issues/181") | ||
147 | } | ||
148 | } | ||
115 | } | 149 | } |
116 | } | 150 | } |
117 | 151 | ||
@@ -122,20 +156,32 @@ struct ModuleData { | |||
122 | children: Vec<LinkId>, | 156 | children: Vec<LinkId>, |
123 | } | 157 | } |
124 | 158 | ||
125 | /// `ModuleSource` is the syntax tree element that produced this module: | ||
126 | /// either a file, or an inlinde module. | ||
127 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
128 | pub(crate) enum ModuleSource { | ||
129 | File(FileId), | ||
130 | // Inline(SyntaxPtr), | ||
131 | } | ||
132 | |||
133 | impl ModuleSource { | 159 | impl ModuleSource { |
134 | fn is_file(self, file_id: FileId) -> bool { | 160 | pub(crate) fn as_file(self) -> Option<FileId> { |
161 | match self { | ||
162 | ModuleSource::File(f) => Some(f), | ||
163 | ModuleSource::Inline(..) => None, | ||
164 | } | ||
165 | } | ||
166 | |||
167 | fn resolve(self, db: &impl SyntaxDatabase) -> ModuleSourceNode { | ||
135 | match self { | 168 | match self { |
136 | ModuleSource::File(f) => f == file_id, | 169 | ModuleSource::File(file_id) => { |
170 | let syntax = db.file_syntax(file_id); | ||
171 | ModuleSourceNode::Root(syntax.ast().into()) | ||
172 | } | ||
173 | ModuleSource::Inline(ptr) => { | ||
174 | let syntax = db.resolve_syntax_ptr(ptr); | ||
175 | let syntax = syntax.borrowed(); | ||
176 | let module = ast::Module::cast(syntax).unwrap(); | ||
177 | ModuleSourceNode::Inline(module.into()) | ||
178 | } | ||
137 | } | 179 | } |
138 | } | 180 | } |
181 | |||
182 | fn is_file(self, file_id: FileId) -> bool { | ||
183 | self.as_file() == Some(file_id) | ||
184 | } | ||
139 | } | 185 | } |
140 | 186 | ||
141 | #[derive(Hash, Debug, PartialEq, Eq)] | 187 | #[derive(Hash, Debug, PartialEq, Eq)] |