diff options
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/references.rs | 65 |
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; | |||
19 | use ra_db::{SourceDatabase, SourceDatabaseExt}; | 19 | use ra_db::{SourceDatabase, SourceDatabaseExt}; |
20 | use ra_prof::profile; | 20 | use ra_prof::profile; |
21 | use ra_syntax::{ | 21 | use 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 | ||
26 | use crate::{ | 27 | use 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 | ||
236 | fn access_mode(kind: NameKind, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { | 242 | fn 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 | |||
269 | fn 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() |