Skip to content

Commit 631bca7

Browse files
committed
Highlight declarations and references for both defs in field shorthands
1 parent ced65f7 commit 631bca7

File tree

2 files changed

+75
-32
lines changed

2 files changed

+75
-32
lines changed

crates/ide/src/highlight_related.rs

Lines changed: 74 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use hir::Semantics;
22
use ide_db::{
33
base_db::FilePosition,
4-
defs::Definition,
4+
defs::{Definition, NameClass, NameRefClass},
55
helpers::{for_each_break_expr, for_each_tail_expr, pick_best_token},
66
search::{FileReference, ReferenceAccess, SearchScope},
77
RootDatabase,
88
};
99
use syntax::{
1010
ast::{self, LoopBodyOwner},
11-
match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, T,
11+
match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize, T,
1212
};
1313

1414
use crate::{display::TryToNav, references, NavigationTarget};
@@ -70,35 +70,36 @@ fn highlight_references(
7070
syntax: &SyntaxNode,
7171
FilePosition { offset, file_id }: FilePosition,
7272
) -> Option<Vec<HighlightedRange>> {
73-
let def = references::find_def(sema, syntax, offset)?;
74-
let usages = def
75-
.usages(sema)
76-
.set_scope(Some(SearchScope::single_file(file_id)))
77-
.include_self_refs()
78-
.all();
79-
80-
let declaration = match def {
81-
Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
82-
Some(NavigationTarget::from_module_to_decl(sema.db, module))
73+
let defs = find_defs(sema, syntax, offset)?;
74+
let usages = defs
75+
.iter()
76+
.flat_map(|&d| {
77+
d.usages(sema)
78+
.set_scope(Some(SearchScope::single_file(file_id)))
79+
.include_self_refs()
80+
.all()
81+
.references
82+
.remove(&file_id)
83+
})
84+
.flatten()
85+
.map(|FileReference { access, range, .. }| HighlightedRange { range, access });
86+
87+
let declarations = defs.iter().flat_map(|def| {
88+
match def {
89+
&Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
90+
Some(NavigationTarget::from_module_to_decl(sema.db, module))
91+
}
92+
def => def.try_to_nav(sema.db),
8393
}
84-
def => def.try_to_nav(sema.db),
85-
}
86-
.filter(|decl| decl.file_id == file_id)
87-
.and_then(|decl| {
88-
let range = decl.focus_range?;
89-
let access = references::decl_access(&def, syntax, range);
90-
Some(HighlightedRange { range, access })
94+
.filter(|decl| decl.file_id == file_id)
95+
.and_then(|decl| {
96+
let range = decl.focus_range?;
97+
let access = references::decl_access(&def, syntax, range);
98+
Some(HighlightedRange { range, access })
99+
})
91100
});
92101

93-
let file_refs = usages.references.get(&file_id).map_or(&[][..], Vec::as_slice);
94-
let mut res = Vec::with_capacity(file_refs.len() + 1);
95-
res.extend(declaration);
96-
res.extend(
97-
file_refs
98-
.iter()
99-
.map(|&FileReference { access, range, .. }| HighlightedRange { range, access }),
100-
);
101-
Some(res)
102+
Some(declarations.chain(usages).collect())
102103
}
103104

104105
fn highlight_exit_points(
@@ -265,6 +266,35 @@ fn cover_range(r0: Option<TextRange>, r1: Option<TextRange>) -> Option<TextRange
265266
}
266267
}
267268

269+
fn find_defs(
270+
sema: &Semantics<RootDatabase>,
271+
syntax: &SyntaxNode,
272+
offset: TextSize,
273+
) -> Option<Vec<Definition>> {
274+
let defs = match sema.find_node_at_offset_with_descend(syntax, offset)? {
275+
ast::NameLike::NameRef(name_ref) => match NameRefClass::classify(sema, &name_ref)? {
276+
NameRefClass::Definition(def) => vec![def],
277+
NameRefClass::FieldShorthand { local_ref, field_ref } => {
278+
vec![Definition::Local(local_ref), Definition::Field(field_ref)]
279+
}
280+
},
281+
ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
282+
NameClass::Definition(it) | NameClass::ConstReference(it) => vec![it],
283+
NameClass::PatFieldShorthand { local_def, field_ref } => {
284+
vec![Definition::Local(local_def), Definition::Field(field_ref)]
285+
}
286+
},
287+
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
288+
.and_then(|class| match class {
289+
NameRefClass::Definition(it) => Some(it),
290+
_ => None,
291+
})
292+
.or_else(|| NameClass::classify_lifetime(sema, &lifetime).and_then(NameClass::defined))
293+
.map(|it| vec![it])?,
294+
};
295+
Some(defs)
296+
}
297+
268298
#[cfg(test)]
269299
mod tests {
270300
use crate::fixture;
@@ -773,6 +803,22 @@ fn foo() {
773803
);
774804
}
775805

806+
#[test]
807+
fn test_hl_field_shorthand() {
808+
check(
809+
r#"
810+
struct Struct { field: u32 }
811+
//^^^^^
812+
fn function(field: u32) {
813+
//^^^^^
814+
Struct { field$0 }
815+
//^^^^^ read
816+
//^^^^^ read
817+
}
818+
"#,
819+
);
820+
}
821+
776822
#[test]
777823
fn test_hl_disabled_ref_local() {
778824
let config = HighlightRelatedConfig {

crates/ide/src/references.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,7 @@ pub(crate) fn find_def(
118118
_ => None,
119119
})
120120
.or_else(|| {
121-
NameClass::classify_lifetime(sema, &lifetime).and_then(|class| match class {
122-
NameClass::Definition(it) => Some(it),
123-
_ => None,
124-
})
121+
NameClass::classify_lifetime(sema, &lifetime).and_then(NameClass::defined)
125122
})?,
126123
};
127124
Some(def)

0 commit comments

Comments
 (0)