mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 04:23:25 +00:00
Slightly cleanup import_assets module
This commit is contained in:
parent
02b844e9fb
commit
01b410c69a
2 changed files with 86 additions and 64 deletions
|
@ -63,13 +63,13 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
|
||||||
|
|
||||||
fn import_group_message(import_candidate: &ImportCandidate) -> GroupLabel {
|
fn import_group_message(import_candidate: &ImportCandidate) -> GroupLabel {
|
||||||
let name = match import_candidate {
|
let name = match import_candidate {
|
||||||
ImportCandidate::UnqualifiedName(name) => format!("Import {}", name),
|
ImportCandidate::UnqualifiedName(candidate)
|
||||||
ImportCandidate::QualifierStart(qualifier_start) => format!("Import {}", qualifier_start),
|
| ImportCandidate::QualifierStart(candidate) => format!("Import {}", &candidate.name),
|
||||||
ImportCandidate::TraitAssocItem(_, trait_assoc_item_name) => {
|
ImportCandidate::TraitAssocItem(candidate) => {
|
||||||
format!("Import a trait for item {}", trait_assoc_item_name)
|
format!("Import a trait for item {}", &candidate.name)
|
||||||
}
|
}
|
||||||
ImportCandidate::TraitMethod(_, trait_method_name) => {
|
ImportCandidate::TraitMethod(candidate) => {
|
||||||
format!("Import a trait for method {}", trait_method_name)
|
format!("Import a trait for method {}", &candidate.name)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
GroupLabel(name)
|
GroupLabel(name)
|
||||||
|
|
|
@ -12,18 +12,29 @@ use crate::assist_config::InsertUseConfig;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum ImportCandidate {
|
pub(crate) enum ImportCandidate {
|
||||||
/// Simple name like 'HashMap'
|
/// Simple name like 'HashMap'
|
||||||
UnqualifiedName(String),
|
UnqualifiedName(PathImportCandidate),
|
||||||
/// First part of the qualified name.
|
/// First part of the qualified name.
|
||||||
/// For 'std::collections::HashMap', that will be 'std'.
|
/// For 'std::collections::HashMap', that will be 'std'.
|
||||||
QualifierStart(String),
|
QualifierStart(PathImportCandidate),
|
||||||
/// A trait associated function (with no self parameter) or associated constant.
|
/// A trait associated function (with no self parameter) or associated constant.
|
||||||
/// For 'test_mod::TestEnum::test_function', `Type` is the `test_mod::TestEnum` expression type
|
/// For 'test_mod::TestEnum::test_function', `ty` is the `test_mod::TestEnum` expression type
|
||||||
/// and `String` is the `test_function`
|
/// and `name` is the `test_function`
|
||||||
TraitAssocItem(hir::Type, String),
|
TraitAssocItem(TraitImportCandidate),
|
||||||
/// A trait method with self parameter.
|
/// A trait method with self parameter.
|
||||||
/// For 'test_enum.test_method()', `Type` is the `test_enum` expression type
|
/// For 'test_enum.test_method()', `ty` is the `test_enum` expression type
|
||||||
/// and `String` is the `test_method`
|
/// and `name` is the `test_method`
|
||||||
TraitMethod(hir::Type, String),
|
TraitMethod(TraitImportCandidate),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct TraitImportCandidate {
|
||||||
|
pub ty: hir::Type,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct PathImportCandidate {
|
||||||
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -74,10 +85,10 @@ impl ImportAssets {
|
||||||
|
|
||||||
fn get_search_query(&self) -> &str {
|
fn get_search_query(&self) -> &str {
|
||||||
match &self.import_candidate {
|
match &self.import_candidate {
|
||||||
ImportCandidate::UnqualifiedName(name) => name,
|
ImportCandidate::UnqualifiedName(candidate)
|
||||||
ImportCandidate::QualifierStart(qualifier_start) => qualifier_start,
|
| ImportCandidate::QualifierStart(candidate) => &candidate.name,
|
||||||
ImportCandidate::TraitAssocItem(_, trait_assoc_item_name) => trait_assoc_item_name,
|
ImportCandidate::TraitAssocItem(candidate)
|
||||||
ImportCandidate::TraitMethod(_, trait_method_name) => trait_method_name,
|
| ImportCandidate::TraitMethod(candidate) => &candidate.name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,27 +117,29 @@ impl ImportAssets {
|
||||||
prefixed: Option<hir::PrefixKind>,
|
prefixed: Option<hir::PrefixKind>,
|
||||||
) -> BTreeSet<hir::ModPath> {
|
) -> BTreeSet<hir::ModPath> {
|
||||||
let db = sema.db;
|
let db = sema.db;
|
||||||
|
let mut trait_candidates = FxHashSet::default();
|
||||||
let current_crate = self.module_with_name_to_import.krate();
|
let current_crate = self.module_with_name_to_import.krate();
|
||||||
imports_locator::find_imports(sema, current_crate, &self.get_search_query())
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|candidate| match &self.import_candidate {
|
|
||||||
ImportCandidate::TraitAssocItem(assoc_item_type, _) => {
|
|
||||||
let located_assoc_item = match candidate {
|
|
||||||
Either::Left(ModuleDef::Function(located_function)) => located_function
|
|
||||||
.as_assoc_item(db)
|
|
||||||
.map(|assoc| assoc.container(db))
|
|
||||||
.and_then(Self::assoc_to_trait),
|
|
||||||
Either::Left(ModuleDef::Const(located_const)) => located_const
|
|
||||||
.as_assoc_item(db)
|
|
||||||
.map(|assoc| assoc.container(db))
|
|
||||||
.and_then(Self::assoc_to_trait),
|
|
||||||
_ => None,
|
|
||||||
}?;
|
|
||||||
|
|
||||||
let mut trait_candidates = FxHashSet::default();
|
let filter = |candidate: Either<hir::ModuleDef, hir::MacroDef>| {
|
||||||
|
trait_candidates.clear();
|
||||||
|
match &self.import_candidate {
|
||||||
|
ImportCandidate::TraitAssocItem(trait_candidate) => {
|
||||||
|
let located_assoc_item = match candidate {
|
||||||
|
Either::Left(ModuleDef::Function(located_function)) => {
|
||||||
|
located_function.as_assoc_item(db)
|
||||||
|
}
|
||||||
|
Either::Left(ModuleDef::Const(located_const)) => {
|
||||||
|
located_const.as_assoc_item(db)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
.map(|assoc| assoc.container(db))
|
||||||
|
.and_then(Self::assoc_to_trait)?;
|
||||||
|
|
||||||
trait_candidates.insert(located_assoc_item.into());
|
trait_candidates.insert(located_assoc_item.into());
|
||||||
|
|
||||||
assoc_item_type
|
trait_candidate
|
||||||
|
.ty
|
||||||
.iterate_path_candidates(
|
.iterate_path_candidates(
|
||||||
db,
|
db,
|
||||||
current_crate,
|
current_crate,
|
||||||
|
@ -137,7 +150,7 @@ impl ImportAssets {
|
||||||
.map(ModuleDef::from)
|
.map(ModuleDef::from)
|
||||||
.map(Either::Left)
|
.map(Either::Left)
|
||||||
}
|
}
|
||||||
ImportCandidate::TraitMethod(function_callee, _) => {
|
ImportCandidate::TraitMethod(trait_candidate) => {
|
||||||
let located_assoc_item =
|
let located_assoc_item =
|
||||||
if let Either::Left(ModuleDef::Function(located_function)) = candidate {
|
if let Either::Left(ModuleDef::Function(located_function)) = candidate {
|
||||||
located_function
|
located_function
|
||||||
|
@ -148,10 +161,10 @@ impl ImportAssets {
|
||||||
None
|
None
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let mut trait_candidates = FxHashSet::default();
|
|
||||||
trait_candidates.insert(located_assoc_item.into());
|
trait_candidates.insert(located_assoc_item.into());
|
||||||
|
|
||||||
function_callee
|
trait_candidate
|
||||||
|
.ty
|
||||||
.iterate_method_candidates(
|
.iterate_method_candidates(
|
||||||
db,
|
db,
|
||||||
current_crate,
|
current_crate,
|
||||||
|
@ -165,12 +178,14 @@ impl ImportAssets {
|
||||||
.map(Either::Left)
|
.map(Either::Left)
|
||||||
}
|
}
|
||||||
_ => Some(candidate),
|
_ => Some(candidate),
|
||||||
})
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
imports_locator::find_imports(sema, current_crate, &self.get_search_query())
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(filter)
|
||||||
.filter_map(|candidate| {
|
.filter_map(|candidate| {
|
||||||
let item: hir::ItemInNs = match candidate {
|
let item: hir::ItemInNs = candidate.either(Into::into, Into::into);
|
||||||
Either::Left(module_def) => module_def.into(),
|
|
||||||
Either::Right(macro_def) => macro_def.into(),
|
|
||||||
};
|
|
||||||
if let Some(prefix_kind) = prefixed {
|
if let Some(prefix_kind) = prefixed {
|
||||||
self.module_with_name_to_import.find_use_path_prefixed(db, item, prefix_kind)
|
self.module_with_name_to_import.find_use_path_prefixed(db, item, prefix_kind)
|
||||||
} else {
|
} else {
|
||||||
|
@ -196,13 +211,13 @@ impl ImportCandidate {
|
||||||
sema: &Semantics<RootDatabase>,
|
sema: &Semantics<RootDatabase>,
|
||||||
method_call: &ast::MethodCallExpr,
|
method_call: &ast::MethodCallExpr,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
if sema.resolve_method_call(method_call).is_some() {
|
match sema.resolve_method_call(method_call) {
|
||||||
return None;
|
Some(_) => None,
|
||||||
|
None => Some(Self::TraitMethod(TraitImportCandidate {
|
||||||
|
ty: sema.type_of_expr(&method_call.receiver()?)?,
|
||||||
|
name: method_call.name_ref()?.syntax().to_string(),
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
Some(Self::TraitMethod(
|
|
||||||
sema.type_of_expr(&method_call.receiver()?)?,
|
|
||||||
method_call.name_ref()?.syntax().to_string(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn for_regular_path(
|
fn for_regular_path(
|
||||||
|
@ -214,7 +229,7 @@ impl ImportCandidate {
|
||||||
}
|
}
|
||||||
|
|
||||||
let segment = path_under_caret.segment()?;
|
let segment = path_under_caret.segment()?;
|
||||||
if let Some(qualifier) = path_under_caret.qualifier() {
|
let candidate = if let Some(qualifier) = path_under_caret.qualifier() {
|
||||||
let qualifier_start = qualifier.syntax().descendants().find_map(ast::NameRef::cast)?;
|
let qualifier_start = qualifier.syntax().descendants().find_map(ast::NameRef::cast)?;
|
||||||
let qualifier_start_path =
|
let qualifier_start_path =
|
||||||
qualifier_start.syntax().ancestors().find_map(ast::Path::cast)?;
|
qualifier_start.syntax().ancestors().find_map(ast::Path::cast)?;
|
||||||
|
@ -224,23 +239,30 @@ impl ImportCandidate {
|
||||||
} else {
|
} else {
|
||||||
sema.resolve_path(&qualifier)?
|
sema.resolve_path(&qualifier)?
|
||||||
};
|
};
|
||||||
if let hir::PathResolution::Def(hir::ModuleDef::Adt(assoc_item_path)) =
|
match qualifier_resolution {
|
||||||
qualifier_resolution
|
hir::PathResolution::Def(hir::ModuleDef::Adt(assoc_item_path)) => {
|
||||||
{
|
ImportCandidate::TraitAssocItem(TraitImportCandidate {
|
||||||
Some(ImportCandidate::TraitAssocItem(
|
ty: assoc_item_path.ty(sema.db),
|
||||||
assoc_item_path.ty(sema.db),
|
name: segment.syntax().to_string(),
|
||||||
segment.syntax().to_string(),
|
})
|
||||||
))
|
}
|
||||||
} else {
|
_ => return None,
|
||||||
None
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(ImportCandidate::QualifierStart(qualifier_start.syntax().to_string()))
|
ImportCandidate::QualifierStart(PathImportCandidate {
|
||||||
|
name: qualifier_start.syntax().to_string(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(ImportCandidate::UnqualifiedName(
|
ImportCandidate::UnqualifiedName(PathImportCandidate {
|
||||||
segment.syntax().descendants().find_map(ast::NameRef::cast)?.syntax().to_string(),
|
name: segment
|
||||||
))
|
.syntax()
|
||||||
}
|
.descendants()
|
||||||
|
.find_map(ast::NameRef::cast)?
|
||||||
|
.syntax()
|
||||||
|
.to_string(),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
Some(candidate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue