Deduplicate lsp locations

This commit is contained in:
Lukas Wirth 2024-02-19 12:22:27 +01:00
parent 30b992e95a
commit 91a8f34aee
2 changed files with 12 additions and 28 deletions

View File

@ -2,7 +2,6 @@
//! Protocol. This module specifically handles requests. //! Protocol. This module specifically handles requests.
use std::{ use std::{
collections::HashSet,
fs, fs,
io::Write as _, io::Write as _,
path::PathBuf, path::PathBuf,
@ -14,10 +13,10 @@ use anyhow::Context;
use ide::{ use ide::{
AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, FilePosition, FileRange, AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, FilePosition, FileRange,
HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, RangeLimit, HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, RangeLimit,
ReferenceCategory, ReferenceSearchResult, Runnable, RunnableKind, SingleResolve, SourceChange, ReferenceCategory, Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit,
TextEdit,
}; };
use ide_db::SymbolKind; use ide_db::SymbolKind;
use itertools::Itertools;
use lsp_server::ErrorCode; use lsp_server::ErrorCode;
use lsp_types::{ use lsp_types::{
CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
@ -30,8 +29,6 @@ use lsp_types::{
}; };
use project_model::{ManifestPath, ProjectWorkspace, TargetKind}; use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
use serde_json::json; use serde_json::json;
#[allow(unused_imports)]
use stdx::IsNoneOr;
use stdx::{format_to, never}; use stdx::{format_to, never};
use syntax::{algo, ast, AstNode, TextRange, TextSize}; use syntax::{algo, ast, AstNode, TextRange, TextSize};
use triomphe::Arc; use triomphe::Arc;
@ -1059,10 +1056,9 @@ pub(crate) fn handle_references(
let exclude_imports = snap.config.find_all_refs_exclude_imports(); let exclude_imports = snap.config.find_all_refs_exclude_imports();
let exclude_tests = snap.config.find_all_refs_exclude_tests(); 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); return Ok(None);
}; };
deduplicate_declarations(&mut refs);
let include_declaration = params.context.include_declaration; let include_declaration = params.context.include_declaration;
let locations = refs let locations = refs
@ -1088,23 +1084,13 @@ pub(crate) fn handle_references(
}) })
.chain(decl) .chain(decl)
}) })
.unique()
.filter_map(|frange| to_proto::location(&snap, frange).ok()) .filter_map(|frange| to_proto::location(&snap, frange).ok())
.collect(); .collect();
Ok(Some(locations)) 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( pub(crate) fn handle_formatting(
snap: GlobalStateSnapshot, snap: GlobalStateSnapshot,
params: lsp_types::DocumentFormattingParams, params: lsp_types::DocumentFormattingParams,
@ -1809,10 +1795,7 @@ fn show_ref_command_link(
position: &FilePosition, position: &FilePosition,
) -> Option<lsp_ext::CommandLinkGroup> { ) -> Option<lsp_ext::CommandLinkGroup> {
if snap.config.hover_actions().references && snap.config.client_commands().show_reference { if snap.config.hover_actions().references && snap.config.client_commands().show_reference {
if let Some(mut ref_search_res) = if let Some(ref_search_res) = snap.analysis.find_all_refs(*position, None).unwrap_or(None) {
snap.analysis.find_all_refs(*position, None).unwrap_or(None)
{
deduplicate_declarations(&mut ref_search_res);
let uri = to_proto::url(snap, position.file_id); let uri = to_proto::url(snap, position.file_id);
let line_index = snap.file_line_index(position.file_id).ok()?; let line_index = snap.file_line_index(position.file_id).ok()?;
let position = to_proto::position(&line_index, position.offset); let position = to_proto::position(&line_index, position.offset);
@ -1820,10 +1803,10 @@ fn show_ref_command_link(
.into_iter() .into_iter()
.flat_map(|res| res.references) .flat_map(|res| res.references)
.flat_map(|(file_id, ranges)| { .flat_map(|(file_id, ranges)| {
ranges.into_iter().filter_map(move |(range, _)| { ranges.into_iter().map(move |(range, _)| FileRange { file_id, range })
to_proto::location(snap, FileRange { file_id, range }).ok()
})
}) })
.unique()
.filter_map(|range| to_proto::location(snap, range).ok())
.collect(); .collect();
let title = to_proto::reference_title(locations.len()); let title = to_proto::reference_title(locations.len());
let command = to_proto::command::show_references(title, &uri, position, locations); let command = to_proto::command::show_references(title, &uri, position, locations);

View File

@ -904,15 +904,16 @@ pub(crate) fn goto_definition_response(
if snap.config.location_link() { if snap.config.location_link() {
let links = targets let links = targets
.into_iter() .into_iter()
.unique_by(|nav| (nav.file_id, nav.full_range, nav.focus_range))
.map(|nav| location_link(snap, src, nav)) .map(|nav| location_link(snap, src, nav))
.collect::<Cancellable<Vec<_>>>()?; .collect::<Cancellable<Vec<_>>>()?;
Ok(links.into()) Ok(links.into())
} else { } else {
let locations = targets let locations = targets
.into_iter() .into_iter()
.map(|nav| { .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })
location(snap, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) .unique()
}) .map(|range| location(snap, range))
.collect::<Cancellable<Vec<_>>>()?; .collect::<Cancellable<Vec<_>>>()?;
Ok(locations.into()) Ok(locations.into())
} }