Skip to content

Commit d993f32

Browse files
committed
Basic DocumentHighlightKind support for assignments
1 parent 19eb7fa commit d993f32

File tree

5 files changed

+107
-17
lines changed

5 files changed

+107
-17
lines changed

crates/ra_ide/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ pub use crate::{
7575
inlay_hints::{InlayHint, InlayKind},
7676
line_index::{LineCol, LineIndex},
7777
line_index_utils::translate_offset_with_edit,
78-
references::{Reference, ReferenceKind, ReferenceSearchResult, SearchScope},
78+
references::{Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope},
7979
runnables::{Runnable, RunnableKind},
8080
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
8181
syntax_highlighting::HighlightedRange,

crates/ra_ide/src/references.rs

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ use once_cell::unsync::Lazy;
1919
use ra_db::{SourceDatabase, SourceDatabaseExt};
2020
use ra_prof::profile;
2121
use ra_syntax::{
22-
algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextUnit,
23-
TokenAtOffset,
22+
algo::find_node_at_offset, ast, match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode,
23+
TextUnit, TokenAtOffset,
2424
};
2525

2626
use crate::{
@@ -46,6 +46,7 @@ pub struct ReferenceSearchResult {
4646
pub struct Reference {
4747
pub file_range: FileRange,
4848
pub kind: ReferenceKind,
49+
pub access: Option<ReferenceAccess>,
4950
}
5051

5152
#[derive(Debug, Clone, PartialEq)]
@@ -54,6 +55,12 @@ pub enum ReferenceKind {
5455
Other,
5556
}
5657

58+
#[derive(Debug, Clone, PartialEq)]
59+
pub enum ReferenceAccess {
60+
Read,
61+
Write,
62+
}
63+
5764
impl ReferenceSearchResult {
5865
pub fn declaration(&self) -> &NavigationTarget {
5966
&self.declaration
@@ -72,7 +79,7 @@ impl ReferenceSearchResult {
7279
}
7380

7481
// allow turning ReferenceSearchResult into an iterator
75-
// over FileRanges
82+
// over References
7683
impl IntoIterator for ReferenceSearchResult {
7784
type Item = Reference;
7885
type IntoIter = std::vec::IntoIter<Reference>;
@@ -85,6 +92,7 @@ impl IntoIterator for ReferenceSearchResult {
8592
range: self.declaration.range(),
8693
},
8794
kind: self.declaration_kind,
95+
access: None,
8896
});
8997
v.append(&mut self.references);
9098
v.into_iter()
@@ -201,7 +209,13 @@ fn process_definition(
201209
} else {
202210
ReferenceKind::Other
203211
};
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+
});
205219
}
206220
}
207221
}
@@ -210,11 +224,46 @@ fn process_definition(
210224
refs
211225
}
212226

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+
213262
#[cfg(test)]
214263
mod tests {
215264
use crate::{
216265
mock_analysis::{analysis_and_position, single_file_with_position, MockAnalysis},
217-
Reference, ReferenceKind, ReferenceSearchResult, SearchScope,
266+
Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope,
218267
};
219268

220269
#[test]
@@ -515,6 +564,20 @@ mod tests {
515564
);
516565
}
517566

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+
518581
fn get_all_refs(text: &str) -> ReferenceSearchResult {
519582
let (analysis, position) = single_file_with_position(text);
520583
analysis.find_all_refs(position, None).unwrap().unwrap()

crates/ra_lsp_server/src/conv.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use lsp_types::{
99
use ra_ide::{
1010
translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
1111
FileRange, FileSystemEdit, Fold, FoldKind, InsertTextFormat, LineCol, LineIndex,
12-
NavigationTarget, RangeInfo, Severity, SourceChange, SourceFileEdit,
12+
NavigationTarget, RangeInfo, ReferenceAccess, Severity, SourceChange, SourceFileEdit,
1313
};
1414
use ra_syntax::{SyntaxKind, TextRange, TextUnit};
1515
use ra_text_edit::{AtomTextEdit, TextEdit};
@@ -53,6 +53,18 @@ impl Conv for SyntaxKind {
5353
}
5454
}
5555

56+
impl Conv for ReferenceAccess {
57+
type Output = ::lsp_types::DocumentHighlightKind;
58+
59+
fn conv(self) -> Self::Output {
60+
use lsp_types::DocumentHighlightKind::*;
61+
match self {
62+
ReferenceAccess::Read => Read,
63+
ReferenceAccess::Write => Write,
64+
}
65+
}
66+
}
67+
5668
impl Conv for CompletionItemKind {
5769
type Output = ::lsp_types::CompletionItemKind;
5870

crates/ra_lsp_server/src/main_loop/handlers.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -536,18 +536,32 @@ pub fn handle_references(
536536

537537
let locations = if params.context.include_declaration {
538538
refs.into_iter()
539-
.filter_map(|r| {
540-
let line_index = world.analysis().file_line_index(r.file_range.file_id).ok()?;
541-
to_location(r.file_range.file_id, r.file_range.range, &world, &line_index).ok()
539+
.filter_map(|reference| {
540+
let line_index =
541+
world.analysis().file_line_index(reference.file_range.file_id).ok()?;
542+
to_location(
543+
reference.file_range.file_id,
544+
reference.file_range.range,
545+
&world,
546+
&line_index,
547+
)
548+
.ok()
542549
})
543550
.collect()
544551
} else {
545552
// Only iterate over the references if include_declaration was false
546553
refs.references()
547554
.iter()
548-
.filter_map(|r| {
549-
let line_index = world.analysis().file_line_index(r.file_range.file_id).ok()?;
550-
to_location(r.file_range.file_id, r.file_range.range, &world, &line_index).ok()
555+
.filter_map(|reference| {
556+
let line_index =
557+
world.analysis().file_line_index(reference.file_range.file_id).ok()?;
558+
to_location(
559+
reference.file_range.file_id,
560+
reference.file_range.range,
561+
&world,
562+
&line_index,
563+
)
564+
.ok()
551565
})
552566
.collect()
553567
};
@@ -836,10 +850,10 @@ pub fn handle_document_highlight(
836850

837851
Ok(Some(
838852
refs.into_iter()
839-
.filter(|r| r.file_range.file_id == file_id)
840-
.map(|r| DocumentHighlight {
841-
range: r.file_range.range.conv_with(&line_index),
842-
kind: None,
853+
.filter(|reference| reference.file_range.file_id == file_id)
854+
.map(|reference| DocumentHighlight {
855+
range: reference.file_range.range.conv_with(&line_index),
856+
kind: reference.access.map(|it| it.conv()),
843857
})
844858
.collect(),
845859
))

crates/ra_syntax/src/ast/expr_extensions.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ impl BinOp {
144144
}
145145
}
146146
}
147+
147148
impl ast::BinExpr {
148149
pub fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
149150
self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| {

0 commit comments

Comments
 (0)