Auto merge of #16582 - Veykril:find-path-length, r=Veykril

fix: Respect textual length of paths in find-path

Fixes https://github.com/rust-lang/rust-analyzer/issues/16572
This commit is contained in:
bors 2024-02-16 09:58:11 +00:00
commit a01655552d
3 changed files with 68 additions and 11 deletions

View File

@ -447,18 +447,25 @@ fn select_best_path(
}
const STD_CRATES: [Name; 3] = [known::std, known::core, known::alloc];
let choose = |new_path: (ModPath, _), old_path: (ModPath, _)| {
let new_has_prelude = new_path.0.segments().iter().any(|seg| seg == &known::prelude);
let old_has_prelude = old_path.0.segments().iter().any(|seg| seg == &known::prelude);
let choose = |new: (ModPath, _), old: (ModPath, _)| {
let (new_path, _) = &new;
let (old_path, _) = &old;
let new_has_prelude = new_path.segments().iter().any(|seg| seg == &known::prelude);
let old_has_prelude = old_path.segments().iter().any(|seg| seg == &known::prelude);
match (new_has_prelude, old_has_prelude, prefer_prelude) {
(true, false, true) | (false, true, false) => new_path,
(true, false, false) | (false, true, true) => old_path,
// no prelude difference in the paths, so pick the smaller one
(true, false, true) | (false, true, false) => new,
(true, false, false) | (false, true, true) => old,
// no prelude difference in the paths, so pick the shorter one
(true, true, _) | (false, false, _) => {
if new_path.0.len() < old_path.0.len() {
new_path
let new_path_is_shorter = new_path
.len()
.cmp(&old_path.len())
.then_with(|| new_path.textual_len().cmp(&old_path.textual_len()))
.is_lt();
if new_path_is_shorter {
new
} else {
old_path
old
}
}
}
@ -469,8 +476,8 @@ fn select_best_path(
let rank = match prefer_no_std {
false => |name: &Name| match name {
name if name == &known::core => 0,
name if name == &known::alloc => 0,
name if name == &known::std => 1,
name if name == &known::alloc => 1,
name if name == &known::std => 2,
_ => unreachable!(),
},
true => |name: &Name| match name {
@ -1539,4 +1546,38 @@ pub mod foo {
"krate::prelude::Foo",
);
}
#[test]
fn respect_segment_length() {
check_found_path(
r#"
//- /main.rs crate:main deps:petgraph
$0
//- /petgraph.rs crate:petgraph
pub mod graph {
pub use crate::graph_impl::{
NodeIndex
};
}
mod graph_impl {
pub struct NodeIndex<Ix>(Ix);
}
pub mod stable_graph {
#[doc(no_inline)]
pub use crate::graph::{NodeIndex};
}
pub mod prelude {
#[doc(no_inline)]
pub use crate::graph::{NodeIndex};
}
"#,
"petgraph::graph::NodeIndex",
"petgraph::graph::NodeIndex",
"petgraph::graph::NodeIndex",
"petgraph::graph::NodeIndex",
);
}
}

View File

@ -182,6 +182,7 @@ pub enum Expr {
tail: Option<ExprId>,
},
Const(ConstBlockId),
// FIXME: Fold this into Block with an unsafe flag?
Unsafe {
id: Option<BlockId>,
statements: Box<[Statement]>,

View File

@ -94,6 +94,21 @@ pub fn len(&self) -> usize {
}
}
pub fn textual_len(&self) -> usize {
let base = match self.kind {
PathKind::Plain => 0,
PathKind::Super(0) => "self".len(),
PathKind::Super(i) => "super".len() * i as usize,
PathKind::Crate => "crate".len(),
PathKind::Abs => 0,
PathKind::DollarCrate(_) => "$crate".len(),
};
self.segments()
.iter()
.map(|segment| segment.as_str().map_or(0, str::len))
.fold(base, core::ops::Add::add)
}
pub fn is_ident(&self) -> bool {
self.as_ident().is_some()
}