diff options
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 376 |
1 files changed, 136 insertions, 240 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 74c248a96..f5cb3550e 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -1,91 +1,33 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | fmt, | 2 | fmt, |
3 | hash::{Hash, Hasher}, | ||
4 | sync::Arc, | 3 | sync::Arc, |
5 | }; | 4 | }; |
6 | 5 | ||
7 | use ra_editor::{self, find_node_at_offset, FileSymbol, LineIndex, LocalEdit}; | 6 | use ra_editor::{self, find_node_at_offset, FileSymbol, LineIndex, LocalEdit}; |
8 | use ra_syntax::{ | 7 | use ra_syntax::{ |
9 | ast::{self, ArgListOwner, Expr, NameOwner}, | 8 | ast::{self, ArgListOwner, Expr, NameOwner}, |
10 | AstNode, SourceFileNode, SmolStr, | 9 | AstNode, SourceFileNode, |
11 | SyntaxKind::*, | 10 | SyntaxKind::*, |
12 | SyntaxNodeRef, TextRange, TextUnit, | 11 | SyntaxNodeRef, TextRange, TextUnit, |
13 | }; | 12 | }; |
13 | use ra_db::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE, SyntaxDatabase, SourceFileQuery}; | ||
14 | use rayon::prelude::*; | 14 | use rayon::prelude::*; |
15 | use relative_path::RelativePath; | ||
16 | use rustc_hash::FxHashSet; | 15 | use rustc_hash::FxHashSet; |
17 | use salsa::{Database, ParallelDatabase}; | 16 | use salsa::{Database, ParallelDatabase}; |
17 | use hir::{ | ||
18 | self, | ||
19 | FnSignatureInfo, | ||
20 | Problem, | ||
21 | }; | ||
18 | 22 | ||
19 | use crate::{ | 23 | use crate::{ |
20 | completion::{completions, CompletionItem}, | 24 | completion::{completions, CompletionItem}, |
21 | db::{self, FileSyntaxQuery, SyntaxDatabase}, | 25 | db, |
22 | descriptors::{ | 26 | symbol_index::{SymbolIndex, SymbolsDatabase}, |
23 | function::{FnDescriptor, FnId}, | 27 | AnalysisChange, Cancelable, CrateId, Diagnostic, FileId, |
24 | module::{ModuleSource, ModuleTree, Problem}, | ||
25 | DeclarationDescriptor, DescriptorDatabase, | ||
26 | }, | ||
27 | input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, | ||
28 | symbol_index::SymbolIndex, | ||
29 | AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver, | ||
30 | FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, | 28 | FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, |
31 | }; | 29 | }; |
32 | 30 | ||
33 | #[derive(Clone, Debug)] | ||
34 | pub(crate) struct FileResolverImp { | ||
35 | inner: Arc<FileResolver>, | ||
36 | } | ||
37 | |||
38 | impl PartialEq for FileResolverImp { | ||
39 | fn eq(&self, other: &FileResolverImp) -> bool { | ||
40 | self.inner() == other.inner() | ||
41 | } | ||
42 | } | ||
43 | |||
44 | impl Eq for FileResolverImp {} | ||
45 | |||
46 | impl Hash for FileResolverImp { | ||
47 | fn hash<H: Hasher>(&self, hasher: &mut H) { | ||
48 | self.inner().hash(hasher); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | impl FileResolverImp { | ||
53 | pub(crate) fn new(inner: Arc<FileResolver>) -> FileResolverImp { | ||
54 | FileResolverImp { inner } | ||
55 | } | ||
56 | pub(crate) fn file_stem(&self, file_id: FileId) -> String { | ||
57 | self.inner.file_stem(file_id) | ||
58 | } | ||
59 | pub(crate) fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId> { | ||
60 | self.inner.resolve(file_id, path) | ||
61 | } | ||
62 | fn inner(&self) -> *const FileResolver { | ||
63 | &*self.inner | ||
64 | } | ||
65 | } | ||
66 | |||
67 | impl Default for FileResolverImp { | ||
68 | fn default() -> FileResolverImp { | ||
69 | #[derive(Debug)] | ||
70 | struct DummyResolver; | ||
71 | impl FileResolver for DummyResolver { | ||
72 | fn file_stem(&self, _file_: FileId) -> String { | ||
73 | panic!("file resolver not set") | ||
74 | } | ||
75 | fn resolve( | ||
76 | &self, | ||
77 | _file_id: FileId, | ||
78 | _path: &::relative_path::RelativePath, | ||
79 | ) -> Option<FileId> { | ||
80 | panic!("file resolver not set") | ||
81 | } | ||
82 | } | ||
83 | FileResolverImp { | ||
84 | inner: Arc::new(DummyResolver), | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | #[derive(Debug, Default)] | 31 | #[derive(Debug, Default)] |
90 | pub(crate) struct AnalysisHostImpl { | 32 | pub(crate) struct AnalysisHostImpl { |
91 | db: db::RootDatabase, | 33 | db: db::RootDatabase, |
@@ -102,7 +44,7 @@ impl AnalysisHostImpl { | |||
102 | 44 | ||
103 | for (file_id, text) in change.files_changed { | 45 | for (file_id, text) in change.files_changed { |
104 | self.db | 46 | self.db |
105 | .query_mut(crate::input::FileTextQuery) | 47 | .query_mut(ra_db::FileTextQuery) |
106 | .set(file_id, Arc::new(text)) | 48 | .set(file_id, Arc::new(text)) |
107 | } | 49 | } |
108 | if !(change.files_added.is_empty() && change.files_removed.is_empty()) { | 50 | if !(change.files_added.is_empty() && change.files_removed.is_empty()) { |
@@ -112,22 +54,22 @@ impl AnalysisHostImpl { | |||
112 | let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE)); | 54 | let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE)); |
113 | for (file_id, text) in change.files_added { | 55 | for (file_id, text) in change.files_added { |
114 | self.db | 56 | self.db |
115 | .query_mut(crate::input::FileTextQuery) | 57 | .query_mut(ra_db::FileTextQuery) |
116 | .set(file_id, Arc::new(text)); | 58 | .set(file_id, Arc::new(text)); |
117 | self.db | 59 | self.db |
118 | .query_mut(crate::input::FileSourceRootQuery) | 60 | .query_mut(ra_db::FileSourceRootQuery) |
119 | .set(file_id, crate::input::WORKSPACE); | 61 | .set(file_id, ra_db::WORKSPACE); |
120 | source_root.files.insert(file_id); | 62 | source_root.files.insert(file_id); |
121 | } | 63 | } |
122 | for file_id in change.files_removed { | 64 | for file_id in change.files_removed { |
123 | self.db | 65 | self.db |
124 | .query_mut(crate::input::FileTextQuery) | 66 | .query_mut(ra_db::FileTextQuery) |
125 | .set(file_id, Arc::new(String::new())); | 67 | .set(file_id, Arc::new(String::new())); |
126 | source_root.files.remove(&file_id); | 68 | source_root.files.remove(&file_id); |
127 | } | 69 | } |
128 | source_root.file_resolver = file_resolver; | 70 | source_root.file_resolver = file_resolver; |
129 | self.db | 71 | self.db |
130 | .query_mut(crate::input::SourceRootQuery) | 72 | .query_mut(ra_db::SourceRootQuery) |
131 | .set(WORKSPACE, Arc::new(source_root)) | 73 | .set(WORKSPACE, Arc::new(source_root)) |
132 | } | 74 | } |
133 | if !change.libraries_added.is_empty() { | 75 | if !change.libraries_added.is_empty() { |
@@ -138,11 +80,16 @@ impl AnalysisHostImpl { | |||
138 | let mut files = FxHashSet::default(); | 80 | let mut files = FxHashSet::default(); |
139 | for (file_id, text) in library.files { | 81 | for (file_id, text) in library.files { |
140 | files.insert(file_id); | 82 | files.insert(file_id); |
83 | log::debug!( | ||
84 | "library file: {:?} {:?}", | ||
85 | file_id, | ||
86 | library.file_resolver.debug_path(file_id) | ||
87 | ); | ||
141 | self.db | 88 | self.db |
142 | .query_mut(crate::input::FileSourceRootQuery) | 89 | .query_mut(ra_db::FileSourceRootQuery) |
143 | .set_constant(file_id, source_root_id); | 90 | .set_constant(file_id, source_root_id); |
144 | self.db | 91 | self.db |
145 | .query_mut(crate::input::FileTextQuery) | 92 | .query_mut(ra_db::FileTextQuery) |
146 | .set_constant(file_id, Arc::new(text)); | 93 | .set_constant(file_id, Arc::new(text)); |
147 | } | 94 | } |
148 | let source_root = SourceRoot { | 95 | let source_root = SourceRoot { |
@@ -150,19 +97,19 @@ impl AnalysisHostImpl { | |||
150 | file_resolver: library.file_resolver, | 97 | file_resolver: library.file_resolver, |
151 | }; | 98 | }; |
152 | self.db | 99 | self.db |
153 | .query_mut(crate::input::SourceRootQuery) | 100 | .query_mut(ra_db::SourceRootQuery) |
154 | .set(source_root_id, Arc::new(source_root)); | 101 | .set(source_root_id, Arc::new(source_root)); |
155 | self.db | 102 | self.db |
156 | .query_mut(crate::input::LibrarySymbolsQuery) | 103 | .query_mut(crate::symbol_index::LibrarySymbolsQuery) |
157 | .set(source_root_id, Arc::new(library.symbol_index)); | 104 | .set(source_root_id, Arc::new(library.symbol_index)); |
158 | } | 105 | } |
159 | self.db | 106 | self.db |
160 | .query_mut(crate::input::LibrariesQuery) | 107 | .query_mut(ra_db::LibrariesQuery) |
161 | .set((), Arc::new(libraries)); | 108 | .set((), Arc::new(libraries)); |
162 | } | 109 | } |
163 | if let Some(crate_graph) = change.crate_graph { | 110 | if let Some(crate_graph) = change.crate_graph { |
164 | self.db | 111 | self.db |
165 | .query_mut(crate::input::CrateGraphQuery) | 112 | .query_mut(ra_db::CrateGraphQuery) |
166 | .set((), Arc::new(crate_graph)) | 113 | .set((), Arc::new(crate_graph)) |
167 | } | 114 | } |
168 | } | 115 | } |
@@ -181,7 +128,7 @@ impl fmt::Debug for AnalysisImpl { | |||
181 | 128 | ||
182 | impl AnalysisImpl { | 129 | impl AnalysisImpl { |
183 | pub fn file_syntax(&self, file_id: FileId) -> SourceFileNode { | 130 | pub fn file_syntax(&self, file_id: FileId) -> SourceFileNode { |
184 | self.db.file_syntax(file_id) | 131 | self.db.source_file(file_id) |
185 | } | 132 | } |
186 | pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { | 133 | pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { |
187 | self.db.file_lines(file_id) | 134 | self.db.file_lines(file_id) |
@@ -212,59 +159,48 @@ impl AnalysisImpl { | |||
212 | .collect() | 159 | .collect() |
213 | }; | 160 | }; |
214 | self.db | 161 | self.db |
215 | .query(FileSyntaxQuery) | 162 | .query(SourceFileQuery) |
216 | .sweep(salsa::SweepStrategy::default().discard_values()); | 163 | .sweep(salsa::SweepStrategy::default().discard_values()); |
217 | Ok(query.search(&buf)) | 164 | Ok(query.search(&buf)) |
218 | } | 165 | } |
219 | fn module_tree(&self, file_id: FileId) -> Cancelable<Arc<ModuleTree>> { | 166 | /// This return `Vec`: a module may be included from several places. We |
220 | let source_root = self.db.file_source_root(file_id); | 167 | /// don't handle this case yet though, so the Vec has length at most one. |
221 | self.db.module_tree(source_root) | ||
222 | } | ||
223 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 168 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
224 | let module_tree = self.module_tree(position.file_id)?; | 169 | let descr = match hir::Module::guess_from_position(&*self.db, position)? { |
225 | let file = self.db.file_syntax(position.file_id); | 170 | None => return Ok(Vec::new()), |
226 | let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) | 171 | Some(it) => it, |
227 | { | ||
228 | Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m), | ||
229 | _ => ModuleSource::SourceFile(position.file_id), | ||
230 | }; | 172 | }; |
231 | 173 | let (file_id, decl) = match descr.parent_link_source(&*self.db) { | |
232 | let res = module_tree | 174 | None => return Ok(Vec::new()), |
233 | .modules_for_source(module_source) | 175 | Some(it) => it, |
234 | .into_iter() | 176 | }; |
235 | .filter_map(|module_id| { | 177 | let decl = decl.borrowed(); |
236 | let link = module_id.parent_link(&module_tree)?; | 178 | let decl_name = decl.name().unwrap(); |
237 | let file_id = link.owner(&module_tree).source(&module_tree).file_id(); | 179 | let sym = FileSymbol { |
238 | let decl = link.bind_source(&module_tree, &*self.db); | 180 | name: decl_name.text(), |
239 | let decl = decl.borrowed(); | 181 | node_range: decl_name.syntax().range(), |
240 | 182 | kind: MODULE, | |
241 | let decl_name = decl.name().unwrap(); | 183 | }; |
242 | 184 | Ok(vec![(file_id, sym)]) | |
243 | let sym = FileSymbol { | ||
244 | name: decl_name.text(), | ||
245 | node_range: decl_name.syntax().range(), | ||
246 | kind: MODULE, | ||
247 | }; | ||
248 | Some((file_id, sym)) | ||
249 | }) | ||
250 | .collect(); | ||
251 | Ok(res) | ||
252 | } | 185 | } |
186 | /// Returns `Vec` for the same reason as `parent_module` | ||
253 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { | 187 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { |
254 | let module_tree = self.module_tree(file_id)?; | 188 | let descr = match hir::Module::guess_from_file_id(&*self.db, file_id)? { |
255 | let crate_graph = self.db.crate_graph(); | 189 | None => return Ok(Vec::new()), |
256 | let res = module_tree | 190 | Some(it) => it, |
257 | .modules_for_source(ModuleSource::SourceFile(file_id)) | 191 | }; |
258 | .into_iter() | 192 | let root = descr.crate_root(); |
259 | .map(|it| it.root(&module_tree)) | 193 | let file_id = root |
260 | .filter_map(|it| it.source(&module_tree).as_file()) | 194 | .source() |
261 | .filter_map(|it| crate_graph.crate_id_for_crate_root(it)) | 195 | .as_file() |
262 | .collect(); | 196 | .expect("root module always has a file as a source"); |
263 | 197 | ||
264 | Ok(res) | 198 | let crate_graph = self.db.crate_graph(); |
199 | let crate_id = crate_graph.crate_id_for_crate_root(file_id); | ||
200 | Ok(crate_id.into_iter().collect()) | ||
265 | } | 201 | } |
266 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { | 202 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { |
267 | self.db.crate_graph().crate_roots[&crate_id] | 203 | self.db.crate_graph().crate_root(crate_id) |
268 | } | 204 | } |
269 | pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { | 205 | pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { |
270 | completions(&self.db, position) | 206 | completions(&self.db, position) |
@@ -273,51 +209,51 @@ impl AnalysisImpl { | |||
273 | &self, | 209 | &self, |
274 | position: FilePosition, | 210 | position: FilePosition, |
275 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 211 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
276 | let module_tree = self.module_tree(position.file_id)?; | 212 | let file = self.db.source_file(position.file_id); |
277 | let file = self.db.file_syntax(position.file_id); | ||
278 | let syntax = file.syntax(); | 213 | let syntax = file.syntax(); |
279 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { | 214 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { |
280 | // First try to resolve the symbol locally | 215 | if let Some(fn_descr) = |
281 | return if let Some((name, range)) = | 216 | hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref) |
282 | resolve_local_name(&self.db, position.file_id, name_ref) | ||
283 | { | 217 | { |
284 | let mut vec = vec![]; | 218 | let scope = fn_descr.scope(&*self.db); |
285 | vec.push(( | 219 | // First try to resolve the symbol locally |
286 | position.file_id, | 220 | return if let Some(entry) = scope.resolve_local_name(name_ref) { |
287 | FileSymbol { | 221 | let mut vec = vec![]; |
288 | name, | 222 | vec.push(( |
289 | node_range: range, | 223 | position.file_id, |
290 | kind: NAME, | 224 | FileSymbol { |
291 | }, | 225 | name: entry.name().clone(), |
292 | )); | 226 | node_range: entry.ptr().range(), |
293 | Ok(vec) | 227 | kind: NAME, |
294 | } else { | 228 | }, |
295 | // If that fails try the index based approach. | 229 | )); |
296 | self.index_resolve(name_ref) | 230 | Ok(vec) |
297 | }; | 231 | } else { |
232 | // If that fails try the index based approach. | ||
233 | self.index_resolve(name_ref) | ||
234 | }; | ||
235 | } | ||
298 | } | 236 | } |
299 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { | 237 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { |
300 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { | 238 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { |
301 | if module.has_semi() { | 239 | if module.has_semi() { |
302 | let file_ids = self.resolve_module(&*module_tree, position.file_id, module); | 240 | let parent_module = |
303 | 241 | hir::Module::guess_from_file_id(&*self.db, position.file_id)?; | |
304 | let res = file_ids | 242 | let child_name = module.name(); |
305 | .into_iter() | 243 | match (parent_module, child_name) { |
306 | .map(|id| { | 244 | (Some(parent_module), Some(child_name)) => { |
307 | let name = module | 245 | if let Some(child) = parent_module.child(&child_name.text()) { |
308 | .name() | 246 | let file_id = child.source().file_id(); |
309 | .map(|n| n.text()) | 247 | let symbol = FileSymbol { |
310 | .unwrap_or_else(|| SmolStr::new("")); | 248 | name: child_name.text(), |
311 | let symbol = FileSymbol { | 249 | node_range: TextRange::offset_len(0.into(), 0.into()), |
312 | name, | 250 | kind: MODULE, |
313 | node_range: TextRange::offset_len(0.into(), 0.into()), | 251 | }; |
314 | kind: MODULE, | 252 | return Ok(vec![(file_id, symbol)]); |
315 | }; | 253 | } |
316 | (id, symbol) | 254 | } |
317 | }) | 255 | _ => (), |
318 | .collect(); | 256 | } |
319 | |||
320 | return Ok(res); | ||
321 | } | 257 | } |
322 | } | 258 | } |
323 | } | 259 | } |
@@ -325,32 +261,42 @@ impl AnalysisImpl { | |||
325 | } | 261 | } |
326 | 262 | ||
327 | pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { | 263 | pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { |
328 | let file = self.db.file_syntax(position.file_id); | 264 | let file = self.db.source_file(position.file_id); |
329 | let syntax = file.syntax(); | ||
330 | |||
331 | // Find the binding associated with the offset | 265 | // Find the binding associated with the offset |
332 | let maybe_binding = | 266 | let (binding, descr) = match find_binding(&self.db, &file, position) { |
333 | find_node_at_offset::<ast::BindPat>(syntax, position.offset).or_else(|| { | ||
334 | let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?; | ||
335 | let resolved = resolve_local_name(&self.db, position.file_id, name_ref)?; | ||
336 | find_node_at_offset::<ast::BindPat>(syntax, resolved.1.end()) | ||
337 | }); | ||
338 | |||
339 | let binding = match maybe_binding { | ||
340 | None => return Vec::new(), | 267 | None => return Vec::new(), |
341 | Some(it) => it, | 268 | Some(it) => it, |
342 | }; | 269 | }; |
343 | 270 | ||
344 | let decl = DeclarationDescriptor::new(binding); | 271 | let mut ret = vec![(position.file_id, binding.syntax().range())]; |
345 | |||
346 | let mut ret = vec![(position.file_id, decl.range)]; | ||
347 | ret.extend( | 272 | ret.extend( |
348 | decl.find_all_refs() | 273 | descr |
274 | .scope(&*self.db) | ||
275 | .find_all_refs(binding) | ||
349 | .into_iter() | 276 | .into_iter() |
350 | .map(|ref_desc| (position.file_id, ref_desc.range)), | 277 | .map(|ref_desc| (position.file_id, ref_desc.range)), |
351 | ); | 278 | ); |
352 | 279 | ||
353 | ret | 280 | return ret; |
281 | |||
282 | fn find_binding<'a>( | ||
283 | db: &db::RootDatabase, | ||
284 | source_file: &'a SourceFileNode, | ||
285 | position: FilePosition, | ||
286 | ) -> Option<(ast::BindPat<'a>, hir::Function)> { | ||
287 | let syntax = source_file.syntax(); | ||
288 | if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) { | ||
289 | let descr = hir::Function::guess_for_bind_pat(db, position.file_id, binding)?; | ||
290 | return Some((binding, descr)); | ||
291 | }; | ||
292 | let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?; | ||
293 | let descr = hir::Function::guess_for_name_ref(db, position.file_id, name_ref)?; | ||
294 | let scope = descr.scope(db); | ||
295 | let resolved = scope.resolve_local_name(name_ref)?; | ||
296 | let resolved = resolved.ptr().resolve(source_file); | ||
297 | let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?; | ||
298 | Some((binding, descr)) | ||
299 | } | ||
354 | } | 300 | } |
355 | 301 | ||
356 | pub fn doc_comment_for( | 302 | pub fn doc_comment_for( |
@@ -358,14 +304,13 @@ impl AnalysisImpl { | |||
358 | file_id: FileId, | 304 | file_id: FileId, |
359 | symbol: FileSymbol, | 305 | symbol: FileSymbol, |
360 | ) -> Cancelable<Option<String>> { | 306 | ) -> Cancelable<Option<String>> { |
361 | let file = self.db.file_syntax(file_id); | 307 | let file = self.db.source_file(file_id); |
362 | 308 | ||
363 | Ok(symbol.docs(&file)) | 309 | Ok(symbol.docs(&file)) |
364 | } | 310 | } |
365 | 311 | ||
366 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 312 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { |
367 | let module_tree = self.module_tree(file_id)?; | 313 | let syntax = self.db.source_file(file_id); |
368 | let syntax = self.db.file_syntax(file_id); | ||
369 | 314 | ||
370 | let mut res = ra_editor::diagnostics(&syntax) | 315 | let mut res = ra_editor::diagnostics(&syntax) |
371 | .into_iter() | 316 | .into_iter() |
@@ -375,8 +320,8 @@ impl AnalysisImpl { | |||
375 | fix: None, | 320 | fix: None, |
376 | }) | 321 | }) |
377 | .collect::<Vec<_>>(); | 322 | .collect::<Vec<_>>(); |
378 | if let Some(m) = module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) { | 323 | if let Some(m) = hir::Module::guess_from_file_id(&*self.db, file_id)? { |
379 | for (name_node, problem) in m.problems(&module_tree, &*self.db) { | 324 | for (name_node, problem) in m.problems(&*self.db) { |
380 | let diag = match problem { | 325 | let diag = match problem { |
381 | Problem::UnresolvedModule { candidate } => { | 326 | Problem::UnresolvedModule { candidate } => { |
382 | let create_file = FileSystemEdit::CreateFile { | 327 | let create_file = FileSystemEdit::CreateFile { |
@@ -452,27 +397,22 @@ impl AnalysisImpl { | |||
452 | pub fn resolve_callable( | 397 | pub fn resolve_callable( |
453 | &self, | 398 | &self, |
454 | position: FilePosition, | 399 | position: FilePosition, |
455 | ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> { | 400 | ) -> Cancelable<Option<(FnSignatureInfo, Option<usize>)>> { |
456 | let file = self.db.file_syntax(position.file_id); | 401 | let file = self.db.source_file(position.file_id); |
457 | let syntax = file.syntax(); | 402 | let syntax = file.syntax(); |
458 | 403 | ||
459 | // Find the calling expression and it's NameRef | 404 | // Find the calling expression and it's NameRef |
460 | let calling_node = match FnCallNode::with_node(syntax, position.offset) { | 405 | let calling_node = ctry!(FnCallNode::with_node(syntax, position.offset)); |
461 | Some(node) => node, | 406 | let name_ref = ctry!(calling_node.name_ref()); |
462 | None => return Ok(None), | ||
463 | }; | ||
464 | let name_ref = match calling_node.name_ref() { | ||
465 | Some(name) => name, | ||
466 | None => return Ok(None), | ||
467 | }; | ||
468 | 407 | ||
469 | // Resolve the function's NameRef (NOTE: this isn't entirely accurate). | 408 | // Resolve the function's NameRef (NOTE: this isn't entirely accurate). |
470 | let file_symbols = self.index_resolve(name_ref)?; | 409 | let file_symbols = self.index_resolve(name_ref)?; |
471 | for (fn_fiel_id, fs) in file_symbols { | 410 | for (fn_file_id, fs) in file_symbols { |
472 | if fs.kind == FN_DEF { | 411 | if fs.kind == FN_DEF { |
473 | let fn_file = self.db.file_syntax(fn_fiel_id); | 412 | let fn_file = self.db.source_file(fn_file_id); |
474 | if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) { | 413 | if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) { |
475 | if let Some(descriptor) = FnDescriptor::new(fn_def) { | 414 | let descr = hir::Function::guess_from_source(&*self.db, fn_file_id, fn_def); |
415 | if let Some(descriptor) = descr.signature_info(&*self.db) { | ||
476 | // If we have a calling expression let's find which argument we are on | 416 | // If we have a calling expression let's find which argument we are on |
477 | let mut current_parameter = None; | 417 | let mut current_parameter = None; |
478 | 418 | ||
@@ -526,27 +466,6 @@ impl AnalysisImpl { | |||
526 | query.limit(4); | 466 | query.limit(4); |
527 | self.world_symbols(query) | 467 | self.world_symbols(query) |
528 | } | 468 | } |
529 | |||
530 | fn resolve_module( | ||
531 | &self, | ||
532 | module_tree: &ModuleTree, | ||
533 | file_id: FileId, | ||
534 | module: ast::Module, | ||
535 | ) -> Vec<FileId> { | ||
536 | let name = match module.name() { | ||
537 | Some(name) => name.text(), | ||
538 | None => return Vec::new(), | ||
539 | }; | ||
540 | let module_id = match module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) { | ||
541 | Some(id) => id, | ||
542 | None => return Vec::new(), | ||
543 | }; | ||
544 | module_id | ||
545 | .child(module_tree, name.as_str()) | ||
546 | .and_then(|it| it.source(&module_tree).as_file()) | ||
547 | .into_iter() | ||
548 | .collect() | ||
549 | } | ||
550 | } | 469 | } |
551 | 470 | ||
552 | impl SourceChange { | 471 | impl SourceChange { |
@@ -566,16 +485,6 @@ impl SourceChange { | |||
566 | } | 485 | } |
567 | } | 486 | } |
568 | 487 | ||
569 | impl CrateGraph { | ||
570 | fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { | ||
571 | let (&crate_id, _) = self | ||
572 | .crate_roots | ||
573 | .iter() | ||
574 | .find(|(_crate_id, &root_id)| root_id == file_id)?; | ||
575 | Some(crate_id) | ||
576 | } | ||
577 | } | ||
578 | |||
579 | enum FnCallNode<'a> { | 488 | enum FnCallNode<'a> { |
580 | CallExpr(ast::CallExpr<'a>), | 489 | CallExpr(ast::CallExpr<'a>), |
581 | MethodCallExpr(ast::MethodCallExpr<'a>), | 490 | MethodCallExpr(ast::MethodCallExpr<'a>), |
@@ -614,16 +523,3 @@ impl<'a> FnCallNode<'a> { | |||
614 | } | 523 | } |
615 | } | 524 | } |
616 | } | 525 | } |
617 | |||
618 | fn resolve_local_name( | ||
619 | db: &db::RootDatabase, | ||
620 | file_id: FileId, | ||
621 | name_ref: ast::NameRef, | ||
622 | ) -> Option<(SmolStr, TextRange)> { | ||
623 | let fn_def = name_ref.syntax().ancestors().find_map(ast::FnDef::cast)?; | ||
624 | let fn_id = FnId::new(file_id, fn_def); | ||
625 | let scopes = db.fn_scopes(fn_id); | ||
626 | let scope_entry = crate::descriptors::function::resolve_local_name(name_ref, &scopes)?; | ||
627 | let syntax = db.resolve_syntax_ptr(scope_entry.ptr().into_global(file_id)); | ||
628 | Some((scope_entry.name().clone(), syntax.range())) | ||
629 | } | ||