aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/references
diff options
context:
space:
mode:
authorEkaterina Babshukova <[email protected]>2019-10-22 21:46:53 +0100
committerEkaterina Babshukova <[email protected]>2019-10-22 22:35:06 +0100
commitdecfd28bd14b56befa17257694caacc57a090939 (patch)
treecdf5a5b39600b41a9eee301b9760cde1282aeb33 /crates/ra_ide_api/src/references
parentb5a3ee93e24931c8bba628ddc7be4f098a19a326 (diff)
some fixes, add docs
Diffstat (limited to 'crates/ra_ide_api/src/references')
-rw-r--r--crates/ra_ide_api/src/references/classify.rs8
-rw-r--r--crates/ra_ide_api/src/references/name_definition.rs5
-rw-r--r--crates/ra_ide_api/src/references/search_scope.rs81
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
3use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; 3use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer};
4use ra_db::FileId; 4use ra_db::FileId;
5use ra_syntax::{ast, match_ast, AstNode, AstPtr}; 5use ra_syntax::{ast, match_ast, AstNode, AstPtr};
6use test_utils::tested_by;
6 7
7use super::{ 8use 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, &macro_call) { 147 if let Some(macro_def) = analyzer.resolve_macro_call(db, &macro_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
3use hir::{ 6use 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.
3use 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
5use hir::{DefWithBody, HasSource, ModuleSource}; 6use hir::{DefWithBody, HasSource, ModuleSource};
6use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; 7use ra_db::{FileId, SourceDatabase, SourceDatabaseExt};
7use ra_syntax::{AstNode, TextRange}; 8use ra_syntax::{AstNode, TextRange};
9use rustc_hash::FxHashSet;
8 10
9use crate::db::RootDatabase; 11use crate::db::RootDatabase;
10 12
11use super::{NameDefinition, NameKind}; 13use super::{NameDefinition, NameKind};
12 14
13impl NameDefinition { 15impl 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}