diff options
author | Aleksey Kladov <[email protected]> | 2020-03-03 17:22:52 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-03-03 17:22:52 +0000 |
commit | 7d71cc72b5902300ed03db409b2a858517a1f5e0 (patch) | |
tree | 8cc0425d7b25c5da3f6a633a3addfb38640c5002 | |
parent | 674770ef0473cf938d734f54bcf33524d9fdf5f8 (diff) |
Refactor reference search a bit
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 12 | ||||
-rw-r--r-- | crates/ra_ide/src/references.rs | 61 | ||||
-rw-r--r-- | crates/ra_ide_db/src/defs.rs | 28 |
3 files changed, 74 insertions, 27 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index b71ee764a..2944926e6 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -27,7 +27,7 @@ use hir_ty::{ | |||
27 | use ra_db::{CrateId, Edition, FileId}; | 27 | use ra_db::{CrateId, Edition, FileId}; |
28 | use ra_prof::profile; | 28 | use ra_prof::profile; |
29 | use ra_syntax::{ | 29 | use ra_syntax::{ |
30 | ast::{self, AttrsOwner}, | 30 | ast::{self, AttrsOwner, NameOwner}, |
31 | AstNode, | 31 | AstNode, |
32 | }; | 32 | }; |
33 | use rustc_hash::FxHashSet; | 33 | use rustc_hash::FxHashSet; |
@@ -603,6 +603,10 @@ impl Static { | |||
603 | pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { | 603 | pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { |
604 | Some(self.module(db).krate()) | 604 | Some(self.module(db).krate()) |
605 | } | 605 | } |
606 | |||
607 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { | ||
608 | db.static_data(self.id).name.clone() | ||
609 | } | ||
606 | } | 610 | } |
607 | 611 | ||
608 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 612 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -674,6 +678,11 @@ impl MacroDef { | |||
674 | let module_id = db.crate_def_map(krate).root; | 678 | let module_id = db.crate_def_map(krate).root; |
675 | Some(Module::new(Crate { id: krate }, module_id)) | 679 | Some(Module::new(Crate { id: krate }, module_id)) |
676 | } | 680 | } |
681 | |||
682 | /// XXX: this parses the file | ||
683 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { | ||
684 | self.source(db).value.name().map(|it| it.as_name()) | ||
685 | } | ||
677 | } | 686 | } |
678 | 687 | ||
679 | /// Invariant: `inner.as_assoc_item(db).is_some()` | 688 | /// Invariant: `inner.as_assoc_item(db).is_some()` |
@@ -783,6 +792,7 @@ pub struct Local { | |||
783 | } | 792 | } |
784 | 793 | ||
785 | impl Local { | 794 | impl Local { |
795 | // FIXME: why is this an option? It shouldn't be? | ||
786 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { | 796 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { |
787 | let body = db.body(self.parent.into()); | 797 | let body = db.body(self.parent.into()); |
788 | match &body[self.pat_id] { | 798 | match &body[self.pat_id] { |
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 9b0785e1d..c9c9c6483 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -125,9 +125,29 @@ pub(crate) fn find_all_refs( | |||
125 | (find_node_at_offset::<ast::Name>(&syntax, position.offset), ReferenceKind::Other) | 125 | (find_node_at_offset::<ast::Name>(&syntax, position.offset), ReferenceKind::Other) |
126 | }; | 126 | }; |
127 | 127 | ||
128 | let RangeInfo { range, info: (name, def) } = find_name(&sema, &syntax, position, opt_name)?; | 128 | let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; |
129 | let declaration = def.try_to_nav(db)?; | ||
130 | 129 | ||
130 | let references = find_refs_to_def(db, &def, search_scope) | ||
131 | .into_iter() | ||
132 | .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) | ||
133 | .collect(); | ||
134 | |||
135 | let decl_range = def.try_to_nav(db)?.range(); | ||
136 | |||
137 | let declaration = Declaration { | ||
138 | nav: def.try_to_nav(db)?, | ||
139 | kind: ReferenceKind::Other, | ||
140 | access: decl_access(&def, &syntax, decl_range), | ||
141 | }; | ||
142 | |||
143 | Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references })) | ||
144 | } | ||
145 | |||
146 | pub(crate) fn find_refs_to_def( | ||
147 | db: &RootDatabase, | ||
148 | def: &NameDefinition, | ||
149 | search_scope: Option<SearchScope>, | ||
150 | ) -> Vec<Reference> { | ||
131 | let search_scope = { | 151 | let search_scope = { |
132 | let base = SearchScope::for_def(&def, db); | 152 | let base = SearchScope::for_def(&def, db); |
133 | match search_scope { | 153 | match search_scope { |
@@ -136,20 +156,12 @@ pub(crate) fn find_all_refs( | |||
136 | } | 156 | } |
137 | }; | 157 | }; |
138 | 158 | ||
139 | let decl_range = declaration.range(); | 159 | let name = match def.name(db) { |
140 | 160 | None => return Vec::new(), | |
141 | let declaration = Declaration { | 161 | Some(it) => it.to_string(), |
142 | nav: declaration, | ||
143 | kind: ReferenceKind::Other, | ||
144 | access: decl_access(&def, &name, &syntax, decl_range), | ||
145 | }; | 162 | }; |
146 | 163 | ||
147 | let references = process_definition(db, def, name, search_scope) | 164 | process_definition(db, def, name, search_scope) |
148 | .into_iter() | ||
149 | .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) | ||
150 | .collect(); | ||
151 | |||
152 | Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references })) | ||
153 | } | 165 | } |
154 | 166 | ||
155 | fn find_name( | 167 | fn find_name( |
@@ -157,21 +169,21 @@ fn find_name( | |||
157 | syntax: &SyntaxNode, | 169 | syntax: &SyntaxNode, |
158 | position: FilePosition, | 170 | position: FilePosition, |
159 | opt_name: Option<ast::Name>, | 171 | opt_name: Option<ast::Name>, |
160 | ) -> Option<RangeInfo<(String, NameDefinition)>> { | 172 | ) -> Option<RangeInfo<NameDefinition>> { |
161 | if let Some(name) = opt_name { | 173 | if let Some(name) = opt_name { |
162 | let def = classify_name(sema, &name)?.definition(); | 174 | let def = classify_name(sema, &name)?.definition(); |
163 | let range = name.syntax().text_range(); | 175 | let range = name.syntax().text_range(); |
164 | return Some(RangeInfo::new(range, (name.text().to_string(), def))); | 176 | return Some(RangeInfo::new(range, def)); |
165 | } | 177 | } |
166 | let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; | 178 | let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; |
167 | let def = classify_name_ref(sema, &name_ref)?.definition(); | 179 | let def = classify_name_ref(sema, &name_ref)?.definition(); |
168 | let range = name_ref.syntax().text_range(); | 180 | let range = name_ref.syntax().text_range(); |
169 | Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) | 181 | Some(RangeInfo::new(range, def)) |
170 | } | 182 | } |
171 | 183 | ||
172 | fn process_definition( | 184 | fn process_definition( |
173 | db: &RootDatabase, | 185 | db: &RootDatabase, |
174 | def: NameDefinition, | 186 | def: &NameDefinition, |
175 | name: String, | 187 | name: String, |
176 | scope: SearchScope, | 188 | scope: SearchScope, |
177 | ) -> Vec<Reference> { | 189 | ) -> Vec<Reference> { |
@@ -217,7 +229,7 @@ fn process_definition( | |||
217 | 229 | ||
218 | if let Some(d) = classify_name_ref(&sema, &name_ref) { | 230 | if let Some(d) = classify_name_ref(&sema, &name_ref) { |
219 | let d = d.definition(); | 231 | let d = d.definition(); |
220 | if d == def { | 232 | if &d == def { |
221 | let kind = | 233 | let kind = |
222 | if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { | 234 | if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { |
223 | ReferenceKind::StructLiteral | 235 | ReferenceKind::StructLiteral |
@@ -240,7 +252,6 @@ fn process_definition( | |||
240 | 252 | ||
241 | fn decl_access( | 253 | fn decl_access( |
242 | def: &NameDefinition, | 254 | def: &NameDefinition, |
243 | name: &str, | ||
244 | syntax: &SyntaxNode, | 255 | syntax: &SyntaxNode, |
245 | range: TextRange, | 256 | range: TextRange, |
246 | ) -> Option<ReferenceAccess> { | 257 | ) -> Option<ReferenceAccess> { |
@@ -253,7 +264,7 @@ fn decl_access( | |||
253 | if stmt.initializer().is_some() { | 264 | if stmt.initializer().is_some() { |
254 | let pat = stmt.pat()?; | 265 | let pat = stmt.pat()?; |
255 | if let ast::Pat::BindPat(it) = pat { | 266 | if let ast::Pat::BindPat(it) = pat { |
256 | if it.name()?.text().as_str() == name { | 267 | if it.is_mutable() { |
257 | return Some(ReferenceAccess::Write); | 268 | return Some(ReferenceAccess::Write); |
258 | } | 269 | } |
259 | } | 270 | } |
@@ -463,7 +474,7 @@ mod tests { | |||
463 | let refs = get_all_refs(code); | 474 | let refs = get_all_refs(code); |
464 | check_result( | 475 | check_result( |
465 | refs, | 476 | refs, |
466 | "spam BIND_PAT FileId(1) [44; 48) Other Write", | 477 | "spam BIND_PAT FileId(1) [44; 48) Other", |
467 | &["FileId(1) [71; 75) Other Read", "FileId(1) [78; 82) Other Read"], | 478 | &["FileId(1) [71; 75) Other Read", "FileId(1) [78; 82) Other Read"], |
468 | ); | 479 | ); |
469 | } | 480 | } |
@@ -709,15 +720,15 @@ mod tests { | |||
709 | fn test_basic_highlight_read_write() { | 720 | fn test_basic_highlight_read_write() { |
710 | let code = r#" | 721 | let code = r#" |
711 | fn foo() { | 722 | fn foo() { |
712 | let i<|> = 0; | 723 | let mut i<|> = 0; |
713 | i = i + 1; | 724 | i = i + 1; |
714 | }"#; | 725 | }"#; |
715 | 726 | ||
716 | let refs = get_all_refs(code); | 727 | let refs = get_all_refs(code); |
717 | check_result( | 728 | check_result( |
718 | refs, | 729 | refs, |
719 | "i BIND_PAT FileId(1) [36; 37) Other Write", | 730 | "i BIND_PAT FileId(1) [40; 41) Other Write", |
720 | &["FileId(1) [55; 56) Other Write", "FileId(1) [59; 60) Other Read"], | 731 | &["FileId(1) [59; 60) Other Write", "FileId(1) [63; 64) Other Read"], |
721 | ); | 732 | ); |
722 | } | 733 | } |
723 | 734 | ||
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 7b1030a14..8a5161dfe 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs | |||
@@ -6,7 +6,7 @@ | |||
6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). | 6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). |
7 | 7 | ||
8 | use hir::{ | 8 | use hir::{ |
9 | Adt, FieldSource, HasSource, ImplDef, Local, MacroDef, Module, ModuleDef, Semantics, | 9 | Adt, FieldSource, HasSource, ImplDef, Local, MacroDef, Module, ModuleDef, Name, Semantics, |
10 | StructField, TypeParam, | 10 | StructField, TypeParam, |
11 | }; | 11 | }; |
12 | use ra_prof::profile; | 12 | use ra_prof::profile; |
@@ -66,6 +66,32 @@ impl NameDefinition { | |||
66 | NameDefinition::TypeParam(_) => None, | 66 | NameDefinition::TypeParam(_) => None, |
67 | } | 67 | } |
68 | } | 68 | } |
69 | |||
70 | pub fn name(&self, db: &RootDatabase) -> Option<Name> { | ||
71 | let name = match self { | ||
72 | NameDefinition::Macro(it) => it.name(db)?, | ||
73 | NameDefinition::StructField(it) => it.name(db), | ||
74 | NameDefinition::ModuleDef(def) => match def { | ||
75 | hir::ModuleDef::Module(it) => it.name(db)?, | ||
76 | hir::ModuleDef::Function(it) => it.name(db), | ||
77 | hir::ModuleDef::Adt(def) => match def { | ||
78 | hir::Adt::Struct(it) => it.name(db), | ||
79 | hir::Adt::Union(it) => it.name(db), | ||
80 | hir::Adt::Enum(it) => it.name(db), | ||
81 | }, | ||
82 | hir::ModuleDef::EnumVariant(it) => it.name(db), | ||
83 | hir::ModuleDef::Const(it) => it.name(db)?, | ||
84 | hir::ModuleDef::Static(it) => it.name(db)?, | ||
85 | hir::ModuleDef::Trait(it) => it.name(db), | ||
86 | hir::ModuleDef::TypeAlias(it) => it.name(db), | ||
87 | hir::ModuleDef::BuiltinType(_) => return None, | ||
88 | }, | ||
89 | NameDefinition::SelfType(_) => return None, | ||
90 | NameDefinition::Local(it) => it.name(db)?, | ||
91 | NameDefinition::TypeParam(it) => it.name(db), | ||
92 | }; | ||
93 | Some(name) | ||
94 | } | ||
69 | } | 95 | } |
70 | 96 | ||
71 | pub enum NameClass { | 97 | pub enum NameClass { |