diff options
author | Ekaterina Babshukova <[email protected]> | 2019-10-22 21:46:53 +0100 |
---|---|---|
committer | Ekaterina Babshukova <[email protected]> | 2019-10-22 22:35:06 +0100 |
commit | decfd28bd14b56befa17257694caacc57a090939 (patch) | |
tree | cdf5a5b39600b41a9eee301b9760cde1282aeb33 /crates/ra_ide_api/src/references | |
parent | b5a3ee93e24931c8bba628ddc7be4f098a19a326 (diff) |
some fixes, add docs
Diffstat (limited to 'crates/ra_ide_api/src/references')
-rw-r--r-- | crates/ra_ide_api/src/references/classify.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/name_definition.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/search_scope.rs | 81 |
3 files changed, 47 insertions, 47 deletions
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 3beab9861..c8daff9b1 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs | |||
@@ -1,8 +1,9 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Functions that are used to classify an element from its definition or reference. |
2 | 2 | ||
3 | use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; | 3 | use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; |
4 | use ra_db::FileId; | 4 | use ra_db::FileId; |
5 | use ra_syntax::{ast, match_ast, AstNode, AstPtr}; | 5 | use ra_syntax::{ast, match_ast, AstNode, AstPtr}; |
6 | use test_utils::tested_by; | ||
6 | 7 | ||
7 | use super::{ | 8 | use super::{ |
8 | name_definition::{from_assoc_item, from_module_def, from_pat, from_struct_field}, | 9 | name_definition::{from_assoc_item, from_module_def, from_pat, from_struct_field}, |
@@ -111,18 +112,21 @@ pub(crate) fn classify_name_ref( | |||
111 | let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); | 112 | let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); |
112 | 113 | ||
113 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 114 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
115 | tested_by!(goto_definition_works_for_methods); | ||
114 | if let Some(func) = analyzer.resolve_method_call(&method_call) { | 116 | if let Some(func) = analyzer.resolve_method_call(&method_call) { |
115 | return Some(from_assoc_item(db, func.into())); | 117 | return Some(from_assoc_item(db, func.into())); |
116 | } | 118 | } |
117 | } | 119 | } |
118 | 120 | ||
119 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 121 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
122 | tested_by!(goto_definition_works_for_fields); | ||
120 | if let Some(field) = analyzer.resolve_field(&field_expr) { | 123 | if let Some(field) = analyzer.resolve_field(&field_expr) { |
121 | return Some(from_struct_field(db, field)); | 124 | return Some(from_struct_field(db, field)); |
122 | } | 125 | } |
123 | } | 126 | } |
124 | 127 | ||
125 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | 128 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
129 | tested_by!(goto_definition_works_for_record_fields); | ||
126 | if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { | 130 | if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { |
127 | let variant_def = analyzer.resolve_record_literal(&record_lit)?; | 131 | let variant_def = analyzer.resolve_record_literal(&record_lit)?; |
128 | let hir_path = Path::from_name_ref(name_ref); | 132 | let hir_path = Path::from_name_ref(name_ref); |
@@ -139,6 +143,7 @@ pub(crate) fn classify_name_ref( | |||
139 | let visibility = None; | 143 | let visibility = None; |
140 | 144 | ||
141 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 145 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
146 | tested_by!(goto_definition_works_for_macros); | ||
142 | if let Some(macro_def) = analyzer.resolve_macro_call(db, ¯o_call) { | 147 | if let Some(macro_def) = analyzer.resolve_macro_call(db, ¯o_call) { |
143 | let kind = NameKind::Macro(macro_def); | 148 | let kind = NameKind::Macro(macro_def); |
144 | return Some(NameDefinition { kind, container, visibility }); | 149 | return Some(NameDefinition { kind, container, visibility }); |
@@ -152,7 +157,6 @@ pub(crate) fn classify_name_ref( | |||
152 | AssocItem(item) => Some(from_assoc_item(db, item)), | 157 | AssocItem(item) => Some(from_assoc_item(db, item)), |
153 | LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat), | 158 | LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat), |
154 | LocalBinding(Either::B(par)) => { | 159 | LocalBinding(Either::B(par)) => { |
155 | // Not really supported | ||
156 | let kind = NameKind::SelfParam(par); | 160 | let kind = NameKind::SelfParam(par); |
157 | Some(NameDefinition { kind, container, visibility }) | 161 | Some(NameDefinition { kind, container, visibility }) |
158 | } | 162 | } |
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs index 723d97237..4580bc789 100644 --- a/crates/ra_ide_api/src/references/name_definition.rs +++ b/crates/ra_ide_api/src/references/name_definition.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! `NameDefinition` keeps information about the element we want to search references for. |
2 | //! The element is represented by `NameKind`. It's located inside some `container` and | ||
3 | //! has a `visibility`, which defines a search scope. | ||
4 | //! Note that the reference search is possible for not all of the classified items. | ||
2 | 5 | ||
3 | use hir::{ | 6 | use hir::{ |
4 | db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, | 7 | db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, |
diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs index 8495a92a5..5cb69b8fc 100644 --- a/crates/ra_ide_api/src/references/search_scope.rs +++ b/crates/ra_ide_api/src/references/search_scope.rs | |||
@@ -1,72 +1,66 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Generally, `search_scope` returns files that might contain references for the element. |
2 | 2 | //! For `pub(crate)` things it's a crate, for `pub` things it's a crate and dependant crates. | |
3 | use std::collections::HashSet; | 3 | //! In some cases, the location of the references is known to within a `TextRange`, |
4 | //! e.g. for things like local variables. | ||
4 | 5 | ||
5 | use hir::{DefWithBody, HasSource, ModuleSource}; | 6 | use hir::{DefWithBody, HasSource, ModuleSource}; |
6 | use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; | 7 | use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; |
7 | use ra_syntax::{AstNode, TextRange}; | 8 | use ra_syntax::{AstNode, TextRange}; |
9 | use rustc_hash::FxHashSet; | ||
8 | 10 | ||
9 | use crate::db::RootDatabase; | 11 | use crate::db::RootDatabase; |
10 | 12 | ||
11 | use super::{NameDefinition, NameKind}; | 13 | use super::{NameDefinition, NameKind}; |
12 | 14 | ||
13 | impl NameDefinition { | 15 | impl NameDefinition { |
14 | pub(crate) fn search_scope(&self, db: &RootDatabase) -> HashSet<(FileId, Option<TextRange>)> { | 16 | pub(crate) fn search_scope(&self, db: &RootDatabase) -> FxHashSet<(FileId, Option<TextRange>)> { |
15 | let module_src = self.container.definition_source(db); | 17 | let module_src = self.container.definition_source(db); |
16 | let file_id = module_src.file_id.original_file(db); | 18 | let file_id = module_src.file_id.original_file(db); |
17 | 19 | ||
18 | if let NameKind::Pat((def, _)) = self.kind { | 20 | if let NameKind::Pat((def, _)) = self.kind { |
21 | let mut res = FxHashSet::default(); | ||
19 | let range = match def { | 22 | let range = match def { |
20 | DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), | 23 | DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), |
21 | DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), | 24 | DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), |
22 | DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), | 25 | DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), |
23 | }; | 26 | }; |
24 | return [(file_id, Some(range))].iter().cloned().collect(); | 27 | res.insert((file_id, Some(range))); |
28 | return res; | ||
25 | } | 29 | } |
26 | 30 | ||
27 | if let Some(ref vis) = self.visibility { | 31 | let vis = |
28 | let vis = vis.syntax().to_string(); | 32 | self.visibility.as_ref().map(|v| v.syntax().to_string()).unwrap_or("".to_string()); |
29 | |||
30 | // FIXME: add "pub(in path)" | ||
31 | |||
32 | if vis.as_str() == "pub(super)" { | ||
33 | if let Some(parent_module) = self.container.parent(db) { | ||
34 | let mut files = HashSet::new(); | ||
35 | 33 | ||
36 | let parent_src = parent_module.definition_source(db); | 34 | if vis.as_str() == "pub(super)" { |
37 | let file_id = parent_src.file_id.original_file(db); | 35 | if let Some(parent_module) = self.container.parent(db) { |
36 | let mut files = FxHashSet::default(); | ||
37 | let parent_src = parent_module.definition_source(db); | ||
38 | let file_id = parent_src.file_id.original_file(db); | ||
38 | 39 | ||
39 | match parent_src.ast { | 40 | match parent_src.ast { |
40 | ModuleSource::Module(m) => { | 41 | ModuleSource::Module(m) => { |
41 | let range = Some(m.syntax().text_range()); | 42 | let range = Some(m.syntax().text_range()); |
42 | files.insert((file_id, range)); | 43 | files.insert((file_id, range)); |
43 | } | 44 | } |
44 | ModuleSource::SourceFile(_) => { | 45 | ModuleSource::SourceFile(_) => { |
45 | files.insert((file_id, None)); | 46 | files.insert((file_id, None)); |
46 | files.extend( | 47 | files.extend(parent_module.children(db).map(|m| { |
47 | parent_module | 48 | let src = m.definition_source(db); |
48 | .children(db) | 49 | (src.file_id.original_file(db), None) |
49 | .map(|m| { | 50 | })); |
50 | let src = m.definition_source(db); | ||
51 | (src.file_id.original_file(db), None) | ||
52 | }) | ||
53 | .collect::<HashSet<_>>(), | ||
54 | ); | ||
55 | } | ||
56 | } | 51 | } |
57 | return files; | ||
58 | } else { | ||
59 | let range = match module_src.ast { | ||
60 | ModuleSource::Module(m) => Some(m.syntax().text_range()), | ||
61 | ModuleSource::SourceFile(_) => None, | ||
62 | }; | ||
63 | return [(file_id, range)].iter().cloned().collect(); | ||
64 | } | 52 | } |
53 | return files; | ||
65 | } | 54 | } |
55 | } | ||
66 | 56 | ||
57 | if vis.as_str() != "" { | ||
67 | let source_root_id = db.file_source_root(file_id); | 58 | let source_root_id = db.file_source_root(file_id); |
68 | let source_root = db.source_root(source_root_id); | 59 | let source_root = db.source_root(source_root_id); |
69 | let mut files = source_root.walk().map(|id| (id.into(), None)).collect::<HashSet<_>>(); | 60 | let mut files = |
61 | source_root.walk().map(|id| (id.into(), None)).collect::<FxHashSet<_>>(); | ||
62 | |||
63 | // FIXME: add "pub(in path)" | ||
70 | 64 | ||
71 | if vis.as_str() == "pub(crate)" { | 65 | if vis.as_str() == "pub(crate)" { |
72 | return files; | 66 | return files; |
@@ -74,10 +68,8 @@ impl NameDefinition { | |||
74 | if vis.as_str() == "pub" { | 68 | if vis.as_str() == "pub" { |
75 | let krate = self.container.krate(db).unwrap(); | 69 | let krate = self.container.krate(db).unwrap(); |
76 | let crate_graph = db.crate_graph(); | 70 | let crate_graph = db.crate_graph(); |
77 | |||
78 | for crate_id in crate_graph.iter() { | 71 | for crate_id in crate_graph.iter() { |
79 | let mut crate_deps = crate_graph.dependencies(crate_id); | 72 | let mut crate_deps = crate_graph.dependencies(crate_id); |
80 | |||
81 | if crate_deps.any(|dep| dep.crate_id() == krate.crate_id()) { | 73 | if crate_deps.any(|dep| dep.crate_id() == krate.crate_id()) { |
82 | let root_file = crate_graph.crate_root(crate_id); | 74 | let root_file = crate_graph.crate_root(crate_id); |
83 | let source_root_id = db.file_source_root(root_file); | 75 | let source_root_id = db.file_source_root(root_file); |
@@ -85,15 +77,16 @@ impl NameDefinition { | |||
85 | files.extend(source_root.walk().map(|id| (id.into(), None))); | 77 | files.extend(source_root.walk().map(|id| (id.into(), None))); |
86 | } | 78 | } |
87 | } | 79 | } |
88 | |||
89 | return files; | 80 | return files; |
90 | } | 81 | } |
91 | } | 82 | } |
92 | 83 | ||
84 | let mut res = FxHashSet::default(); | ||
93 | let range = match module_src.ast { | 85 | let range = match module_src.ast { |
94 | ModuleSource::Module(m) => Some(m.syntax().text_range()), | 86 | ModuleSource::Module(m) => Some(m.syntax().text_range()), |
95 | ModuleSource::SourceFile(_) => None, | 87 | ModuleSource::SourceFile(_) => None, |
96 | }; | 88 | }; |
97 | [(file_id, range)].iter().cloned().collect() | 89 | res.insert((file_id, range)); |
90 | res | ||
98 | } | 91 | } |
99 | } | 92 | } |