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.rs | 106 |
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 } "#, ); |