aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/imp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r--crates/ra_analysis/src/imp.rs136
1 files changed, 50 insertions, 86 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 812fed32d..e1493bdaa 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -21,7 +21,7 @@ use crate::{
21 db::{self, FileSyntaxQuery, SyntaxDatabase}, 21 db::{self, FileSyntaxQuery, SyntaxDatabase},
22 descriptors::{ 22 descriptors::{
23 function::{FnDescriptor, FnId}, 23 function::{FnDescriptor, FnId},
24 module::{ModuleSource, ModuleTree, Problem}, 24 module::{ModuleDescriptor, Problem},
25 DeclarationDescriptor, DescriptorDatabase, 25 DeclarationDescriptor, DescriptorDatabase,
26 }, 26 },
27 input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, 27 input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE},
@@ -216,52 +216,41 @@ impl AnalysisImpl {
216 .sweep(salsa::SweepStrategy::default().discard_values()); 216 .sweep(salsa::SweepStrategy::default().discard_values());
217 Ok(query.search(&buf)) 217 Ok(query.search(&buf))
218 } 218 }
219 fn module_tree(&self, file_id: FileId) -> Cancelable<Arc<ModuleTree>> { 219 /// This return `Vec`: a module may be included from several places. We
220 let source_root = self.db.file_source_root(file_id); 220 /// 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)>> { 221 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
224 let module_tree = self.module_tree(position.file_id)?; 222 let descr = match ModuleDescriptor::guess_from_position(&*self.db, position)? {
225 let file = self.db.file_syntax(position.file_id); 223 None => return Ok(Vec::new()),
226 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) 224 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 }; 225 };
231 226 let (file_id, decl) = match descr.parent_link_source(&*self.db) {
232 let res = module_tree 227 None => return Ok(Vec::new()),
233 .modules_for_source(module_source) 228 Some(it) => it,
234 .into_iter() 229 };
235 .filter_map(|module_id| { 230 let decl = decl.borrowed();
236 let link = module_id.parent_link(&module_tree)?; 231 let decl_name = decl.name().unwrap();
237 let file_id = link.owner(&module_tree).source(&module_tree).file_id(); 232 let sym = FileSymbol {
238 let decl = link.bind_source(&module_tree, &*self.db); 233 name: decl_name.text(),
239 let decl = decl.borrowed(); 234 node_range: decl_name.syntax().range(),
240 235 kind: MODULE,
241 let decl_name = decl.name().unwrap(); 236 };
242 237 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 } 238 }
239 /// Returns `Vec` for the same reason as `parent_module`
253 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 240 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
254 let module_tree = self.module_tree(file_id)?; 241 let descr = match ModuleDescriptor::guess_from_file_id(&*self.db, file_id)? {
255 let crate_graph = self.db.crate_graph(); 242 None => return Ok(Vec::new()),
256 let res = module_tree 243 Some(it) => it,
257 .modules_for_source(ModuleSource::SourceFile(file_id)) 244 };
258 .into_iter() 245 let root = descr.crate_root();
259 .map(|it| it.root(&module_tree)) 246 let file_id = root
260 .filter_map(|it| it.source(&module_tree).as_file()) 247 .source()
261 .filter_map(|it| crate_graph.crate_id_for_crate_root(it)) 248 .as_file()
262 .collect(); 249 .expect("root module always has a file as a source");
263 250
264 Ok(res) 251 let crate_graph = self.db.crate_graph();
252 let crate_id = crate_graph.crate_id_for_crate_root(file_id);
253 Ok(crate_id.into_iter().collect())
265 } 254 }
266 pub fn crate_root(&self, crate_id: CrateId) -> FileId { 255 pub fn crate_root(&self, crate_id: CrateId) -> FileId {
267 self.db.crate_graph().crate_roots[&crate_id] 256 self.db.crate_graph().crate_roots[&crate_id]
@@ -273,7 +262,6 @@ impl AnalysisImpl {
273 &self, 262 &self,
274 position: FilePosition, 263 position: FilePosition,
275 ) -> Cancelable<Vec<(FileId, FileSymbol)>> { 264 ) -> Cancelable<Vec<(FileId, FileSymbol)>> {
276 let module_tree = self.module_tree(position.file_id)?;
277 let file = self.db.file_syntax(position.file_id); 265 let file = self.db.file_syntax(position.file_id);
278 let syntax = file.syntax(); 266 let syntax = file.syntax();
279 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { 267 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
@@ -299,25 +287,23 @@ impl AnalysisImpl {
299 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { 287 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) { 288 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
301 if module.has_semi() { 289 if module.has_semi() {
302 let file_ids = self.resolve_module(&*module_tree, position.file_id, module); 290 let parent_module =
303 291 ModuleDescriptor::guess_from_file_id(&*self.db, position.file_id)?;
304 let res = file_ids 292 let child_name = module.name();
305 .into_iter() 293 match (parent_module, child_name) {
306 .map(|id| { 294 (Some(parent_module), Some(child_name)) => {
307 let name = module 295 if let Some(child) = parent_module.child(&child_name.text()) {
308 .name() 296 let file_id = child.source().file_id();
309 .map(|n| n.text()) 297 let symbol = FileSymbol {
310 .unwrap_or_else(|| SmolStr::new("")); 298 name: child_name.text(),
311 let symbol = FileSymbol { 299 node_range: TextRange::offset_len(0.into(), 0.into()),
312 name, 300 kind: MODULE,
313 node_range: TextRange::offset_len(0.into(), 0.into()), 301 };
314 kind: MODULE, 302 return Ok(vec![(file_id, symbol)]);
315 }; 303 }
316 (id, symbol) 304 }
317 }) 305 _ => (),
318 .collect(); 306 }
319
320 return Ok(res);
321 } 307 }
322 } 308 }
323 } 309 }
@@ -364,7 +350,6 @@ impl AnalysisImpl {
364 } 350 }
365 351
366 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { 352 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
367 let module_tree = self.module_tree(file_id)?;
368 let syntax = self.db.file_syntax(file_id); 353 let syntax = self.db.file_syntax(file_id);
369 354
370 let mut res = ra_editor::diagnostics(&syntax) 355 let mut res = ra_editor::diagnostics(&syntax)
@@ -375,8 +360,8 @@ impl AnalysisImpl {
375 fix: None, 360 fix: None,
376 }) 361 })
377 .collect::<Vec<_>>(); 362 .collect::<Vec<_>>();
378 if let Some(m) = module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) { 363 if let Some(m) = ModuleDescriptor::guess_from_file_id(&*self.db, file_id)? {
379 for (name_node, problem) in m.problems(&module_tree, &*self.db) { 364 for (name_node, problem) in m.problems(&*self.db) {
380 let diag = match problem { 365 let diag = match problem {
381 Problem::UnresolvedModule { candidate } => { 366 Problem::UnresolvedModule { candidate } => {
382 let create_file = FileSystemEdit::CreateFile { 367 let create_file = FileSystemEdit::CreateFile {
@@ -526,27 +511,6 @@ impl AnalysisImpl {
526 query.limit(4); 511 query.limit(4);
527 self.world_symbols(query) 512 self.world_symbols(query)
528 } 513 }
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} 514}
551 515
552impl SourceChange { 516impl SourceChange {