diff options
author | Jeremy Kolb <kjeremy@gmail.com> | 2020-01-04 22:46:01 +0000 |
---|---|---|
committer | kjeremy <kjeremy@gmail.com> | 2020-01-10 20:14:19 +0000 |
commit | d993f329a01deb3cdc011c3eb1dfd859302fec04 (patch) | |
tree | 4ee64d1bd29b793cf5d9cff1f712cc02077b490a /crates/ra_ide/src | |
parent | 19eb7fa1db7da8417314ddfafe7addbbd9c3b46a (diff) |
Basic DocumentHighlightKind support for assignments
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/references.rs | 73 |
2 files changed, 69 insertions, 6 deletions
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 7b187eba3..837315ca7 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -75,7 +75,7 @@ pub use crate::{ | |||
75 | inlay_hints::{InlayHint, InlayKind}, | 75 | inlay_hints::{InlayHint, InlayKind}, |
76 | line_index::{LineCol, LineIndex}, | 76 | line_index::{LineCol, LineIndex}, |
77 | line_index_utils::translate_offset_with_edit, | 77 | line_index_utils::translate_offset_with_edit, |
78 | references::{Reference, ReferenceKind, ReferenceSearchResult, SearchScope}, | 78 | references::{Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope}, |
79 | runnables::{Runnable, RunnableKind}, | 79 | runnables::{Runnable, RunnableKind}, |
80 | source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, | 80 | source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, |
81 | syntax_highlighting::HighlightedRange, | 81 | syntax_highlighting::HighlightedRange, |
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 5a3ec4eb9..b9d8a6b1e 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -19,8 +19,8 @@ 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, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextUnit, | 22 | algo::find_node_at_offset, ast, match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, |
23 | TokenAtOffset, | 23 | TextUnit, TokenAtOffset, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | use crate::{ | 26 | use crate::{ |
@@ -46,6 +46,7 @@ pub struct ReferenceSearchResult { | |||
46 | pub struct Reference { | 46 | pub struct Reference { |
47 | pub file_range: FileRange, | 47 | pub file_range: FileRange, |
48 | pub kind: ReferenceKind, | 48 | pub kind: ReferenceKind, |
49 | pub access: Option<ReferenceAccess>, | ||
49 | } | 50 | } |
50 | 51 | ||
51 | #[derive(Debug, Clone, PartialEq)] | 52 | #[derive(Debug, Clone, PartialEq)] |
@@ -54,6 +55,12 @@ pub enum ReferenceKind { | |||
54 | Other, | 55 | Other, |
55 | } | 56 | } |
56 | 57 | ||
58 | #[derive(Debug, Clone, PartialEq)] | ||
59 | pub enum ReferenceAccess { | ||
60 | Read, | ||
61 | Write, | ||
62 | } | ||
63 | |||
57 | impl ReferenceSearchResult { | 64 | impl ReferenceSearchResult { |
58 | pub fn declaration(&self) -> &NavigationTarget { | 65 | pub fn declaration(&self) -> &NavigationTarget { |
59 | &self.declaration | 66 | &self.declaration |
@@ -72,7 +79,7 @@ impl ReferenceSearchResult { | |||
72 | } | 79 | } |
73 | 80 | ||
74 | // allow turning ReferenceSearchResult into an iterator | 81 | // allow turning ReferenceSearchResult into an iterator |
75 | // over FileRanges | 82 | // over References |
76 | impl IntoIterator for ReferenceSearchResult { | 83 | impl IntoIterator for ReferenceSearchResult { |
77 | type Item = Reference; | 84 | type Item = Reference; |
78 | type IntoIter = std::vec::IntoIter<Reference>; | 85 | type IntoIter = std::vec::IntoIter<Reference>; |
@@ -85,6 +92,7 @@ impl IntoIterator for ReferenceSearchResult { | |||
85 | range: self.declaration.range(), | 92 | range: self.declaration.range(), |
86 | }, | 93 | }, |
87 | kind: self.declaration_kind, | 94 | kind: self.declaration_kind, |
95 | access: None, | ||
88 | }); | 96 | }); |
89 | v.append(&mut self.references); | 97 | v.append(&mut self.references); |
90 | v.into_iter() | 98 | v.into_iter() |
@@ -201,7 +209,13 @@ fn process_definition( | |||
201 | } else { | 209 | } else { |
202 | ReferenceKind::Other | 210 | ReferenceKind::Other |
203 | }; | 211 | }; |
204 | refs.push(Reference { file_range: FileRange { file_id, range }, kind }); | 212 | let access = access_mode(d.kind, &name_ref); |
213 | |||
214 | refs.push(Reference { | ||
215 | file_range: FileRange { file_id, range }, | ||
216 | kind, | ||
217 | access, | ||
218 | }); | ||
205 | } | 219 | } |
206 | } | 220 | } |
207 | } | 221 | } |
@@ -210,11 +224,46 @@ fn process_definition( | |||
210 | refs | 224 | refs |
211 | } | 225 | } |
212 | 226 | ||
227 | fn access_mode(kind: NameKind, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { | ||
228 | match kind { | ||
229 | NameKind::Local(_) | NameKind::Field(_) => { | ||
230 | //LetExpr or BinExpr | ||
231 | name_ref.syntax().ancestors().find_map(|node| { | ||
232 | match_ast! { | ||
233 | match (node) { | ||
234 | ast::BinExpr(expr) => { | ||
235 | match expr.op_kind() { | ||
236 | Some(kind) if kind.is_assignment() => { | ||
237 | if let Some(lhs) = expr.lhs() { | ||
238 | if lhs.syntax().text_range() == name_ref.syntax().text_range() { | ||
239 | return Some(ReferenceAccess::Write); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | if let Some(rhs) = expr.rhs() { | ||
244 | if rhs.syntax().text_range().is_subrange(&name_ref.syntax().text_range()) { | ||
245 | return Some(ReferenceAccess::Read); | ||
246 | } | ||
247 | } | ||
248 | }, | ||
249 | _ => { return Some(ReferenceAccess::Read) }, | ||
250 | } | ||
251 | None | ||
252 | }, | ||
253 | _ => {None} | ||
254 | } | ||
255 | } | ||
256 | }) | ||
257 | } | ||
258 | _ => None, | ||
259 | } | ||
260 | } | ||
261 | |||
213 | #[cfg(test)] | 262 | #[cfg(test)] |
214 | mod tests { | 263 | mod tests { |
215 | use crate::{ | 264 | use crate::{ |
216 | mock_analysis::{analysis_and_position, single_file_with_position, MockAnalysis}, | 265 | mock_analysis::{analysis_and_position, single_file_with_position, MockAnalysis}, |
217 | Reference, ReferenceKind, ReferenceSearchResult, SearchScope, | 266 | Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope, |
218 | }; | 267 | }; |
219 | 268 | ||
220 | #[test] | 269 | #[test] |
@@ -515,6 +564,20 @@ mod tests { | |||
515 | ); | 564 | ); |
516 | } | 565 | } |
517 | 566 | ||
567 | #[test] | ||
568 | fn test_basic_highlight_read() { | ||
569 | let code = r#" | ||
570 | fn foo() { | ||
571 | let i<|> = 0; | ||
572 | i = i + 1; | ||
573 | }"#; | ||
574 | |||
575 | let refs = get_all_refs(code); | ||
576 | assert_eq!(refs.len(), 3); | ||
577 | assert_eq!(refs.references[0].access, Some(ReferenceAccess::Write)); | ||
578 | assert_eq!(refs.references[1].access, Some(ReferenceAccess::Read)); | ||
579 | } | ||
580 | |||
518 | fn get_all_refs(text: &str) -> ReferenceSearchResult { | 581 | fn get_all_refs(text: &str) -> ReferenceSearchResult { |
519 | let (analysis, position) = single_file_with_position(text); | 582 | let (analysis, position) = single_file_with_position(text); |
520 | analysis.find_all_refs(position, None).unwrap().unwrap() | 583 | analysis.find_all_refs(position, None).unwrap().unwrap() |