diff options
| author | bors <bors@rust-lang.org> | 2024-02-19 11:38:14 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-02-19 11:38:14 +0000 |
| commit | d8c8ccc38005c0583d0188a112f88233b151eff0 (patch) | |
| tree | 09dc56becee428e94a193be9cf988034d1a2ff31 | |
| parent | 60982dc8fc2e7862d68bb2b3e3d5d4fff8052de9 (diff) | |
| parent | 91a8f34aeed075427ad4f6c0c6f58f247ac7de42 (diff) | |
| download | rust-d8c8ccc38005c0583d0188a112f88233b151eff0.tar.gz rust-d8c8ccc38005c0583d0188a112f88233b151eff0.zip | |
Auto merge of #16358 - krobelus:fix-redundant-references-with-macros, r=Veykril
Deduplicate references when some of them are in macro expansions EDIT: I wonder if this is a regression, I'll try to investigate. Commit 6a06f6f72 (Deduplicate reference search results, 2022-11-07) deduplicates references within each definition. Apparently our descend_into_macros() stanza returns one definition for each time a name is used in a macro. Each of those definitions has the same set of references. We return them all, leading to many redundant references. Work around this by deduplicating definitions as well. Perhaps there is a better fix to not produce duplicate definitions in the first place. I discovered this working with the "bitflags" macro from the crate of the same name. Fixes #16357
| -rw-r--r-- | crates/rust-analyzer/src/handlers/request.rs | 13 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/lsp/to_proto.rs | 7 | ||||
| -rw-r--r-- | crates/stdx/src/lib.rs | 16 |
3 files changed, 27 insertions, 9 deletions
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index eb9d4bf0f02..04a04395429 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -16,6 +16,7 @@ use ide::{ ReferenceCategory, Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit, }; use ide_db::SymbolKind; +use itertools::Itertools; use lsp_server::ErrorCode; use lsp_types::{ CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, @@ -1055,9 +1056,8 @@ pub(crate) fn handle_references( let exclude_imports = snap.config.find_all_refs_exclude_imports(); let exclude_tests = snap.config.find_all_refs_exclude_tests(); - let refs = match snap.analysis.find_all_refs(position, None)? { - None => return Ok(None), - Some(refs) => refs, + let Some(refs) = snap.analysis.find_all_refs(position, None)? else { + return Ok(None); }; let include_declaration = params.context.include_declaration; @@ -1084,6 +1084,7 @@ pub(crate) fn handle_references( }) .chain(decl) }) + .unique() .filter_map(|frange| to_proto::location(&snap, frange).ok()) .collect(); @@ -1802,10 +1803,10 @@ fn show_ref_command_link( .into_iter() .flat_map(|res| res.references) .flat_map(|(file_id, ranges)| { - ranges.into_iter().filter_map(move |(range, _)| { - to_proto::location(snap, FileRange { file_id, range }).ok() - }) + ranges.into_iter().map(move |(range, _)| FileRange { file_id, range }) }) + .unique() + .filter_map(|range| to_proto::location(snap, range).ok()) .collect(); let title = to_proto::reference_title(locations.len()); let command = to_proto::command::show_references(title, &uri, position, locations); diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index 727007bba08..4101d476cd3 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -904,15 +904,16 @@ pub(crate) fn goto_definition_response( if snap.config.location_link() { let links = targets .into_iter() + .unique_by(|nav| (nav.file_id, nav.full_range, nav.focus_range)) .map(|nav| location_link(snap, src, nav)) .collect::<Cancellable<Vec<_>>>()?; Ok(links.into()) } else { let locations = targets .into_iter() - .map(|nav| { - location(snap, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) - }) + .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) + .unique() + .map(|range| location(snap, range)) .collect::<Cancellable<Vec<_>>>()?; Ok(locations.into()) } diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 9a9ebae74e8..0504ca50b88 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -302,6 +302,22 @@ pub fn slice_tails<T>(this: &[T]) -> impl Iterator<Item = &[T]> { (0..this.len()).map(|i| &this[i..]) } +pub trait IsNoneOr { + type Type; + #[allow(clippy::wrong_self_convention)] + fn is_none_or(self, s: impl FnOnce(Self::Type) -> bool) -> bool; +} +#[allow(unstable_name_collisions)] +impl<T> IsNoneOr for Option<T> { + type Type = T; + fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool { + match self { + Some(v) => f(v), + None => true, + } + } +} + #[cfg(test)] mod tests { use super::*; |
