aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/references.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/references.rs')
-rw-r--r--crates/ra_ide/src/references.rs61
1 files changed, 36 insertions, 25 deletions
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