about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-02-19 12:22:27 +0100
committerLukas Wirth <lukastw97@gmail.com>2024-02-19 12:23:59 +0100
commit91a8f34aeed075427ad4f6c0c6f58f247ac7de42 (patch)
tree09dc56becee428e94a193be9cf988034d1a2ff31
parent30b992e95a1e437b3e96b0e86373427f0fe2b121 (diff)
downloadrust-91a8f34aeed075427ad4f6c0c6f58f247ac7de42.tar.gz
rust-91a8f34aeed075427ad4f6c0c6f58f247ac7de42.zip
Deduplicate lsp locations
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs33
-rw-r--r--crates/rust-analyzer/src/lsp/to_proto.rs7
2 files changed, 12 insertions, 28 deletions
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index a677cea31b5..04a04395429 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -2,7 +2,6 @@
 //! Protocol. This module specifically handles requests.
 
 use std::{
-    collections::HashSet,
     fs,
     io::Write as _,
     path::PathBuf,
@@ -14,10 +13,10 @@ use anyhow::Context;
 use ide::{
     AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, FilePosition, FileRange,
     HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, RangeLimit,
-    ReferenceCategory, ReferenceSearchResult, Runnable, RunnableKind, SingleResolve, SourceChange,
-    TextEdit,
+    ReferenceCategory, Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit,
 };
 use ide_db::SymbolKind;
+use itertools::Itertools;
 use lsp_server::ErrorCode;
 use lsp_types::{
     CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
@@ -30,8 +29,6 @@ use lsp_types::{
 };
 use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
 use serde_json::json;
-#[allow(unused_imports)]
-use stdx::IsNoneOr;
 use stdx::{format_to, never};
 use syntax::{algo, ast, AstNode, TextRange, TextSize};
 use triomphe::Arc;
@@ -1059,10 +1056,9 @@ 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 Some(mut refs) = snap.analysis.find_all_refs(position, None)? else {
+    let Some(refs) = snap.analysis.find_all_refs(position, None)? else {
         return Ok(None);
     };
-    deduplicate_declarations(&mut refs);
 
     let include_declaration = params.context.include_declaration;
     let locations = refs
@@ -1088,23 +1084,13 @@ pub(crate) fn handle_references(
                 })
                 .chain(decl)
         })
+        .unique()
         .filter_map(|frange| to_proto::location(&snap, frange).ok())
         .collect();
 
     Ok(Some(locations))
 }
 
-fn deduplicate_declarations(refs: &mut Vec<ReferenceSearchResult>) {
-    if refs.iter().filter(|decl| decl.declaration.is_some()).take(2).count() > 1 {
-        let mut seen_navigation_targets = HashSet::new();
-        refs.retain(|res| {
-            res.declaration
-                .as_ref()
-                .is_none_or(|decl| seen_navigation_targets.insert(decl.nav.clone()))
-        });
-    }
-}
-
 pub(crate) fn handle_formatting(
     snap: GlobalStateSnapshot,
     params: lsp_types::DocumentFormattingParams,
@@ -1809,10 +1795,7 @@ fn show_ref_command_link(
     position: &FilePosition,
 ) -> Option<lsp_ext::CommandLinkGroup> {
     if snap.config.hover_actions().references && snap.config.client_commands().show_reference {
-        if let Some(mut ref_search_res) =
-            snap.analysis.find_all_refs(*position, None).unwrap_or(None)
-        {
-            deduplicate_declarations(&mut ref_search_res);
+        if let Some(ref_search_res) = snap.analysis.find_all_refs(*position, None).unwrap_or(None) {
             let uri = to_proto::url(snap, position.file_id);
             let line_index = snap.file_line_index(position.file_id).ok()?;
             let position = to_proto::position(&line_index, position.offset);
@@ -1820,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())
     }