fix: Respect textual length of paths in find-path

This commit is contained in:
Lukas Wirth 2024-02-16 10:54:54 +01:00
parent b9b0d29b8e
commit c00c9ee959
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]; const STD_CRATES: [Name; 3] = [known::std, known::core, known::alloc];
let choose = |new_path: (ModPath, _), old_path: (ModPath, _)| { let choose = |new: (ModPath, _), old: (ModPath, _)| {
let new_has_prelude = new_path.0.segments().iter().any(|seg| seg == &known::prelude); let (new_path, _) = &new;
let old_has_prelude = old_path.0.segments().iter().any(|seg| seg == &known::prelude); 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) { match (new_has_prelude, old_has_prelude, prefer_prelude) {
(true, false, true) | (false, true, false) => new_path, (true, false, true) | (false, true, false) => new,
(true, false, false) | (false, true, true) => old_path, (true, false, false) | (false, true, true) => old,
// no prelude difference in the paths, so pick the smaller one // no prelude difference in the paths, so pick the shorter one
(true, true, _) | (false, false, _) => { (true, true, _) | (false, false, _) => {
if new_path.0.len() < old_path.0.len() { let new_path_is_shorter = new_path
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 { } else {
old_path old
} }
} }
} }
@ -469,8 +476,8 @@ fn select_best_path(
let rank = match prefer_no_std { let rank = match prefer_no_std {
false => |name: &Name| match name { false => |name: &Name| match name {
name if name == &known::core => 0, name if name == &known::core => 0,
name if name == &known::alloc => 0, name if name == &known::alloc => 1,
name if name == &known::std => 1, name if name == &known::std => 2,
_ => unreachable!(), _ => unreachable!(),
}, },
true => |name: &Name| match name { true => |name: &Name| match name {
@ -1539,4 +1546,38 @@ pub mod foo {
"krate::prelude::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>, tail: Option<ExprId>,
}, },
Const(ConstBlockId), Const(ConstBlockId),
// FIXME: Fold this into Block with an unsafe flag?
Unsafe { Unsafe {
id: Option<BlockId>, id: Option<BlockId>,
statements: Box<[Statement]>, 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 { pub fn is_ident(&self) -> bool {
self.as_ident().is_some() self.as_ident().is_some()
} }