Skip to content

Commit fb25c91

Browse files
mikhail-m1matklad
authored andcommitted
Adds a way to limits reference search by StructLiteral
1 parent 5d8f2bd commit fb25c91

File tree

3 files changed

+100
-18
lines changed

3 files changed

+100
-18
lines changed

crates/ra_ide/src/references.rs

Lines changed: 84 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ use hir::InFile;
1818
use once_cell::unsync::Lazy;
1919
use ra_db::{SourceDatabase, SourceDatabaseExt};
2020
use ra_prof::profile;
21-
use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode, TextUnit};
21+
use ra_syntax::{
22+
algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextUnit,
23+
TokenAtOffset,
24+
};
2225

2326
use crate::{
2427
db::RootDatabase, display::ToNav, FilePosition, FileRange, NavigationTarget, RangeInfo,
@@ -35,15 +38,28 @@ pub use self::search_scope::SearchScope;
3538
#[derive(Debug, Clone)]
3639
pub struct ReferenceSearchResult {
3740
declaration: NavigationTarget,
38-
references: Vec<FileRange>,
41+
declaration_kind: ReferenceKind,
42+
references: Vec<Reference>,
43+
}
44+
45+
#[derive(Debug, Clone)]
46+
pub struct Reference {
47+
pub file_range: FileRange,
48+
pub kind: ReferenceKind,
49+
}
50+
51+
#[derive(Debug, Clone, PartialEq)]
52+
pub enum ReferenceKind {
53+
StructLiteral,
54+
Other,
3955
}
4056

4157
impl ReferenceSearchResult {
4258
pub fn declaration(&self) -> &NavigationTarget {
4359
&self.declaration
4460
}
4561

46-
pub fn references(&self) -> &[FileRange] {
62+
pub fn references(&self) -> &[Reference] {
4763
&self.references
4864
}
4965

@@ -58,24 +74,43 @@ impl ReferenceSearchResult {
5874
// allow turning ReferenceSearchResult into an iterator
5975
// over FileRanges
6076
impl IntoIterator for ReferenceSearchResult {
61-
type Item = FileRange;
62-
type IntoIter = std::vec::IntoIter<FileRange>;
77+
type Item = Reference;
78+
type IntoIter = std::vec::IntoIter<Reference>;
6379

6480
fn into_iter(mut self) -> Self::IntoIter {
6581
let mut v = Vec::with_capacity(self.len());
66-
v.push(FileRange { file_id: self.declaration.file_id(), range: self.declaration.range() });
82+
v.push(Reference {
83+
file_range: FileRange {
84+
file_id: self.declaration.file_id(),
85+
range: self.declaration.range(),
86+
},
87+
kind: self.declaration_kind,
88+
});
6789
v.append(&mut self.references);
6890
v.into_iter()
6991
}
7092
}
7193

7294
pub(crate) fn find_all_refs(
7395
db: &RootDatabase,
74-
position: FilePosition,
96+
mut position: FilePosition,
7597
search_scope: Option<SearchScope>,
7698
) -> Option<RangeInfo<ReferenceSearchResult>> {
7799
let parse = db.parse(position.file_id);
78100
let syntax = parse.tree().syntax().clone();
101+
102+
let token = syntax.token_at_offset(position.offset);
103+
let mut search_kind = ReferenceKind::Other;
104+
105+
if let TokenAtOffset::Between(ref left, ref right) = token {
106+
if (right.kind() == SyntaxKind::L_CURLY || right.kind() == SyntaxKind::L_PAREN)
107+
&& left.kind() != SyntaxKind::IDENT
108+
{
109+
position = FilePosition { offset: left.text_range().start(), ..position };
110+
search_kind = ReferenceKind::StructLiteral;
111+
}
112+
}
113+
79114
let RangeInfo { range, info: (name, def) } = find_name(db, &syntax, position)?;
80115

81116
let declaration = match def.kind {
@@ -96,9 +131,15 @@ pub(crate) fn find_all_refs(
96131
}
97132
};
98133

99-
let references = process_definition(db, def, name, search_scope);
134+
let references = process_definition(db, def, name, search_scope)
135+
.into_iter()
136+
.filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind)
137+
.collect();
100138

101-
Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references }))
139+
Some(RangeInfo::new(
140+
range,
141+
ReferenceSearchResult { declaration, references, declaration_kind: ReferenceKind::Other },
142+
))
102143
}
103144

