aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/descriptors')
-rw-r--r--crates/ra_analysis/src/descriptors/module/imp.rs16
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs84
-rw-r--r--crates/ra_analysis/src/descriptors/module/scope.rs15
3 files changed, 80 insertions, 35 deletions
diff --git a/crates/ra_analysis/src/descriptors/module/imp.rs b/crates/ra_analysis/src/descriptors/module/imp.rs
index 22dbe7184..3a010ecf5 100644
--- a/crates/ra_analysis/src/descriptors/module/imp.rs
+++ b/crates/ra_analysis/src/descriptors/module/imp.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, NameOwner}, 4 ast::{self, ModuleItemOwner, NameOwner},
5 SmolStr, 5 SmolStr,
6}; 6};
7use relative_path::RelativePathBuf; 7use relative_path::RelativePathBuf;
@@ -15,7 +15,8 @@ use crate::{
15}; 15};
16 16
17use super::{ 17use super::{
18 LinkData, LinkId, ModuleData, ModuleId, ModuleScope, ModuleSource, ModuleTree, Problem, 18 LinkData, LinkId, ModuleData, ModuleId, ModuleScope, ModuleSource, ModuleSourceNode,
19 ModuleTree, Problem,
19}; 20};
20 21
21pub(crate) fn submodules( 22pub(crate) fn submodules(
@@ -45,9 +46,14 @@ pub(crate) fn module_scope(
45 module_id: ModuleId, 46 module_id: ModuleId,
46) -> Cancelable<Arc<ModuleScope>> { 47) -> Cancelable<Arc<ModuleScope>> {
47 let tree = db.module_tree(source_root_id)?; 48 let tree = db.module_tree(source_root_id)?;
48 let ModuleSource::File(file_id) = module_id.source(&tree); 49 let source = module_id.source(&tree).resolve(db);
49 let syntax = db.file_syntax(file_id); 50 let res = match source {
50 let res = ModuleScope::new(&syntax); 51 ModuleSourceNode::Root(root) => ModuleScope::new(root.ast().items()),
52 ModuleSourceNode::Inline(inline) => match inline.ast().item_list() {
53 Some(items) => ModuleScope::new(items.items()),
54 None => ModuleScope::new(std::iter::empty()),
55 },
56 };
51 Ok(Arc::new(res)) 57 Ok(Arc::new(res))
52} 58}
53 59
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};
8use relative_path::RelativePathBuf; 8use relative_path::RelativePathBuf;
9 9
10use crate::FileId; 10use crate::{db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId};
11 11
12pub(crate) use self::scope::ModuleScope; 12pub(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)]
46pub(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.
54enum 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)]
43pub(crate) struct ModuleId(u32); 60pub(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)]
128pub(crate) enum ModuleSource {
129 File(FileId),
130 // Inline(SyntaxPtr),
131}
132
133impl ModuleSource { 159impl 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)]
diff --git a/crates/ra_analysis/src/descriptors/module/scope.rs b/crates/ra_analysis/src/descriptors/module/scope.rs
index 681e272c2..215b31f8e 100644
--- a/crates/ra_analysis/src/descriptors/module/scope.rs
+++ b/crates/ra_analysis/src/descriptors/module/scope.rs
@@ -1,9 +1,6 @@
1//! Backend for module-level scope resolution & completion 1//! Backend for module-level scope resolution & completion
2 2
3use ra_syntax::{ 3use ra_syntax::{ast, AstNode, SmolStr};
4 ast::{self, ModuleItemOwner},
5 AstNode, File, SmolStr,
6};
7 4
8use crate::syntax_ptr::LocalSyntaxPtr; 5use crate::syntax_ptr::LocalSyntaxPtr;
9 6
@@ -28,11 +25,7 @@ enum EntryKind {
28} 25}
29 26
30impl ModuleScope { 27impl ModuleScope {
31 pub fn new(file: &File) -> ModuleScope { 28 pub(crate) fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> ModuleScope {
32 ModuleScope::from_items(file.ast().items())
33 }
34
35 pub fn from_items<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> ModuleScope {
36 let mut entries = Vec::new(); 29 let mut entries = Vec::new();
37 for item in items { 30 for item in items {
38 let entry = match item { 31 let entry = match item {
@@ -102,11 +95,11 @@ fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) {
102#[cfg(test)] 95#[cfg(test)]
103mod tests { 96mod tests {
104 use super::*; 97 use super::*;
105 use ra_syntax::File; 98 use ra_syntax::{ast::ModuleItemOwner, File};
106 99
107 fn do_check(code: &str, expected: &[&str]) { 100 fn do_check(code: &str, expected: &[&str]) {
108 let file = File::parse(&code); 101 let file = File::parse(&code);
109 let scope = ModuleScope::new(&file); 102 let scope = ModuleScope::new(file.ast().items());
110 let actual = scope.entries.iter().map(|it| it.name()).collect::<Vec<_>>(); 103 let actual = scope.entries.iter().map(|it| it.name()).collect::<Vec<_>>();
111 assert_eq!(expected, actual.as_slice()); 104 assert_eq!(expected, actual.as_slice());
112 } 105 }