diff options
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r-- | crates/ra_analysis/src/db.rs | 21 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors.rs | 108 | ||||
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 207 | ||||
-rw-r--r-- | crates/ra_analysis/src/job.rs | 14 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 78 | ||||
-rw-r--r-- | crates/ra_analysis/src/module_map.rs | 13 | ||||
-rw-r--r-- | crates/ra_analysis/src/roots.rs | 63 | ||||
-rw-r--r-- | crates/ra_analysis/src/symbol_index.rs | 29 |
8 files changed, 298 insertions, 235 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index c69577233..042dde1ac 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -1,17 +1,18 @@ | |||
1 | use std::{ | ||
2 | fmt, | ||
3 | sync::Arc, | ||
4 | hash::{Hash, Hasher}, | ||
5 | }; | ||
6 | use salsa; | ||
7 | use rustc_hash::FxHashSet; | ||
8 | use ra_syntax::File; | ||
9 | use ra_editor::{LineIndex}; | ||
10 | use crate::{ | 1 | use crate::{ |
2 | module_map::{ModuleDescriptorQuery, ModuleTreeQuery, ModulesDatabase}, | ||
11 | symbol_index::SymbolIndex, | 3 | symbol_index::SymbolIndex, |
12 | module_map::{ModulesDatabase, ModuleTreeQuery, ModuleDescriptorQuery}, | ||
13 | FileId, FileResolverImp, | 4 | FileId, FileResolverImp, |
14 | }; | 5 | }; |
6 | use ra_editor::LineIndex; | ||
7 | use ra_syntax::File; | ||
8 | use rustc_hash::FxHashSet; | ||
9 | use salsa; | ||
10 | |||
11 | use std::{ | ||
12 | fmt, | ||
13 | hash::{Hash, Hasher}, | ||
14 | sync::Arc, | ||
15 | }; | ||
15 | 16 | ||
16 | #[derive(Default)] | 17 | #[derive(Default)] |
17 | pub(crate) struct RootDatabase { | 18 | pub(crate) struct RootDatabase { |
diff --git a/crates/ra_analysis/src/descriptors.rs b/crates/ra_analysis/src/descriptors.rs index 8d9f38ca5..6f26f9935 100644 --- a/crates/ra_analysis/src/descriptors.rs +++ b/crates/ra_analysis/src/descriptors.rs | |||
@@ -1,41 +1,34 @@ | |||
1 | use std::{ | 1 | use crate::{imp::FileResolverImp, FileId}; |
2 | collections::BTreeMap, | ||
3 | }; | ||
4 | use relative_path::RelativePathBuf; | ||
5 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | ast::{self, AstNode, NameOwner}, | ||
4 | text_utils::is_subrange, | ||
6 | SmolStr, | 5 | SmolStr, |
7 | ast::{self, NameOwner, AstNode}, | ||
8 | text_utils::is_subrange | ||
9 | }; | ||
10 | use crate::{ | ||
11 | FileId, | ||
12 | imp::FileResolverImp, | ||
13 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | ||
8 | |||
9 | use std::collections::BTreeMap; | ||
14 | 10 | ||
15 | #[derive(Debug, PartialEq, Eq, Hash)] | 11 | #[derive(Debug, PartialEq, Eq, Hash)] |
16 | pub struct ModuleDescriptor { | 12 | pub struct ModuleDescriptor { |
17 | pub submodules: Vec<Submodule> | 13 | pub submodules: Vec<Submodule>, |
18 | } | 14 | } |
19 | 15 | ||
20 | impl ModuleDescriptor { | 16 | impl ModuleDescriptor { |
21 | pub fn new(root: ast::Root) -> ModuleDescriptor { | 17 | pub fn new(root: ast::Root) -> ModuleDescriptor { |
22 | let submodules = modules(root) | 18 | let submodules = modules(root).map(|(name, _)| Submodule { name }).collect(); |
23 | .map(|(name, _)| Submodule { name }) | ||
24 | .collect(); | ||
25 | 19 | ||
26 | ModuleDescriptor { submodules } } | 20 | ModuleDescriptor { submodules } |
21 | } | ||
27 | } | 22 | } |
28 | 23 | ||
29 | fn modules<'a>(root: ast::Root<'a>) -> impl Iterator<Item=(SmolStr, ast::Module<'a>)> { | 24 | fn modules<'a>(root: ast::Root<'a>) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> { |
30 | root | 25 | root.modules().filter_map(|module| { |
31 | .modules() | 26 | let name = module.name()?.text(); |
32 | .filter_map(|module| { | 27 | if !module.has_semi() { |
33 | let name = module.name()?.text(); | 28 | return None; |
34 | if !module.has_semi() { | 29 | } |
35 | return None; | 30 | Some((name, module)) |
36 | } | 31 | }) |
37 | Some((name, module)) | ||
38 | }) | ||
39 | } | 32 | } |
40 | 33 | ||
41 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] | 34 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] |
@@ -56,7 +49,7 @@ struct Node(usize); | |||
56 | struct NodeData { | 49 | struct NodeData { |
57 | file_id: FileId, | 50 | file_id: FileId, |
58 | links: Vec<Link>, | 51 | links: Vec<Link>, |
59 | parents: Vec<Link> | 52 | parents: Vec<Link>, |
60 | } | 53 | } |
61 | 54 | ||
62 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 55 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
@@ -69,7 +62,6 @@ struct LinkData { | |||
69 | problem: Option<Problem>, | 62 | problem: Option<Problem>, |
70 | } | 63 | } |
71 | 64 | ||
72 | |||
73 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | 65 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
74 | pub enum Problem { | 66 | pub enum Problem { |
75 | UnresolvedModule { | 67 | UnresolvedModule { |
@@ -78,16 +70,18 @@ pub enum Problem { | |||
78 | NotDirOwner { | 70 | NotDirOwner { |
79 | move_to: RelativePathBuf, | 71 | move_to: RelativePathBuf, |
80 | candidate: RelativePathBuf, | 72 | candidate: RelativePathBuf, |
81 | } | 73 | }, |
82 | } | 74 | } |
83 | 75 | ||
84 | impl ModuleTreeDescriptor { | 76 | impl ModuleTreeDescriptor { |
85 | pub(crate) fn new<'a>( | 77 | pub(crate) fn new<'a>( |
86 | files: impl Iterator<Item=(FileId, &'a ModuleDescriptor)> + Clone, | 78 | files: impl Iterator<Item = (FileId, &'a ModuleDescriptor)> + Clone, |
87 | file_resolver: &FileResolverImp, | 79 | file_resolver: &FileResolverImp, |
88 | ) -> ModuleTreeDescriptor { | 80 | ) -> ModuleTreeDescriptor { |
89 | let mut file_id2node = BTreeMap::new(); | 81 | let mut file_id2node = BTreeMap::new(); |
90 | let mut nodes: Vec<NodeData> = files.clone().enumerate() | 82 | let mut nodes: Vec<NodeData> = files |
83 | .clone() | ||
84 | .enumerate() | ||
91 | .map(|(idx, (file_id, _))| { | 85 | .map(|(idx, (file_id, _))| { |
92 | file_id2node.insert(file_id, Node(idx)); | 86 | file_id2node.insert(file_id, Node(idx)); |
93 | NodeData { | 87 | NodeData { |
@@ -120,20 +114,19 @@ impl ModuleTreeDescriptor { | |||
120 | points_to, | 114 | points_to, |
121 | problem, | 115 | problem, |
122 | }) | 116 | }) |
123 | |||
124 | } | 117 | } |
125 | } | 118 | } |
126 | 119 | ||
127 | ModuleTreeDescriptor { | 120 | ModuleTreeDescriptor { |
128 | nodes, links, file_id2node | 121 | nodes, |
122 | links, | ||
123 | file_id2node, | ||
129 | } | 124 | } |
130 | } | 125 | } |
131 | 126 | ||
132 | pub(crate) fn parent_modules(&self, file_id: FileId) -> Vec<Link> { | 127 | pub(crate) fn parent_modules(&self, file_id: FileId) -> Vec<Link> { |
133 | let node = self.file_id2node[&file_id]; | 128 | let node = self.file_id2node[&file_id]; |
134 | self.node(node) | 129 | self.node(node).parents.clone() |
135 | .parents | ||
136 | .clone() | ||
137 | } | 130 | } |
138 | pub(crate) fn child_module_by_name(&self, file_id: FileId, name: &str) -> Vec<FileId> { | 131 | pub(crate) fn child_module_by_name(&self, file_id: FileId, name: &str) -> Vec<FileId> { |
139 | let node = self.file_id2node[&file_id]; | 132 | let node = self.file_id2node[&file_id]; |
@@ -141,10 +134,18 @@ impl ModuleTreeDescriptor { | |||
141 | .links | 134 | .links |
142 | .iter() | 135 | .iter() |
143 | .filter(|it| it.name(self) == name) | 136 | .filter(|it| it.name(self) == name) |
144 | .flat_map(|link| link.points_to(self).iter().map(|&node| self.node(node).file_id)) | 137 | .flat_map(|link| { |
138 | link.points_to(self) | ||
139 | .iter() | ||
140 | .map(|&node| self.node(node).file_id) | ||
141 | }) | ||
145 | .collect() | 142 | .collect() |
146 | } | 143 | } |
147 | pub(crate) fn problems<'a, 'b>(&'b self, file_id: FileId, root: ast::Root<'a>) -> Vec<(ast::Name<'a>, &'b Problem)> { | 144 | pub(crate) fn problems<'a, 'b>( |
145 | &'b self, | ||
146 | file_id: FileId, | ||
147 | root: ast::Root<'a>, | ||
148 | ) -> Vec<(ast::Name<'a>, &'b Problem)> { | ||
148 | let node = self.file_id2node[&file_id]; | 149 | let node = self.file_id2node[&file_id]; |
149 | self.node(node) | 150 | self.node(node) |
150 | .links | 151 | .links |
@@ -176,7 +177,11 @@ impl Link { | |||
176 | fn points_to(self, tree: &ModuleTreeDescriptor) -> &[Node] { | 177 | fn points_to(self, tree: &ModuleTreeDescriptor) -> &[Node] { |
177 | &tree.link(self).points_to | 178 | &tree.link(self).points_to |
178 | } | 179 | } |
179 | pub(crate) fn bind_source<'a>(self, tree: &ModuleTreeDescriptor, root: ast::Root<'a>) -> ast::Module<'a> { | 180 | pub(crate) fn bind_source<'a>( |
181 | self, | ||
182 | tree: &ModuleTreeDescriptor, | ||
183 | root: ast::Root<'a>, | ||
184 | ) -> ast::Module<'a> { | ||
180 | modules(root) | 185 | modules(root) |
181 | .filter(|(name, _)| name == &tree.link(self).name) | 186 | .filter(|(name, _)| name == &tree.link(self).name) |
182 | .next() | 187 | .next() |
@@ -185,22 +190,21 @@ impl Link { | |||
185 | } | 190 | } |
186 | } | 191 | } |
187 | 192 | ||
188 | |||
189 | fn resolve_submodule( | 193 | fn resolve_submodule( |
190 | file_id: FileId, | 194 | file_id: FileId, |
191 | name: &SmolStr, | 195 | name: &SmolStr, |
192 | file_resolver: &FileResolverImp | 196 | file_resolver: &FileResolverImp, |
193 | ) -> (Vec<FileId>, Option<Problem>) { | 197 | ) -> (Vec<FileId>, Option<Problem>) { |
194 | let mod_name = file_resolver.file_stem(file_id); | 198 | let mod_name = file_resolver.file_stem(file_id); |
195 | let is_dir_owner = | 199 | let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; |
196 | mod_name == "mod" || mod_name == "lib" || mod_name == "main"; | ||
197 | 200 | ||
198 | let file_mod = RelativePathBuf::from(format!("../{}.rs", name)); | 201 | let file_mod = RelativePathBuf::from(format!("../{}.rs", name)); |
199 | let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name)); | 202 | let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name)); |
200 | let points_to: Vec<FileId>; | 203 | let points_to: Vec<FileId>; |
201 | let problem: Option<Problem>; | 204 | let problem: Option<Problem>; |
202 | if is_dir_owner { | 205 | if is_dir_owner { |
203 | points_to = [&file_mod, &dir_mod].iter() | 206 | points_to = [&file_mod, &dir_mod] |
207 | .iter() | ||
204 | .filter_map(|path| file_resolver.resolve(file_id, path)) | 208 | .filter_map(|path| file_resolver.resolve(file_id, path)) |
205 | .collect(); | 209 | .collect(); |
206 | problem = if points_to.is_empty() { | 210 | problem = if points_to.is_empty() { |
@@ -223,7 +227,7 @@ fn resolve_submodule( | |||
223 | #[derive(Debug, Clone)] | 227 | #[derive(Debug, Clone)] |
224 | pub struct FnDescriptor { | 228 | pub struct FnDescriptor { |
225 | pub name: String, | 229 | pub name: String, |
226 | pub label : String, | 230 | pub label: String, |
227 | pub ret_type: Option<String>, | 231 | pub ret_type: Option<String>, |
228 | pub params: Vec<String>, | 232 | pub params: Vec<String>, |
229 | } | 233 | } |
@@ -233,9 +237,11 @@ impl FnDescriptor { | |||
233 | let name = node.name()?.text().to_string(); | 237 | let name = node.name()?.text().to_string(); |
234 | 238 | ||
235 | // Strip the body out for the label. | 239 | // Strip the body out for the label. |
236 | let label : String = if let Some(body) = node.body() { | 240 | let label: String = if let Some(body) = node.body() { |
237 | let body_range = body.syntax().range(); | 241 | let body_range = body.syntax().range(); |
238 | let label : String = node.syntax().children() | 242 | let label: String = node |
243 | .syntax() | ||
244 | .children() | ||
239 | .filter(|child| !is_subrange(body_range, child.range())) | 245 | .filter(|child| !is_subrange(body_range, child.range())) |
240 | .map(|node| node.text().to_string()) | 246 | .map(|node| node.text().to_string()) |
241 | .collect(); | 247 | .collect(); |
@@ -251,7 +257,7 @@ impl FnDescriptor { | |||
251 | name, | 257 | name, |
252 | ret_type, | 258 | ret_type, |
253 | params, | 259 | params, |
254 | label | 260 | label, |
255 | }) | 261 | }) |
256 | } | 262 | } |
257 | 263 | ||
@@ -264,9 +270,11 @@ impl FnDescriptor { | |||
264 | 270 | ||
265 | // Maybe use param.pat here? See if we can just extract the name? | 271 | // Maybe use param.pat here? See if we can just extract the name? |
266 | //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); | 272 | //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); |
267 | res.extend(param_list.params() | 273 | res.extend( |
268 | .filter_map(|p| p.pat()) | 274 | param_list |
269 | .map(|pat| pat.syntax().text().to_string()) | 275 | .params() |
276 | .filter_map(|p| p.pat()) | ||
277 | .map(|pat| pat.syntax().text().to_string()), | ||
270 | ); | 278 | ); |
271 | } | 279 | } |
272 | res | 280 | res |
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 5efcaeca0..f1403cb5d 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -1,32 +1,31 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | sync::{ | ||
3 | Arc, | ||
4 | }, | ||
5 | hash::{Hash, Hasher}, | ||
6 | fmt, | ||
7 | collections::VecDeque, | 2 | collections::VecDeque, |
3 | fmt, | ||
4 | hash::{Hash, Hasher}, | ||
8 | iter, | 5 | iter, |
6 | sync::Arc, | ||
9 | }; | 7 | }; |
10 | 8 | ||
11 | use relative_path::RelativePath; | 9 | use ra_editor::{self, find_node_at_offset, resolve_local_name, FileSymbol, LineIndex, LocalEdit}; |
12 | use rustc_hash::FxHashSet; | ||
13 | use ra_editor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit, resolve_local_name}; | ||
14 | use ra_syntax::{ | 10 | use ra_syntax::{ |
15 | TextUnit, TextRange, SmolStr, File, AstNode, SyntaxNodeRef, | 11 | ast::{self, ArgListOwner, Expr, NameOwner}, |
12 | AstNode, File, SmolStr, | ||
16 | SyntaxKind::*, | 13 | SyntaxKind::*, |
17 | ast::{self, NameOwner, ArgListOwner, Expr}, | 14 | SyntaxNodeRef, TextRange, TextUnit, |
18 | }; | 15 | }; |
16 | use relative_path::RelativePath; | ||
17 | use rustc_hash::FxHashSet; | ||
19 | 18 | ||
20 | use crate::{ | 19 | use crate::{ |
21 | FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, | ||
22 | JobToken, CrateGraph, CrateId, | ||
23 | roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot}, | ||
24 | descriptors::{FnDescriptor, ModuleTreeDescriptor, Problem}, | 20 | descriptors::{FnDescriptor, ModuleTreeDescriptor, Problem}, |
21 | roots::{ReadonlySourceRoot, SourceRoot, WritableSourceRoot}, | ||
22 | CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, JobToken, Position, | ||
23 | Query, SourceChange, SourceFileEdit, | ||
25 | }; | 24 | }; |
26 | 25 | ||
27 | #[derive(Clone, Debug)] | 26 | #[derive(Clone, Debug)] |
28 | pub(crate) struct FileResolverImp { | 27 | pub(crate) struct FileResolverImp { |
29 | inner: Arc<FileResolver> | 28 | inner: Arc<FileResolver>, |
30 | } | 29 | } |
31 | 30 | ||
32 | impl PartialEq for FileResolverImp { | 31 | impl PartialEq for FileResolverImp { |
@@ -35,8 +34,7 @@ impl PartialEq for FileResolverImp { | |||
35 | } | 34 | } |
36 | } | 35 | } |
37 | 36 | ||
38 | impl Eq for FileResolverImp { | 37 | impl Eq for FileResolverImp {} |
39 | } | ||
40 | 38 | ||
41 | impl Hash for FileResolverImp { | 39 | impl Hash for FileResolverImp { |
42 | fn hash<H: Hasher>(&self, hasher: &mut H) { | 40 | fn hash<H: Hasher>(&self, hasher: &mut H) { |
@@ -67,17 +65,23 @@ impl Default for FileResolverImp { | |||
67 | fn file_stem(&self, _file_: FileId) -> String { | 65 | fn file_stem(&self, _file_: FileId) -> String { |
68 | panic!("file resolver not set") | 66 | panic!("file resolver not set") |
69 | } | 67 | } |
70 | fn resolve(&self, _file_id: FileId, _path: &::relative_path::RelativePath) -> Option<FileId> { | 68 | fn resolve( |
69 | &self, | ||
70 | _file_id: FileId, | ||
71 | _path: &::relative_path::RelativePath, | ||
72 | ) -> Option<FileId> { | ||
71 | panic!("file resolver not set") | 73 | panic!("file resolver not set") |
72 | } | 74 | } |
73 | } | 75 | } |
74 | FileResolverImp { inner: Arc::new(DummyResolver) } | 76 | FileResolverImp { |
77 | inner: Arc::new(DummyResolver), | ||
78 | } | ||
75 | } | 79 | } |
76 | } | 80 | } |
77 | 81 | ||
78 | #[derive(Debug)] | 82 | #[derive(Debug)] |
79 | pub(crate) struct AnalysisHostImpl { | 83 | pub(crate) struct AnalysisHostImpl { |
80 | data: WorldData | 84 | data: WorldData, |
81 | } | 85 | } |
82 | 86 | ||
83 | impl AnalysisHostImpl { | 87 | impl AnalysisHostImpl { |
@@ -91,13 +95,13 @@ impl AnalysisHostImpl { | |||
91 | data: self.data.clone(), | 95 | data: self.data.clone(), |
92 | } | 96 | } |
93 | } | 97 | } |
94 | pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) { | 98 | pub fn change_files(&mut self, changes: &mut dyn Iterator<Item = (FileId, Option<String>)>) { |
95 | self.data_mut() | 99 | self.data_mut().root.apply_changes(changes, None); |
96 | .root.apply_changes(changes, None); | ||
97 | } | 100 | } |
98 | pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { | 101 | pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { |
99 | self.data_mut() | 102 | self.data_mut() |
100 | .root.apply_changes(&mut iter::empty(), Some(resolver)); | 103 | .root |
104 | .apply_changes(&mut iter::empty(), Some(resolver)); | ||
101 | } | 105 | } |
102 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { | 106 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { |
103 | let mut visited = FxHashSet::default(); | 107 | let mut visited = FxHashSet::default(); |
@@ -131,7 +135,12 @@ impl AnalysisImpl { | |||
131 | if self.data.root.contains(file_id) { | 135 | if self.data.root.contains(file_id) { |
132 | return &self.data.root; | 136 | return &self.data.root; |
133 | } | 137 | } |
134 | &**self.data.libs.iter().find(|it| it.contains(file_id)).unwrap() | 138 | &**self |
139 | .data | ||
140 | .libs | ||
141 | .iter() | ||
142 | .find(|it| it.contains(file_id)) | ||
143 | .unwrap() | ||
135 | } | 144 | } |
136 | pub fn file_syntax(&self, file_id: FileId) -> File { | 145 | pub fn file_syntax(&self, file_id: FileId) -> File { |
137 | self.root(file_id).syntax(file_id) | 146 | self.root(file_id).syntax(file_id) |
@@ -142,18 +151,17 @@ impl AnalysisImpl { | |||
142 | pub fn world_symbols(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | 151 | pub fn world_symbols(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { |
143 | let mut buf = Vec::new(); | 152 | let mut buf = Vec::new(); |
144 | if query.libs { | 153 | if query.libs { |
145 | self.data.libs.iter() | 154 | self.data.libs.iter().for_each(|it| it.symbols(&mut buf)); |
146 | .for_each(|it| it.symbols(&mut buf)); | ||
147 | } else { | 155 | } else { |
148 | self.data.root.symbols(&mut buf); | 156 | self.data.root.symbols(&mut buf); |
149 | } | 157 | } |
150 | query.search(&buf, token) | 158 | query.search(&buf, token) |
151 | |||
152 | } | 159 | } |
153 | pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { | 160 | pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { |
154 | let root = self.root(file_id); | 161 | let root = self.root(file_id); |
155 | let module_tree = root.module_tree(); | 162 | let module_tree = root.module_tree(); |
156 | module_tree.parent_modules(file_id) | 163 | module_tree |
164 | .parent_modules(file_id) | ||
157 | .iter() | 165 | .iter() |
158 | .map(|link| { | 166 | .map(|link| { |
159 | let file_id = link.owner(&module_tree); | 167 | let file_id = link.owner(&module_tree); |
@@ -203,15 +211,17 @@ impl AnalysisImpl { | |||
203 | let file = root.syntax(file_id); | 211 | let file = root.syntax(file_id); |
204 | let syntax = file.syntax(); | 212 | let syntax = file.syntax(); |
205 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { | 213 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { |
206 | |||
207 | // First try to resolve the symbol locally | 214 | // First try to resolve the symbol locally |
208 | if let Some((name, range)) = resolve_local_name(&file, offset, name_ref) { | 215 | if let Some((name, range)) = resolve_local_name(&file, offset, name_ref) { |
209 | let mut vec = vec![]; | 216 | let mut vec = vec![]; |
210 | vec.push((file_id, FileSymbol { | 217 | vec.push(( |
211 | name, | 218 | file_id, |
212 | node_range: range, | 219 | FileSymbol { |
213 | kind : NAME | 220 | name, |
214 | })); | 221 | node_range: range, |
222 | kind: NAME, | ||
223 | }, | ||
224 | )); | ||
215 | 225 | ||
216 | return vec; | 226 | return vec; |
217 | } else { | 227 | } else { |
@@ -224,17 +234,21 @@ impl AnalysisImpl { | |||
224 | if module.has_semi() { | 234 | if module.has_semi() { |
225 | let file_ids = self.resolve_module(&*module_tree, file_id, module); | 235 | let file_ids = self.resolve_module(&*module_tree, file_id, module); |
226 | 236 | ||
227 | let res = file_ids.into_iter().map(|id| { | 237 | let res = file_ids |
228 | let name = module.name() | 238 | .into_iter() |
229 | .map(|n| n.text()) | 239 | .map(|id| { |
230 | .unwrap_or_else(|| SmolStr::new("")); | 240 | let name = module |
231 | let symbol = FileSymbol { | 241 | .name() |
232 | name, | 242 | .map(|n| n.text()) |
233 | node_range: TextRange::offset_len(0.into(), 0.into()), | 243 | .unwrap_or_else(|| SmolStr::new("")); |
234 | kind: MODULE, | 244 | let symbol = FileSymbol { |
235 | }; | 245 | name, |
236 | (id, symbol) | 246 | node_range: TextRange::offset_len(0.into(), 0.into()), |
237 | }).collect(); | 247 | kind: MODULE, |
248 | }; | ||
249 | (id, symbol) | ||
250 | }) | ||
251 | .collect(); | ||
238 | 252 | ||
239 | return res; | 253 | return res; |
240 | } | 254 | } |
@@ -245,12 +259,16 @@ impl AnalysisImpl { | |||
245 | 259 | ||
246 | pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> { | 260 | pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> { |
247 | let root = self.root(file_id); | 261 | let root = self.root(file_id); |
248 | let module_tree = root.module_tree(); | 262 | let module_tree = root.module_tree(); |
249 | let syntax = root.syntax(file_id); | 263 | let syntax = root.syntax(file_id); |
250 | 264 | ||
251 | let mut res = ra_editor::diagnostics(&syntax) | 265 | let mut res = ra_editor::diagnostics(&syntax) |
252 | .into_iter() | 266 | .into_iter() |
253 | .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None }) | 267 | .map(|d| Diagnostic { |
268 | range: d.range, | ||
269 | message: d.msg, | ||
270 | fix: None, | ||
271 | }) | ||
254 | .collect::<Vec<_>>(); | 272 | .collect::<Vec<_>>(); |
255 | 273 | ||
256 | for (name_node, problem) in module_tree.problems(file_id, syntax.ast()) { | 274 | for (name_node, problem) in module_tree.problems(file_id, syntax.ast()) { |
@@ -273,8 +291,14 @@ impl AnalysisImpl { | |||
273 | } | 291 | } |
274 | } | 292 | } |
275 | Problem::NotDirOwner { move_to, candidate } => { | 293 | Problem::NotDirOwner { move_to, candidate } => { |
276 | let move_file = FileSystemEdit::MoveFile { file: file_id, path: move_to.clone() }; | 294 | let move_file = FileSystemEdit::MoveFile { |
277 | let create_file = FileSystemEdit::CreateFile { anchor: file_id, path: move_to.join(candidate) }; | 295 | file: file_id, |
296 | path: move_to.clone(), | ||
297 | }; | ||
298 | let create_file = FileSystemEdit::CreateFile { | ||
299 | anchor: file_id, | ||
300 | path: move_to.join(candidate), | ||
301 | }; | ||
278 | let fix = SourceChange { | 302 | let fix = SourceChange { |
279 | label: "move file and create module".to_string(), | 303 | label: "move file and create module".to_string(), |
280 | source_file_edits: Vec::new(), | 304 | source_file_edits: Vec::new(), |
@@ -297,23 +321,34 @@ impl AnalysisImpl { | |||
297 | let file = self.file_syntax(file_id); | 321 | let file = self.file_syntax(file_id); |
298 | let offset = range.start(); | 322 | let offset = range.start(); |
299 | let actions = vec![ | 323 | let actions = vec![ |
300 | ("flip comma", ra_editor::flip_comma(&file, offset).map(|f| f())), | 324 | ( |
301 | ("add `#[derive]`", ra_editor::add_derive(&file, offset).map(|f| f())), | 325 | "flip comma", |
326 | ra_editor::flip_comma(&file, offset).map(|f| f()), | ||
327 | ), | ||
328 | ( | ||
329 | "add `#[derive]`", | ||
330 | ra_editor::add_derive(&file, offset).map(|f| f()), | ||
331 | ), | ||
302 | ("add impl", ra_editor::add_impl(&file, offset).map(|f| f())), | 332 | ("add impl", ra_editor::add_impl(&file, offset).map(|f| f())), |
303 | ("introduce variable", ra_editor::introduce_variable(&file, range).map(|f| f())), | 333 | ( |
334 | "introduce variable", | ||
335 | ra_editor::introduce_variable(&file, range).map(|f| f()), | ||
336 | ), | ||
304 | ]; | 337 | ]; |
305 | actions.into_iter() | 338 | actions |
339 | .into_iter() | ||
306 | .filter_map(|(name, local_edit)| { | 340 | .filter_map(|(name, local_edit)| { |
307 | Some(SourceChange::from_local_edit( | 341 | Some(SourceChange::from_local_edit(file_id, name, local_edit?)) |
308 | file_id, name, local_edit?, | ||
309 | )) | ||
310 | }) | 342 | }) |
311 | .collect() | 343 | .collect() |
312 | } | 344 | } |
313 | 345 | ||
314 | pub fn resolve_callable(&self, file_id: FileId, offset: TextUnit, token: &JobToken) | 346 | pub fn resolve_callable( |
315 | -> Option<(FnDescriptor, Option<usize>)> { | 347 | &self, |
316 | 348 | file_id: FileId, | |
349 | offset: TextUnit, | ||
350 | token: &JobToken, | ||
351 | ) -> Option<(FnDescriptor, Option<usize>)> { | ||
317 | let root = self.root(file_id); | 352 | let root = self.root(file_id); |
318 | let file = root.syntax(file_id); | 353 | let file = root.syntax(file_id); |
319 | let syntax = file.syntax(); | 354 | let syntax = file.syntax(); |
@@ -332,9 +367,7 @@ impl AnalysisImpl { | |||
332 | let mut current_parameter = None; | 367 | let mut current_parameter = None; |
333 | 368 | ||
334 | let num_params = descriptor.params.len(); | 369 | let num_params = descriptor.params.len(); |
335 | let has_self = fn_def.param_list() | 370 | let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); |
336 | .and_then(|l| l.self_param()) | ||
337 | .is_some(); | ||
338 | 371 | ||
339 | if num_params == 1 { | 372 | if num_params == 1 { |
340 | if !has_self { | 373 | if !has_self { |
@@ -350,8 +383,11 @@ impl AnalysisImpl { | |||
350 | let start = arg_list.syntax().range().start(); | 383 | let start = arg_list.syntax().range().start(); |
351 | 384 | ||
352 | let range_search = TextRange::from_to(start, offset); | 385 | let range_search = TextRange::from_to(start, offset); |
353 | let mut commas: usize = arg_list.syntax().text() | 386 | let mut commas: usize = arg_list |
354 | .slice(range_search).to_string() | 387 | .syntax() |
388 | .text() | ||
389 | .slice(range_search) | ||
390 | .to_string() | ||
355 | .matches(",") | 391 | .matches(",") |
356 | .count(); | 392 | .count(); |
357 | 393 | ||
@@ -381,7 +417,12 @@ impl AnalysisImpl { | |||
381 | self.world_symbols(query, token) | 417 | self.world_symbols(query, token) |
382 | } | 418 | } |
383 | 419 | ||
384 | fn resolve_module(&self, module_tree: &ModuleTreeDescriptor, file_id: FileId, module: ast::Module) -> Vec<FileId> { | 420 | fn resolve_module( |
421 | &self, | ||
422 | module_tree: &ModuleTreeDescriptor, | ||
423 | file_id: FileId, | ||
424 | module: ast::Module, | ||
425 | ) -> Vec<FileId> { | ||
385 | let name = match module.name() { | 426 | let name = match module.name() { |
386 | Some(name) => name.text(), | 427 | Some(name) => name.text(), |
387 | None => return Vec::new(), | 428 | None => return Vec::new(), |
@@ -407,15 +448,17 @@ impl SourceChange { | |||
407 | label: label.to_string(), | 448 | label: label.to_string(), |
408 | source_file_edits: vec![file_edit], | 449 | source_file_edits: vec![file_edit], |
409 | file_system_edits: vec![], | 450 | file_system_edits: vec![], |
410 | cursor_position: edit.cursor_position | 451 | cursor_position: edit |
411 | .map(|offset| Position { offset, file_id }) | 452 | .cursor_position |
453 | .map(|offset| Position { offset, file_id }), | ||
412 | } | 454 | } |
413 | } | 455 | } |
414 | } | 456 | } |
415 | 457 | ||
416 | impl CrateGraph { | 458 | impl CrateGraph { |
417 | fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { | 459 | fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { |
418 | let (&crate_id, _) = self.crate_roots | 460 | let (&crate_id, _) = self |
461 | .crate_roots | ||
419 | .iter() | 462 | .iter() |
420 | .find(|(_crate_id, &root_id)| root_id == file_id)?; | 463 | .find(|(_crate_id, &root_id)| root_id == file_id)?; |
421 | Some(crate_id) | 464 | Some(crate_id) |
@@ -424,7 +467,7 @@ impl CrateGraph { | |||
424 | 467 | ||
425 | enum FnCallNode<'a> { | 468 | enum FnCallNode<'a> { |
426 | CallExpr(ast::CallExpr<'a>), | 469 | CallExpr(ast::CallExpr<'a>), |
427 | MethodCallExpr(ast::MethodCallExpr<'a>) | 470 | MethodCallExpr(ast::MethodCallExpr<'a>), |
428 | } | 471 | } |
429 | 472 | ||
430 | impl<'a> FnCallNode<'a> { | 473 | impl<'a> FnCallNode<'a> { |
@@ -440,27 +483,23 @@ impl<'a> FnCallNode<'a> { | |||
440 | 483 | ||
441 | pub fn name_ref(&self) -> Option<ast::NameRef> { | 484 | pub fn name_ref(&self) -> Option<ast::NameRef> { |
442 | match *self { | 485 | match *self { |
443 | FnCallNode::CallExpr(call_expr) => { | 486 | FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()? { |
444 | Some(match call_expr.expr()? { | 487 | Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?, |
445 | Expr::PathExpr(path_expr) => { | 488 | _ => return None, |
446 | path_expr.path()?.segment()?.name_ref()? | 489 | }), |
447 | }, | 490 | |
448 | _ => return None | 491 | FnCallNode::MethodCallExpr(call_expr) => call_expr |
449 | }) | 492 | .syntax() |
450 | }, | 493 | .children() |
451 | 494 | .filter_map(ast::NameRef::cast) | |
452 | FnCallNode::MethodCallExpr(call_expr) => { | 495 | .nth(0), |
453 | call_expr.syntax().children() | ||
454 | .filter_map(ast::NameRef::cast) | ||
455 | .nth(0) | ||
456 | } | ||
457 | } | 496 | } |
458 | } | 497 | } |
459 | 498 | ||
460 | pub fn arg_list(&self) -> Option<ast::ArgList> { | 499 | pub fn arg_list(&self) -> Option<ast::ArgList> { |
461 | match *self { | 500 | match *self { |
462 | FnCallNode::CallExpr(expr) => expr.arg_list(), | 501 | FnCallNode::CallExpr(expr) => expr.arg_list(), |
463 | FnCallNode::MethodCallExpr(expr) => expr.arg_list() | 502 | FnCallNode::MethodCallExpr(expr) => expr.arg_list(), |
464 | } | 503 | } |
465 | } | 504 | } |
466 | } | 505 | } |
diff --git a/crates/ra_analysis/src/job.rs b/crates/ra_analysis/src/job.rs index ea1652a26..2871f9839 100644 --- a/crates/ra_analysis/src/job.rs +++ b/crates/ra_analysis/src/job.rs | |||
@@ -14,15 +14,20 @@ impl JobHandle { | |||
14 | pub fn new() -> (JobHandle, JobToken) { | 14 | pub fn new() -> (JobHandle, JobToken) { |
15 | let (sender_alive, receiver_alive) = bounded(0); | 15 | let (sender_alive, receiver_alive) = bounded(0); |
16 | let (sender_canceled, receiver_canceled) = bounded(0); | 16 | let (sender_canceled, receiver_canceled) = bounded(0); |
17 | let token = JobToken { _job_alive: sender_alive, job_canceled: receiver_canceled }; | 17 | let token = JobToken { |
18 | let handle = JobHandle { job_alive: receiver_alive, _job_canceled: sender_canceled }; | 18 | _job_alive: sender_alive, |
19 | job_canceled: receiver_canceled, | ||
20 | }; | ||
21 | let handle = JobHandle { | ||
22 | job_alive: receiver_alive, | ||
23 | _job_canceled: sender_canceled, | ||
24 | }; | ||
19 | (handle, token) | 25 | (handle, token) |
20 | } | 26 | } |
21 | pub fn has_completed(&self) -> bool { | 27 | pub fn has_completed(&self) -> bool { |
22 | is_closed(&self.job_alive) | 28 | is_closed(&self.job_alive) |
23 | } | 29 | } |
24 | pub fn cancel(self) { | 30 | pub fn cancel(self) {} |
25 | } | ||
26 | } | 31 | } |
27 | 32 | ||
28 | impl JobToken { | 33 | impl JobToken { |
@@ -31,7 +36,6 @@ impl JobToken { | |||
31 | } | 36 | } |
32 | } | 37 | } |
33 | 38 | ||
34 | |||
35 | // We don't actually send messages through the channels, | 39 | // We don't actually send messages through the channels, |
36 | // and instead just check if the channel is closed, | 40 | // and instead just check if the channel is closed, |
37 | // so we use uninhabited enum as a message type | 41 | // so we use uninhabited enum as a message type |
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index d8b355a81..2eeacaabe 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -1,44 +1,40 @@ | |||
1 | extern crate parking_lot; | 1 | extern crate parking_lot; |
2 | #[macro_use] | 2 | #[macro_use] |
3 | extern crate log; | 3 | extern crate log; |
4 | extern crate fst; | ||
4 | extern crate once_cell; | 5 | extern crate once_cell; |
5 | extern crate ra_syntax; | ||
6 | extern crate ra_editor; | 6 | extern crate ra_editor; |
7 | extern crate fst; | 7 | extern crate ra_syntax; |
8 | extern crate rayon; | 8 | extern crate rayon; |
9 | extern crate relative_path; | 9 | extern crate relative_path; |
10 | #[macro_use] | 10 | #[macro_use] |
11 | extern crate crossbeam_channel; | 11 | extern crate crossbeam_channel; |
12 | extern crate im; | 12 | extern crate im; |
13 | extern crate salsa; | ||
14 | extern crate rustc_hash; | 13 | extern crate rustc_hash; |
14 | extern crate salsa; | ||
15 | 15 | ||
16 | mod symbol_index; | 16 | mod db; |
17 | mod module_map; | 17 | mod descriptors; |
18 | mod imp; | 18 | mod imp; |
19 | mod job; | 19 | mod job; |
20 | mod module_map; | ||
20 | mod roots; | 21 | mod roots; |
21 | mod db; | 22 | mod symbol_index; |
22 | mod descriptors; | ||
23 | 23 | ||
24 | use std::{ | 24 | use std::{fmt::Debug, sync::Arc}; |
25 | sync::Arc, | ||
26 | fmt::Debug, | ||
27 | }; | ||
28 | 25 | ||
26 | use crate::imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}; | ||
27 | use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; | ||
29 | use relative_path::{RelativePath, RelativePathBuf}; | 28 | use relative_path::{RelativePath, RelativePathBuf}; |
30 | use ra_syntax::{File, TextRange, TextUnit, AtomEdit}; | ||
31 | use rustc_hash::FxHashMap; | 29 | use rustc_hash::FxHashMap; |
32 | use crate::imp::{AnalysisImpl, AnalysisHostImpl, FileResolverImp}; | ||
33 | 30 | ||
34 | pub use ra_editor::{ | ||
35 | StructureNode, LineIndex, FileSymbol, | ||
36 | Runnable, RunnableKind, HighlightedRange, CompletionItem, | ||
37 | Fold, FoldKind | ||
38 | }; | ||
39 | pub use crate::{ | 31 | pub use crate::{ |
40 | job::{JobToken, JobHandle}, | ||
41 | descriptors::FnDescriptor, | 32 | descriptors::FnDescriptor, |
33 | job::{JobHandle, JobToken}, | ||
34 | }; | ||
35 | pub use ra_editor::{ | ||
36 | CompletionItem, FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, | ||
37 | RunnableKind, StructureNode, | ||
42 | }; | 38 | }; |
43 | 39 | ||
44 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 40 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
@@ -59,20 +55,24 @@ pub trait FileResolver: Debug + Send + Sync + 'static { | |||
59 | 55 | ||
60 | #[derive(Debug)] | 56 | #[derive(Debug)] |
61 | pub struct AnalysisHost { | 57 | pub struct AnalysisHost { |
62 | imp: AnalysisHostImpl | 58 | imp: AnalysisHostImpl, |
63 | } | 59 | } |
64 | 60 | ||
65 | impl AnalysisHost { | 61 | impl AnalysisHost { |
66 | pub fn new() -> AnalysisHost { | 62 | pub fn new() -> AnalysisHost { |
67 | AnalysisHost { imp: AnalysisHostImpl::new() } | 63 | AnalysisHost { |
64 | imp: AnalysisHostImpl::new(), | ||
65 | } | ||
68 | } | 66 | } |
69 | pub fn analysis(&self) -> Analysis { | 67 | pub fn analysis(&self) -> Analysis { |
70 | Analysis { imp: self.imp.analysis() } | 68 | Analysis { |
69 | imp: self.imp.analysis(), | ||
70 | } | ||
71 | } | 71 | } |
72 | pub fn change_file(&mut self, file_id: FileId, text: Option<String>) { | 72 | pub fn change_file(&mut self, file_id: FileId, text: Option<String>) { |
73 | self.change_files(::std::iter::once((file_id, text))); | 73 | self.change_files(::std::iter::once((file_id, text))); |
74 | } | 74 | } |
75 | pub fn change_files(&mut self, mut changes: impl Iterator<Item=(FileId, Option<String>)>) { | 75 | pub fn change_files(&mut self, mut changes: impl Iterator<Item = (FileId, Option<String>)>) { |
76 | self.imp.change_files(&mut changes) | 76 | self.imp.change_files(&mut changes) |
77 | } | 77 | } |
78 | pub fn set_file_resolver(&mut self, resolver: Arc<FileResolver>) { | 78 | pub fn set_file_resolver(&mut self, resolver: Arc<FileResolver>) { |
@@ -115,7 +115,7 @@ pub enum FileSystemEdit { | |||
115 | MoveFile { | 115 | MoveFile { |
116 | file: FileId, | 116 | file: FileId, |
117 | path: RelativePathBuf, | 117 | path: RelativePathBuf, |
118 | } | 118 | }, |
119 | } | 119 | } |
120 | 120 | ||
121 | #[derive(Debug)] | 121 | #[derive(Debug)] |
@@ -144,7 +144,7 @@ impl Query { | |||
144 | only_types: false, | 144 | only_types: false, |
145 | libs: false, | 145 | libs: false, |
146 | exact: false, | 146 | exact: false, |
147 | limit: usize::max_value() | 147 | limit: usize::max_value(), |
148 | } | 148 | } |
149 | } | 149 | } |
150 | pub fn only_types(&mut self) { | 150 | pub fn only_types(&mut self) { |
@@ -163,7 +163,7 @@ impl Query { | |||
163 | 163 | ||
164 | #[derive(Debug)] | 164 | #[derive(Debug)] |
165 | pub struct Analysis { | 165 | pub struct Analysis { |
166 | imp: AnalysisImpl | 166 | imp: AnalysisImpl, |
167 | } | 167 | } |
168 | 168 | ||
169 | impl Analysis { | 169 | impl Analysis { |
@@ -195,7 +195,11 @@ impl Analysis { | |||
195 | } | 195 | } |
196 | pub fn on_eq_typed(&self, file_id: FileId, offset: TextUnit) -> Option<SourceChange> { | 196 | pub fn on_eq_typed(&self, file_id: FileId, offset: TextUnit) -> Option<SourceChange> { |
197 | let file = self.imp.file_syntax(file_id); | 197 | let file = self.imp.file_syntax(file_id); |
198 | Some(SourceChange::from_local_edit(file_id, "add semicolon", ra_editor::on_eq_typed(&file, offset)?)) | 198 | Some(SourceChange::from_local_edit( |
199 | file_id, | ||
200 | "add semicolon", | ||
201 | ra_editor::on_eq_typed(&file, offset)?, | ||
202 | )) | ||
199 | } | 203 | } |
200 | pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> { | 204 | pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> { |
201 | let file = self.imp.file_syntax(file_id); | 205 | let file = self.imp.file_syntax(file_id); |
@@ -204,8 +208,14 @@ impl Analysis { | |||
204 | pub fn symbol_search(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | 208 | pub fn symbol_search(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { |
205 | self.imp.world_symbols(query, token) | 209 | self.imp.world_symbols(query, token) |
206 | } | 210 | } |
207 | pub fn approximately_resolve_symbol(&self, file_id: FileId, offset: TextUnit, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | 211 | pub fn approximately_resolve_symbol( |
208 | self.imp.approximately_resolve_symbol(file_id, offset, token) | 212 | &self, |
213 | file_id: FileId, | ||
214 | offset: TextUnit, | ||
215 | token: &JobToken, | ||
216 | ) -> Vec<(FileId, FileSymbol)> { | ||
217 | self.imp | ||
218 | .approximately_resolve_symbol(file_id, offset, token) | ||
209 | } | 219 | } |
210 | pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { | 220 | pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { |
211 | self.imp.parent_module(file_id) | 221 | self.imp.parent_module(file_id) |
@@ -239,15 +249,19 @@ impl Analysis { | |||
239 | ra_editor::folding_ranges(&file) | 249 | ra_editor::folding_ranges(&file) |
240 | } | 250 | } |
241 | 251 | ||
242 | pub fn resolve_callable(&self, file_id: FileId, offset: TextUnit, token: &JobToken) | 252 | pub fn resolve_callable( |
243 | -> Option<(FnDescriptor, Option<usize>)> { | 253 | &self, |
254 | file_id: FileId, | ||
255 | offset: TextUnit, | ||
256 | token: &JobToken, | ||
257 | ) -> Option<(FnDescriptor, Option<usize>)> { | ||
244 | self.imp.resolve_callable(file_id, offset, token) | 258 | self.imp.resolve_callable(file_id, offset, token) |
245 | } | 259 | } |
246 | } | 260 | } |
247 | 261 | ||
248 | #[derive(Debug)] | 262 | #[derive(Debug)] |
249 | pub struct LibraryData { | 263 | pub struct LibraryData { |
250 | root: roots::ReadonlySourceRoot | 264 | root: roots::ReadonlySourceRoot, |
251 | } | 265 | } |
252 | 266 | ||
253 | impl LibraryData { | 267 | impl LibraryData { |
diff --git a/crates/ra_analysis/src/module_map.rs b/crates/ra_analysis/src/module_map.rs index c1799e3d4..ff0ec3cc7 100644 --- a/crates/ra_analysis/src/module_map.rs +++ b/crates/ra_analysis/src/module_map.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | use std::sync::Arc; | ||
2 | use crate::{ | 1 | use crate::{ |
3 | FileId, | 2 | db::SyntaxDatabase, |
4 | db::{SyntaxDatabase}, | ||
5 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | 3 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, |
4 | FileId, | ||
6 | }; | 5 | }; |
7 | 6 | ||
7 | use std::sync::Arc; | ||
8 | |||
8 | salsa::query_group! { | 9 | salsa::query_group! { |
9 | pub(crate) trait ModulesDatabase: SyntaxDatabase { | 10 | pub(crate) trait ModulesDatabase: SyntaxDatabase { |
10 | fn module_tree(key: ()) -> Arc<ModuleTreeDescriptor> { | 11 | fn module_tree(key: ()) -> Arc<ModuleTreeDescriptor> { |
@@ -16,7 +17,6 @@ salsa::query_group! { | |||
16 | } | 17 | } |
17 | } | 18 | } |
18 | 19 | ||
19 | |||
20 | fn module_descriptor(db: &impl ModulesDatabase, file_id: FileId) -> Arc<ModuleDescriptor> { | 20 | fn module_descriptor(db: &impl ModulesDatabase, file_id: FileId) -> Arc<ModuleDescriptor> { |
21 | let file = db.file_syntax(file_id); | 21 | let file = db.file_syntax(file_id); |
22 | Arc::new(ModuleDescriptor::new(file.ast())) | 22 | Arc::new(ModuleDescriptor::new(file.ast())) |
@@ -29,6 +29,9 @@ fn module_tree(db: &impl ModulesDatabase, (): ()) -> Arc<ModuleTreeDescriptor> { | |||
29 | let module_descr = db.module_descriptor(file_id); | 29 | let module_descr = db.module_descriptor(file_id); |
30 | files.push((file_id, module_descr)); | 30 | files.push((file_id, module_descr)); |
31 | } | 31 | } |
32 | let res = ModuleTreeDescriptor::new(files.iter().map(|(file_id, descr)| (*file_id, &**descr)), &file_set.resolver); | 32 | let res = ModuleTreeDescriptor::new( |
33 | files.iter().map(|(file_id, descr)| (*file_id, &**descr)), | ||
34 | &file_set.resolver, | ||
35 | ); | ||
33 | Arc::new(res) | 36 | Arc::new(res) |
34 | } | 37 | } |
diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs index 76bcecd38..1f2b21b27 100644 --- a/crates/ra_analysis/src/roots.rs +++ b/crates/ra_analysis/src/roots.rs | |||
@@ -1,22 +1,19 @@ | |||
1 | use std::{ | 1 | use std::{panic, sync::Arc}; |
2 | sync::Arc, | ||
3 | panic, | ||
4 | }; | ||
5 | 2 | ||
6 | use once_cell::sync::OnceCell; | 3 | use once_cell::sync::OnceCell; |
7 | use rayon::prelude::*; | ||
8 | use salsa::Database; | ||
9 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
10 | use ra_editor::LineIndex; | 4 | use ra_editor::LineIndex; |
11 | use ra_syntax::File; | 5 | use ra_syntax::File; |
6 | use rayon::prelude::*; | ||
7 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
8 | use salsa::Database; | ||
12 | 9 | ||
13 | use crate::{ | 10 | use crate::{ |
14 | FileId, | ||
15 | imp::FileResolverImp, | ||
16 | symbol_index::SymbolIndex, | ||
17 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | ||
18 | db::{self, FilesDatabase, SyntaxDatabase}, | 11 | db::{self, FilesDatabase, SyntaxDatabase}, |
12 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | ||
13 | imp::FileResolverImp, | ||
19 | module_map::ModulesDatabase, | 14 | module_map::ModulesDatabase, |
15 | symbol_index::SymbolIndex, | ||
16 | FileId, | ||
20 | }; | 17 | }; |
21 | 18 | ||
22 | pub(crate) trait SourceRoot { | 19 | pub(crate) trait SourceRoot { |
@@ -35,7 +32,7 @@ pub(crate) struct WritableSourceRoot { | |||
35 | impl WritableSourceRoot { | 32 | impl WritableSourceRoot { |
36 | pub fn apply_changes( | 33 | pub fn apply_changes( |
37 | &mut self, | 34 | &mut self, |
38 | changes: &mut dyn Iterator<Item=(FileId, Option<String>)>, | 35 | changes: &mut dyn Iterator<Item = (FileId, Option<String>)>, |
39 | file_resolver: Option<FileResolverImp>, | 36 | file_resolver: Option<FileResolverImp>, |
40 | ) { | 37 | ) { |
41 | let mut changed = FxHashSet::default(); | 38 | let mut changed = FxHashSet::default(); |
@@ -46,22 +43,22 @@ impl WritableSourceRoot { | |||
46 | removed.insert(file_id); | 43 | removed.insert(file_id); |
47 | } | 44 | } |
48 | Some(text) => { | 45 | Some(text) => { |
49 | self.db.query(db::FileTextQuery) | 46 | self.db |
47 | .query(db::FileTextQuery) | ||
50 | .set(file_id, Arc::new(text)); | 48 | .set(file_id, Arc::new(text)); |
51 | changed.insert(file_id); | 49 | changed.insert(file_id); |
52 | } | 50 | } |
53 | } | 51 | } |
54 | } | 52 | } |
55 | let file_set = self.db.file_set(()); | 53 | let file_set = self.db.file_set(()); |
56 | let mut files: FxHashSet<FileId> = file_set | 54 | let mut files: FxHashSet<FileId> = file_set.files.clone(); |
57 | .files | ||
58 | .clone(); | ||
59 | for file_id in removed { | 55 | for file_id in removed { |
60 | files.remove(&file_id); | 56 | files.remove(&file_id); |
61 | } | 57 | } |
62 | files.extend(changed); | 58 | files.extend(changed); |
63 | let resolver = file_resolver.unwrap_or_else(|| file_set.resolver.clone()); | 59 | let resolver = file_resolver.unwrap_or_else(|| file_set.resolver.clone()); |
64 | self.db.query(db::FileSetQuery) | 60 | self.db |
61 | .query(db::FileSetQuery) | ||
65 | .set((), Arc::new(db::FileSet { files, resolver })); | 62 | .set((), Arc::new(db::FileSet { files, resolver })); |
66 | } | 63 | } |
67 | } | 64 | } |
@@ -71,9 +68,7 @@ impl SourceRoot for WritableSourceRoot { | |||
71 | self.db.module_tree(()) | 68 | self.db.module_tree(()) |
72 | } | 69 | } |
73 | fn contains(&self, file_id: FileId) -> bool { | 70 | fn contains(&self, file_id: FileId) -> bool { |
74 | self.db.file_set(()) | 71 | self.db.file_set(()).files.contains(&file_id) |
75 | .files | ||
76 | .contains(&file_id) | ||
77 | } | 72 | } |
78 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { | 73 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { |
79 | self.db.file_lines(file_id) | 74 | self.db.file_lines(file_id) |
@@ -83,7 +78,7 @@ impl SourceRoot for WritableSourceRoot { | |||
83 | } | 78 | } |
84 | fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) { | 79 | fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) { |
85 | let db = &self.db; | 80 | let db = &self.db; |
86 | let symbols = db.file_set(()); | 81 | let symbols = db.file_set(()); |
87 | let symbols = symbols | 82 | let symbols = symbols |
88 | .files | 83 | .files |
89 | .iter() | 84 | .iter() |
@@ -108,12 +103,15 @@ impl FileData { | |||
108 | } | 103 | } |
109 | } | 104 | } |
110 | fn lines(&self) -> &Arc<LineIndex> { | 105 | fn lines(&self) -> &Arc<LineIndex> { |
111 | self.lines.get_or_init(|| Arc::new(LineIndex::new(&self.text))) | 106 | self.lines |
107 | .get_or_init(|| Arc::new(LineIndex::new(&self.text))) | ||
112 | } | 108 | } |
113 | fn syntax(&self) -> &File { | 109 | fn syntax(&self) -> &File { |
114 | let text = &self.text; | 110 | let text = &self.text; |
115 | let syntax = &self.syntax; | 111 | let syntax = &self.syntax; |
116 | match panic::catch_unwind(panic::AssertUnwindSafe(|| syntax.get_or_init(|| File::parse(text)))) { | 112 | match panic::catch_unwind(panic::AssertUnwindSafe(|| { |
113 | syntax.get_or_init(|| File::parse(text)) | ||
114 | })) { | ||
117 | Ok(file) => file, | 115 | Ok(file) => file, |
118 | Err(err) => { | 116 | Err(err) => { |
119 | error!("Parser paniced on:\n------\n{}\n------\n", text); | 117 | error!("Parser paniced on:\n------\n{}\n------\n", text); |
@@ -131,22 +129,23 @@ pub(crate) struct ReadonlySourceRoot { | |||
131 | } | 129 | } |
132 | 130 | ||
133 | impl ReadonlySourceRoot { | 131 | impl ReadonlySourceRoot { |
134 | pub(crate) fn new(files: Vec<(FileId, String)>, file_resolver: FileResolverImp) -> ReadonlySourceRoot { | 132 | pub(crate) fn new( |
135 | let modules = files.par_iter() | 133 | files: Vec<(FileId, String)>, |
134 | file_resolver: FileResolverImp, | ||
135 | ) -> ReadonlySourceRoot { | ||
136 | let modules = files | ||
137 | .par_iter() | ||
136 | .map(|(file_id, text)| { | 138 | .map(|(file_id, text)| { |
137 | let syntax = File::parse(text); | 139 | let syntax = File::parse(text); |
138 | let mod_descr = ModuleDescriptor::new(syntax.ast()); | 140 | let mod_descr = ModuleDescriptor::new(syntax.ast()); |
139 | (*file_id, syntax, mod_descr) | 141 | (*file_id, syntax, mod_descr) |
140 | }) | 142 | }) |
141 | .collect::<Vec<_>>(); | 143 | .collect::<Vec<_>>(); |
142 | let module_tree = ModuleTreeDescriptor::new( | 144 | let module_tree = |
143 | modules.iter().map(|it| (it.0, &it.2)), | 145 | ModuleTreeDescriptor::new(modules.iter().map(|it| (it.0, &it.2)), &file_resolver); |
144 | &file_resolver, | ||
145 | ); | ||
146 | 146 | ||
147 | let symbol_index = SymbolIndex::for_files( | 147 | let symbol_index = |
148 | modules.par_iter().map(|it| (it.0, it.1.clone())) | 148 | SymbolIndex::for_files(modules.par_iter().map(|it| (it.0, it.1.clone()))); |
149 | ); | ||
150 | let file_map: FxHashMap<FileId, FileData> = files | 149 | let file_map: FxHashMap<FileId, FileData> = files |
151 | .into_iter() | 150 | .into_iter() |
152 | .map(|(id, text)| (id, FileData::new(text))) | 151 | .map(|(id, text)| (id, FileData::new(text))) |
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index 54672fde4..51eef8170 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs | |||
@@ -1,15 +1,16 @@ | |||
1 | use std::{ | 1 | use crate::{FileId, JobToken, Query}; |
2 | sync::Arc, | 2 | use fst::{self, Streamer}; |
3 | hash::{Hash, Hasher}, | 3 | use ra_editor::{file_symbols, FileSymbol}; |
4 | }; | ||
5 | use ra_editor::{FileSymbol, file_symbols}; | ||
6 | use ra_syntax::{ | 4 | use ra_syntax::{ |
7 | File, | 5 | File, |
8 | SyntaxKind::{self, *}, | 6 | SyntaxKind::{self, *}, |
9 | }; | 7 | }; |
10 | use fst::{self, Streamer}; | ||
11 | use rayon::prelude::*; | 8 | use rayon::prelude::*; |
12 | use crate::{Query, FileId, JobToken}; | 9 | |
10 | use std::{ | ||
11 | hash::{Hash, Hasher}, | ||
12 | sync::Arc, | ||
13 | }; | ||
13 | 14 | ||
14 | #[derive(Debug)] | 15 | #[derive(Debug)] |
15 | pub(crate) struct SymbolIndex { | 16 | pub(crate) struct SymbolIndex { |
@@ -23,8 +24,7 @@ impl PartialEq for SymbolIndex { | |||
23 | } | 24 | } |
24 | } | 25 | } |
25 | 26 | ||
26 | impl Eq for SymbolIndex { | 27 | impl Eq for SymbolIndex {} |
27 | } | ||
28 | 28 | ||
29 | impl Hash for SymbolIndex { | 29 | impl Hash for SymbolIndex { |
30 | fn hash<H: Hasher>(&self, hasher: &mut H) { | 30 | fn hash<H: Hasher>(&self, hasher: &mut H) { |
@@ -33,14 +33,12 @@ impl Hash for SymbolIndex { | |||
33 | } | 33 | } |
34 | 34 | ||
35 | impl SymbolIndex { | 35 | impl SymbolIndex { |
36 | pub(crate) fn for_files(files: impl ParallelIterator<Item=(FileId, File)>) -> SymbolIndex { | 36 | pub(crate) fn for_files(files: impl ParallelIterator<Item = (FileId, File)>) -> SymbolIndex { |
37 | let mut symbols = files | 37 | let mut symbols = files |
38 | .flat_map(|(file_id, file)| { | 38 | .flat_map(|(file_id, file)| { |
39 | file_symbols(&file) | 39 | file_symbols(&file) |
40 | .into_iter() | 40 | .into_iter() |
41 | .map(move |symbol| { | 41 | .map(move |symbol| (symbol.name.as_str().to_lowercase(), (file_id, symbol))) |
42 | (symbol.name.as_str().to_lowercase(), (file_id, symbol)) | ||
43 | }) | ||
44 | .collect::<Vec<_>>() | 42 | .collect::<Vec<_>>() |
45 | }) | 43 | }) |
46 | .collect::<Vec<_>>(); | 44 | .collect::<Vec<_>>(); |
@@ -48,9 +46,7 @@ impl SymbolIndex { | |||
48 | symbols.dedup_by(|s1, s2| s1.0 == s2.0); | 46 | symbols.dedup_by(|s1, s2| s1.0 == s2.0); |
49 | let (names, symbols): (Vec<String>, Vec<(FileId, FileSymbol)>) = | 47 | let (names, symbols): (Vec<String>, Vec<(FileId, FileSymbol)>) = |
50 | symbols.into_iter().unzip(); | 48 | symbols.into_iter().unzip(); |
51 | let map = fst::Map::from_iter( | 49 | let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap(); |
52 | names.into_iter().zip(0u64..) | ||
53 | ).unwrap(); | ||
54 | SymbolIndex { symbols, map } | 50 | SymbolIndex { symbols, map } |
55 | } | 51 | } |
56 | 52 | ||
@@ -65,7 +61,6 @@ impl Query { | |||
65 | indices: &[Arc<SymbolIndex>], | 61 | indices: &[Arc<SymbolIndex>], |
66 | token: &JobToken, | 62 | token: &JobToken, |
67 | ) -> Vec<(FileId, FileSymbol)> { | 63 | ) -> Vec<(FileId, FileSymbol)> { |
68 | |||
69 | let mut op = fst::map::OpBuilder::new(); | 64 | let mut op = fst::map::OpBuilder::new(); |
70 | for file_symbols in indices.iter() { | 65 | for file_symbols in indices.iter() { |
71 | let automaton = fst::automaton::Subsequence::new(&self.lowercased); | 66 | let automaton = fst::automaton::Subsequence::new(&self.lowercased); |