2917: Prefer imports starting with std r=matklad a=SomeoneToIgnore

Closes https://github.com/rust-analyzer/rust-analyzer/issues/2915

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
This commit is contained in:
bors[bot] 2020-01-28 16:22:18 +00:00 committed by GitHub
commit 3bdf2e0972
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 14 deletions

View File

@ -7,10 +7,39 @@
visibility::Visibility, visibility::Visibility,
CrateId, ModuleDefId, ModuleId, CrateId, ModuleDefId, ModuleId,
}; };
use hir_expand::name::Name; use hir_expand::name::{known, Name};
use test_utils::tested_by;
const MAX_PATH_LEN: usize = 15; const MAX_PATH_LEN: usize = 15;
impl ModPath {
fn starts_with_std(&self) -> bool {
self.segments.first().filter(|&first_segment| first_segment == &known::std).is_some()
}
// When std library is present, paths starting with `std::`
// should be preferred over paths starting with `core::` and `alloc::`
fn should_start_with_std(&self) -> bool {
self.segments
.first()
.filter(|&first_segment| {
first_segment == &known::alloc || first_segment == &known::core
})
.is_some()
}
fn len(&self) -> usize {
self.segments.len()
+ match self.kind {
PathKind::Plain => 0,
PathKind::Super(i) => i as usize,
PathKind::Crate => 1,
PathKind::Abs => 0,
PathKind::DollarCrate(_) => 1,
}
}
}
// FIXME: handle local items // FIXME: handle local items
/// Find a path that can be used to refer to a certain item. This can depend on /// Find a path that can be used to refer to a certain item. This can depend on
@ -112,23 +141,27 @@ fn find_path_inner(
Some(path) => path, Some(path) => path,
}; };
path.segments.push(name); path.segments.push(name);
if path_len(&path) < best_path_len {
best_path_len = path_len(&path); let new_path =
best_path = Some(path); if let Some(best_path) = best_path { select_best_path(best_path, path) } else { path };
} best_path_len = new_path.len();
best_path = Some(new_path);
} }
best_path best_path
} }
fn path_len(path: &ModPath) -> usize { fn select_best_path(old_path: ModPath, new_path: ModPath) -> ModPath {
path.segments.len() if old_path.starts_with_std() && new_path.should_start_with_std() {
+ match path.kind { tested_by!(prefer_std_paths);
PathKind::Plain => 0, old_path
PathKind::Super(i) => i as usize, } else if new_path.starts_with_std() && old_path.should_start_with_std() {
PathKind::Crate => 1, tested_by!(prefer_std_paths);
PathKind::Abs => 0, new_path
PathKind::DollarCrate(_) => 1, } else if new_path.len() < old_path.len() {
} new_path
} else {
old_path
}
} }
fn find_importable_locations( fn find_importable_locations(
@ -201,6 +234,7 @@ mod tests {
use hir_expand::hygiene::Hygiene; use hir_expand::hygiene::Hygiene;
use ra_db::fixture::WithFixture; use ra_db::fixture::WithFixture;
use ra_syntax::ast::AstNode; use ra_syntax::ast::AstNode;
use test_utils::covers;
/// `code` needs to contain a cursor marker; checks that `find_path` for the /// `code` needs to contain a cursor marker; checks that `find_path` for the
/// item the `path` refers to returns that same path when called from the /// item the `path` refers to returns that same path when called from the
@ -452,4 +486,41 @@ fn import_cycle() {
"#; "#;
check_found_path(code, "crate::foo::S"); check_found_path(code, "crate::foo::S");
} }
#[test]
fn prefer_std_paths_over_alloc() {
covers!(prefer_std_paths);
let code = r#"
//- /main.rs crate:main deps:alloc,std
<|>
//- /std.rs crate:std deps:alloc
pub mod sync {
pub use alloc::sync::Arc;
}
//- /zzz.rs crate:alloc
pub mod sync {
pub struct Arc;
}
"#;
check_found_path(code, "std::sync::Arc");
}
#[test]
fn prefer_shorter_paths_if_not_alloc() {
let code = r#"
//- /main.rs crate:main deps:megaalloc,std
<|>
//- /std.rs crate:std deps:megaalloc
pub mod sync {
pub use megaalloc::sync::Arc;
}
//- /zzz.rs crate:megaalloc
pub struct Arc;
"#;
check_found_path(code, "megaalloc::Arc");
}
} }

View File

@ -13,4 +13,5 @@
macro_dollar_crate_self macro_dollar_crate_self
macro_dollar_crate_other macro_dollar_crate_other
infer_resolve_while_let infer_resolve_while_let
prefer_std_paths
); );

View File

@ -141,6 +141,8 @@ macro_rules! known_names {
macro_rules, macro_rules,
// Components of known path (value or mod name) // Components of known path (value or mod name)
std, std,
core,
alloc,
iter, iter,
ops, ops,
future, future,