Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/highlight_related.rs')
-rw-r--r--crates/ide/src/highlight_related.rs106
1 files changed, 81 insertions, 25 deletions
diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs
index 4fc2d35538..67ad263fa2 100644
--- a/crates/ide/src/highlight_related.rs
+++ b/crates/ide/src/highlight_related.rs
@@ -6,6 +6,7 @@ use ide_db::{
search::{FileReference, ReferenceAccess, SearchScope},
RootDatabase,
};
+use rustc_hash::FxHashSet;
use syntax::{
ast::{self, LoopBodyOwner},
match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize, T,
@@ -13,6 +14,7 @@ use syntax::{
use crate::{display::TryToNav, references, NavigationTarget};
+#[derive(PartialEq, Eq, Hash)]
pub struct HighlightedRange {
pub range: TextRange,
pub access: Option<ReferenceAccess>,
@@ -70,7 +72,7 @@ fn highlight_references(
syntax: &SyntaxNode,
FilePosition { offset, file_id }: FilePosition,
) -> Option<Vec<HighlightedRange>> {
- let defs = find_defs(sema, syntax, offset)?;
+ let defs = find_defs(sema, syntax, offset);
let usages = defs
.iter()
.flat_map(|&d| {
@@ -99,7 +101,12 @@ fn highlight_references(
})
});
- Some(declarations.chain(usages).collect())
+ let res: FxHashSet<_> = declarations.chain(usages).collect();
+ if res.is_empty() {
+ None
+ } else {
+ Some(res.into_iter().collect())
+ }
}
fn highlight_exit_points(
@@ -270,29 +277,40 @@ fn find_defs(
sema: &Semantics<RootDatabase>,
syntax: &SyntaxNode,
offset: TextSize,
-) -> Option<Vec<Definition>> {
- let defs = match sema.find_node_at_offset_with_descend(syntax, offset)? {
- ast::NameLike::NameRef(name_ref) => match NameRefClass::classify(sema, &name_ref)? {
- NameRefClass::Definition(def) => vec![def],
- NameRefClass::FieldShorthand { local_ref, field_ref } => {
- vec![Definition::Local(local_ref), Definition::Field(field_ref)]
- }
- },
- ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
- NameClass::Definition(it) | NameClass::ConstReference(it) => vec![it],
- NameClass::PatFieldShorthand { local_def, field_ref } => {
- vec![Definition::Local(local_def), Definition::Field(field_ref)]
- }
- },
- ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
- .and_then(|class| match class {
- NameRefClass::Definition(it) => Some(it),
- _ => None,
+) -> FxHashSet<Definition> {
+ sema.find_nodes_at_offset_with_descend(syntax, offset)
+ .flat_map(|name_like| {
+ Some(match name_like {
+ ast::NameLike::NameRef(name_ref) => {
+ match NameRefClass::classify(sema, &name_ref)? {
+ NameRefClass::Definition(def) => vec![def],
+ NameRefClass::FieldShorthand { local_ref, field_ref } => {
+ vec![Definition::Local(local_ref), Definition::Field(field_ref)]
+ }
+ }
+ }
+ ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
+ NameClass::Definition(it) | NameClass::ConstReference(it) => vec![it],
+ NameClass::PatFieldShorthand { local_def, field_ref } => {
+ vec![Definition::Local(local_def), Definition::Field(field_ref)]
+ }
+ },
+ ast::NameLike::Lifetime(lifetime) => {
+ NameRefClass::classify_lifetime(sema, &lifetime)
+ .and_then(|class| match class {
+ NameRefClass::Definition(it) => Some(it),
+ _ => None,
+ })
+ .or_else(|| {
+ NameClass::classify_lifetime(sema, &lifetime)
+ .and_then(NameClass::defined)
+ })
+ .map(|it| vec![it])?
+ }
})
- .or_else(|| NameClass::classify_lifetime(sema, &lifetime).and_then(NameClass::defined))
- .map(|it| vec![it])?,
- };
- Some(defs)
+ })
+ .flatten()
+ .collect()
}
#[cfg(test)]
@@ -393,6 +411,45 @@ fn foo() {
}
#[test]
+ fn test_multi_macro_usage() {
+ check(
+ r#"
+macro_rules! foo {
+ ($ident:ident) => {
+ fn $ident() -> $ident { loop {} }
+ struct $ident;
+ }
+}
+
+foo!(bar$0);
+ // ^^^
+fn foo() {
+ let bar: bar = bar();
+ // ^^^
+ // ^^^
+}
+"#,
+ );
+ check(
+ r#"
+macro_rules! foo {
+ ($ident:ident) => {
+ fn $ident() -> $ident { loop {} }
+ struct $ident;
+ }
+}
+
+foo!(bar);
+ // ^^^
+fn foo() {
+ let bar: bar$0 = bar();
+ // ^^^
+}
+"#,
+ );
+ }
+
+ #[test]
fn test_hl_yield_points() {
check(
r#"
@@ -813,7 +870,6 @@ fn function(field: u32) {
//^^^^^
Struct { field$0 }
//^^^^^ read
- //^^^^^ read
}
"#,
);