aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model.rs12
-rw-r--r--crates/ra_ide/src/references.rs61
-rw-r--r--crates/ra_ide_db/src/defs.rs28
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::{
27use ra_db::{CrateId, Edition, FileId}; 27use ra_db::{CrateId, Edition, FileId};
28use ra_prof::profile; 28use ra_prof::profile;
29use ra_syntax::{ 29use ra_syntax::{
30 ast::{self, AttrsOwner}, 30 ast::{self, AttrsOwner, NameOwner},
31 AstNode, 31 AstNode,
32}; 32};
33use rustc_hash::FxHashSet; 33use 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
785impl Local { 794impl 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
146pub(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
155fn find_name( 167fn 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
172fn process_definition( 184fn 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
241fn decl_access( 253fn 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
8use hir::{ 8use 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};
12use ra_prof::profile; 12use 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
71pub enum NameClass { 97pub enum NameClass {