aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/search_scope.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/search_scope.rs')
-rw-r--r--crates/ra_ide_api/src/search_scope.rs77
1 files changed, 63 insertions, 14 deletions
diff --git a/crates/ra_ide_api/src/search_scope.rs b/crates/ra_ide_api/src/search_scope.rs
index 1cf1aed37..9fcbdcc3a 100644
--- a/crates/ra_ide_api/src/search_scope.rs
+++ b/crates/ra_ide_api/src/search_scope.rs
@@ -1,18 +1,69 @@
1use hir::{DefWithBody, HasSource, ModuleSource}; 1use hir::{
2 source_binder::ReferenceDescriptor, DefWithBody, HasSource, ModuleSource, SourceAnalyzer,
3};
2use ra_db::{FileId, SourceDatabase}; 4use ra_db::{FileId, SourceDatabase};
3use ra_syntax::{AstNode, TextRange}; 5use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, TextRange, TextUnit};
4 6
5use crate::{ 7use crate::{
6 db::RootDatabase, 8 db::RootDatabase,
7 name_kind::{Declaration, NameKind}, 9 name_kind::{classify_name_ref, Definition, NameKind},
8}; 10};
9 11
10pub struct SearchScope { 12pub(crate) struct SearchScope {
11 pub scope: Vec<(FileId, Option<TextRange>)>, 13 pub scope: Vec<(FileId, Option<TextRange>)>,
12} 14}
13 15
14impl Declaration { 16pub(crate) fn find_refs(
15 pub fn scope(self, db: &RootDatabase) -> Option<SearchScope> { 17 db: &RootDatabase,
18 def: Definition,
19 name: String,
20) -> Vec<ReferenceDescriptor> {
21 let pat = name.as_str();
22 let scope = def.scope(db).scope;
23 let mut refs = vec![];
24
25 let is_match = |file_id: FileId, name_ref: &ast::NameRef| -> bool {
26 let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
27 let classified = classify_name_ref(db, file_id, &analyzer, &name_ref);
28 if let Some(d) = classified {
29 d == def
30 } else {
31 false
32 }
33 };
34
35 for (file_id, text_range) in scope {
36 let text = db.file_text(file_id);
37 let parse = SourceFile::parse(&text);
38 let syntax = parse.tree().syntax().clone();
39
40 for (idx, _) in text.match_indices(pat) {
41 let offset = TextUnit::from_usize(idx);
42 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, offset) {
43 let name_range = name_ref.syntax().text_range();
44
45 if let Some(range) = text_range {
46 if name_range.is_subrange(&range) && is_match(file_id, &name_ref) {
47 refs.push(ReferenceDescriptor {
48 name: name_ref.text().to_string(),
49 range: name_ref.syntax().text_range(),
50 });
51 }
52 } else if is_match(file_id, &name_ref) {
53 refs.push(ReferenceDescriptor {
54 name: name_ref.text().to_string(),
55 range: name_ref.syntax().text_range(),
56 });
57 }
58 }
59 }
60 }
61
62 return refs;
63}
64
65impl Definition {
66 pub fn scope(&self, db: &RootDatabase) -> SearchScope {
16 let module_src = self.container.definition_source(db); 67 let module_src = self.container.definition_source(db);
17 let file_id = module_src.file_id.original_file(db); 68 let file_id = module_src.file_id.original_file(db);
18 69
@@ -22,16 +73,16 @@ impl Declaration {
22 DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), 73 DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(),
23 DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), 74 DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(),
24 }; 75 };
25 return Some(SearchScope { scope: vec![(file_id, Some(range))] }); 76 return SearchScope { scope: vec![(file_id, Some(range))] };
26 } 77 }
27 78
28 if let Some(vis) = self.visibility { 79 if let Some(ref vis) = self.visibility {
29 let source_root_id = db.file_source_root(file_id); 80 let source_root_id = db.file_source_root(file_id);
30 let source_root = db.source_root(source_root_id); 81 let source_root = db.source_root(source_root_id);
31 let mut files = source_root.walk().map(|id| (id.into(), None)).collect::<Vec<_>>(); 82 let mut files = source_root.walk().map(|id| (id.into(), None)).collect::<Vec<_>>();
32 83
33 if vis.syntax().text() == "pub(crate)" { 84 if vis.syntax().text() == "pub(crate)" {
34 return Some(SearchScope { scope: files }); 85 return SearchScope { scope: files };
35 } 86 }
36 if vis.syntax().text() == "pub" { 87 if vis.syntax().text() == "pub" {
37 let krate = self.container.krate(db).unwrap(); 88 let krate = self.container.krate(db).unwrap();
@@ -48,17 +99,15 @@ impl Declaration {
48 } 99 }
49 } 100 }
50 101
51 return Some(SearchScope { scope: files }); 102 return SearchScope { scope: files };
52 } 103 }
53 // FIXME: extend to "pub(super)" and "pub(in path)" cases, 104 // FIXME: "pub(super)", "pub(in path)"
54 // then remove `Option`
55 return None;
56 } 105 }
57 106
58 let range = match module_src.ast { 107 let range = match module_src.ast {
59 ModuleSource::Module(m) => Some(m.syntax().text_range()), 108 ModuleSource::Module(m) => Some(m.syntax().text_range()),
60 ModuleSource::SourceFile(_) => None, 109 ModuleSource::SourceFile(_) => None,
61 }; 110 };
62 Some(SearchScope { scope: vec![(file_id, range)] }) 111 SearchScope { scope: vec![(file_id, range)] }
63 } 112 }
64} 113}