aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
authorJeremy Kolb <[email protected]>2020-01-04 22:46:01 +0000
committerkjeremy <[email protected]>2020-01-10 20:14:19 +0000
commitd993f329a01deb3cdc011c3eb1dfd859302fec04 (patch)
tree4ee64d1bd29b793cf5d9cff1f712cc02077b490a /crates/ra_ide
parent19eb7fa1db7da8417314ddfafe7addbbd9c3b46a (diff)
Basic DocumentHighlightKind support for assignments
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/lib.rs2
-rw-r--r--crates/ra_ide/src/references.rs73
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;
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, 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
26use crate::{ 26use crate::{
@@ -46,6 +46,7 @@ pub struct ReferenceSearchResult {
46pub struct Reference { 46pub 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)]
59pub enum ReferenceAccess {
60 Read,
61 Write,
62}
63
57impl ReferenceSearchResult { 64impl 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
76impl IntoIterator for ReferenceSearchResult { 83impl 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
227fn 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)]
214mod tests { 263mod 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()