diff options
author | Ekaterina Babshukova <[email protected]> | 2019-10-10 16:51:51 +0100 |
---|---|---|
committer | Ekaterina Babshukova <[email protected]> | 2019-10-22 21:47:31 +0100 |
commit | 5b03773fbeea55d86f64e5fb69a0d0f1d6a4f7e8 (patch) | |
tree | 1f3ce5c71343535ae0ca0751982a1d0f89480e45 /crates/ra_ide_api/src/search_scope.rs | |
parent | 01853e8d6c6f4b44801c74f4fcdef735d9e77b48 (diff) |
implement search of references
Diffstat (limited to 'crates/ra_ide_api/src/search_scope.rs')
-rw-r--r-- | crates/ra_ide_api/src/search_scope.rs | 77 |
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 @@ | |||
1 | use hir::{DefWithBody, HasSource, ModuleSource}; | 1 | use hir::{ |
2 | source_binder::ReferenceDescriptor, DefWithBody, HasSource, ModuleSource, SourceAnalyzer, | ||
3 | }; | ||
2 | use ra_db::{FileId, SourceDatabase}; | 4 | use ra_db::{FileId, SourceDatabase}; |
3 | use ra_syntax::{AstNode, TextRange}; | 5 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, TextRange, TextUnit}; |
4 | 6 | ||
5 | use crate::{ | 7 | use crate::{ |
6 | db::RootDatabase, | 8 | db::RootDatabase, |
7 | name_kind::{Declaration, NameKind}, | 9 | name_kind::{classify_name_ref, Definition, NameKind}, |
8 | }; | 10 | }; |
9 | 11 | ||
10 | pub struct SearchScope { | 12 | pub(crate) struct SearchScope { |
11 | pub scope: Vec<(FileId, Option<TextRange>)>, | 13 | pub scope: Vec<(FileId, Option<TextRange>)>, |
12 | } | 14 | } |
13 | 15 | ||
14 | impl Declaration { | 16 | pub(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 | |||
65 | impl 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 | } |