aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/references.rs65
1 files changed, 57 insertions, 8 deletions
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index 2d20de1d0..4e52e0e7b 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -19,8 +19,9 @@ use once_cell::unsync::Lazy;
19use ra_db::{SourceDatabase, SourceDatabaseExt}; 19use ra_db::{SourceDatabase, SourceDatabaseExt};
20use ra_prof::profile; 20use ra_prof::profile;
21use ra_syntax::{ 21use ra_syntax::{
22 algo::find_node_at_offset, ast, match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, 22 algo::find_node_at_offset,
23 TextUnit, TokenAtOffset, 23 ast::{self, NameOwner},
24 match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, TextUnit, TokenAtOffset,
24}; 25};
25 26
26use crate::{ 27use crate::{
@@ -149,7 +150,13 @@ pub(crate) fn find_all_refs(
149 } 150 }
150 }; 151 };
151 152
152 let declaration = Declaration { nav: declaration, kind: ReferenceKind::Other, access: None }; 153 let decl_range = declaration.range();
154
155 let declaration = Declaration {
156 nav: declaration,
157 kind: ReferenceKind::Other,
158 access: decl_access(&def.kind, &name, &syntax, decl_range),
159 };
153 160
154 let references = process_definition(db, def, name, search_scope) 161 let references = process_definition(db, def, name, search_scope)
155 .into_iter() 162 .into_iter()
@@ -218,12 +225,11 @@ fn process_definition(
218 } else { 225 } else {
219 ReferenceKind::Other 226 ReferenceKind::Other
220 }; 227 };
221 let access = access_mode(d.kind, &name_ref);
222 228
223 refs.push(Reference { 229 refs.push(Reference {
224 file_range: FileRange { file_id, range }, 230 file_range: FileRange { file_id, range },
225 kind, 231 kind,
226 access, 232 access: reference_access(&d.kind, &name_ref),
227 }); 233 });
228 } 234 }
229 } 235 }
@@ -233,7 +239,34 @@ fn process_definition(
233 refs 239 refs
234} 240}
235 241
236fn access_mode(kind: NameKind, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { 242fn decl_access(
243 kind: &NameKind,
244 name: &str,
245 syntax: &SyntaxNode,
246 range: TextRange,
247) -> Option<ReferenceAccess> {
248 match kind {
249 NameKind::Local(_) | NameKind::Field(_) => {}
250 _ => return None,
251 };
252
253 let stmt = find_node_at_offset::<ast::LetStmt>(syntax, range.start())?;
254 if let Some(_) = stmt.initializer() {
255 let pat = stmt.pat()?;
256 match pat {
257 ast::Pat::BindPat(it) => {
258 if it.name()?.text().as_str() == name {
259 return Some(ReferenceAccess::Write);
260 }
261 }
262 _ => {}
263 }
264 }
265
266 None
267}
268
269fn reference_access(kind: &NameKind, name_ref: &ast::NameRef) -> Option<ReferenceAccess> {
237 // Only Locals and Fields have accesses for now. 270 // Only Locals and Fields have accesses for now.
238 match kind { 271 match kind {
239 NameKind::Local(_) | NameKind::Field(_) => {} 272 NameKind::Local(_) | NameKind::Field(_) => {}
@@ -311,7 +344,7 @@ mod tests {
311 let refs = get_all_refs(code); 344 let refs = get_all_refs(code);
312 check_result( 345 check_result(
313 refs, 346 refs,
314 "i BIND_PAT FileId(1) [33; 34) Other", 347 "i BIND_PAT FileId(1) [33; 34) Other Write",
315 &[ 348 &[
316 "FileId(1) [67; 68) Other Write", 349 "FileId(1) [67; 68) Other Write",
317 "FileId(1) [71; 72) Other Read", 350 "FileId(1) [71; 72) Other Read",
@@ -569,7 +602,7 @@ mod tests {
569 let refs = get_all_refs(code); 602 let refs = get_all_refs(code);
570 check_result( 603 check_result(
571 refs, 604 refs,
572 "i BIND_PAT FileId(1) [36; 37) Other", 605 "i BIND_PAT FileId(1) [36; 37) Other Write",
573 &["FileId(1) [55; 56) Other Write", "FileId(1) [59; 60) Other Read"], 606 &["FileId(1) [55; 56) Other Write", "FileId(1) [59; 60) Other Read"],
574 ); 607 );
575 } 608 }
@@ -594,6 +627,22 @@ mod tests {
594 ); 627 );
595 } 628 }
596 629
630 #[test]
631 fn test_basic_highlight_decl_no_write() {
632 let code = r#"
633 fn foo() {
634 let i<|>;
635 i = 1;
636 }"#;
637
638 let refs = get_all_refs(code);
639 check_result(
640 refs,
641 "i BIND_PAT FileId(1) [36; 37) Other",
642 &["FileId(1) [51; 52) Other Write"],
643 );
644 }
645
597 fn get_all_refs(text: &str) -> ReferenceSearchResult { 646 fn get_all_refs(text: &str) -> ReferenceSearchResult {
598 let (analysis, position) = single_file_with_position(text); 647 let (analysis, position) = single_file_with_position(text);
599 analysis.find_all_refs(position, None).unwrap().unwrap() 648 analysis.find_all_refs(position, None).unwrap().unwrap()