104145
fn find_name<'a>(
@@ -122,7 +163,7 @@ fn process_definition(
122163
def: NameDefinition,
123164
name: String,
124165
scope: SearchScope,
125-
) -> Vec<FileRange> {
166+
) -> Vec<Reference> {
126167
let _p = profile("process_definition");
127168

128169
let pat = name.as_str();
@@ -146,7 +187,21 @@ fn process_definition(
146187
}
147188
if let Some(d) = classify_name_ref(db, InFile::new(file_id.into(), &name_ref)) {
148189
if d == def {
149-
refs.push(FileRange { file_id, range });
190+
let kind = if name_ref
191+
.syntax()
192+
.ancestors()
193+
.find_map(ast::RecordLit::cast)
194+
.and_then(|l| l.path())
195+
.and_then(|p| p.segment())
196+
.and_then(|p| p.name_ref())
197+
.map(|n| n == name_ref)
198+
.unwrap_or(false)
199+
{
200+
ReferenceKind::StructLiteral
201+
} else {
202+
ReferenceKind::Other
203+
};
204+
refs.push(Reference { file_range: FileRange { file_id, range }, kind });
150205
}
151206
}
152207
}
@@ -162,6 +217,24 @@ mod tests {
162217
ReferenceSearchResult, SearchScope,
163218
};
164219

220+
#[test]
221+
fn test_struct_literal() {
222+
let code = r#"
223+
struct Foo <|>{
224+
a: i32,
225+
}
226+
impl Foo {
227+
fn f() -> i32 { 42 }
228+
}
229+
fn main() {
230+
let f: Foo;
231+
f = Foo {a: Foo::f()};
232+
}"#;
233+
234+
let refs = get_all_refs(code);
235+
assert_eq!(refs.len(), 2);
236+
}
237+
165238
#[test]
166239
fn test_find_all_refs_for_local() {
167240
let code = r#"

crates/ra_ide/src/references/rename.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,13 @@ fn rename_reference(
110110

111111
let edit = refs
112112
.into_iter()
113-
.map(|range| source_edit_from_file_id_range(range.file_id, range.range, new_name))
113+
.map(|reference| {
114+
source_edit_from_file_id_range(
115+
reference.file_range.file_id,
116+
reference.file_range.range,
117+
new_name,
118+
)
119+
})
114120
.collect::<Vec<_>>();
115121

116122
if edit.is_empty() {

crates/ra_lsp_server/src/main_loop/handlers.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -531,17 +531,17 @@ pub fn handle_references(
531531
let locations = if params.context.include_declaration {
532532
refs.into_iter()
533533
.filter_map(|r| {
534-
let line_index = world.analysis().file_line_index(r.file_id).ok()?;
535-
to_location(r.file_id, r.range, &world, &line_index).ok()
534+
let line_index = world.analysis().file_line_index(r.file_range.file_id).ok()?;
535+
to_location(r.file_range.file_id, r.file_range.range, &world, &line_index).ok()
536536
})
537537
.collect()
538538
} else {
539539
// Only iterate over the references if include_declaration was false
540540
refs.references()
541541
.iter()
542542
.filter_map(|r| {
543-
let line_index = world.analysis().file_line_index(r.file_id).ok()?;
544-
to_location(r.file_id, r.range, &world, &line_index).ok()
543+
let line_index = world.analysis().file_line_index(r.file_range.file_id).ok()?;
544+
to_location(r.file_range.file_id, r.file_range.range, &world, &line_index).ok()
545545
})
546546
.collect()
547547
};
@@ -830,8 +830,11 @@ pub fn handle_document_highlight(
830830

831831
Ok(Some(
832832
refs.into_iter()
833-
.filter(|r| r.file_id == file_id)
834-
.map(|r| DocumentHighlight { range: r.range.conv_with(&line_index), kind: None })
833+
.filter(|r| r.file_range.file_id == file_id)
834+
.map(|r| DocumentHighlight {
835+
range: r.file_range.range.conv_with(&line_index),
836+
kind: None,
837+
})
835838
.collect(),
836839
))
837840
}

0 commit comments

Comments
 (0)