mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Fix some tests
This commit is contained in:
parent
582cee2cdf
commit
d386481fac
4 changed files with 143 additions and 49 deletions
|
@ -97,7 +97,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
|
|||
.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
|
||||
.into_iter()
|
||||
.map(|import| {
|
||||
let proposed_def = match import.item_to_import() {
|
||||
let proposed_def = match import.item_to_display() {
|
||||
hir::ItemInNs::Types(id) => ScopeDef::ModuleDef(id.into()),
|
||||
hir::ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()),
|
||||
hir::ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()),
|
||||
|
@ -809,7 +809,7 @@ fn main() {
|
|||
#[test]
|
||||
fn unresolved_assoc_item_container() {
|
||||
check_edit(
|
||||
"Item",
|
||||
"TEST_ASSOC",
|
||||
r#"
|
||||
mod foo {
|
||||
pub struct Item;
|
||||
|
@ -820,7 +820,7 @@ mod foo {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
Item::TEST_A$0;
|
||||
Item::TEST_A$0
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
|
@ -844,7 +844,7 @@ fn main() {
|
|||
#[test]
|
||||
fn unresolved_assoc_item_container_with_path() {
|
||||
check_edit(
|
||||
"Item",
|
||||
"TEST_ASSOC",
|
||||
r#"
|
||||
mod foo {
|
||||
pub mod bar {
|
||||
|
@ -857,7 +857,7 @@ mod foo {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
bar::Item::TEST_A$0;
|
||||
bar::Item::TEST_A$0
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
|
@ -876,6 +876,61 @@ mod foo {
|
|||
fn main() {
|
||||
bar::Item::TEST_ASSOC
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unresolved_assoc_item_container_and_trait_with_path() {
|
||||
check_edit(
|
||||
"TEST_ASSOC",
|
||||
r#"
|
||||
mod foo {
|
||||
pub mod bar {
|
||||
pub trait SomeTrait {
|
||||
const TEST_ASSOC: usize;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod baz {
|
||||
use super::bar::SomeTrait;
|
||||
|
||||
pub struct Item;
|
||||
|
||||
impl SomeTrait for Item {
|
||||
const TEST_ASSOC: usize = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
baz::Item::TEST_A$0
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
use foo::{bar::SomeTrait, baz};
|
||||
|
||||
mod foo {
|
||||
pub mod bar {
|
||||
pub trait SomeTrait {
|
||||
const TEST_ASSOC: usize;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod baz {
|
||||
use super::bar::SomeTrait;
|
||||
|
||||
pub struct Item;
|
||||
|
||||
impl SomeTrait for Item {
|
||||
const TEST_ASSOC: usize = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
baz::Item::TEST_ASSOC
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,10 @@ mod builder_ext;
|
|||
use hir::{
|
||||
AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type,
|
||||
};
|
||||
use ide_db::{helpers::SnippetCap, RootDatabase, SymbolKind};
|
||||
use ide_db::{
|
||||
helpers::{item_name, SnippetCap},
|
||||
RootDatabase, SymbolKind,
|
||||
};
|
||||
use syntax::TextRange;
|
||||
|
||||
use crate::{
|
||||
|
@ -56,7 +59,7 @@ pub(crate) fn render_resolution_with_import<'a>(
|
|||
ScopeDef::ModuleDef(ModuleDef::Function(f)) => f.name(ctx.completion.db).to_string(),
|
||||
ScopeDef::ModuleDef(ModuleDef::Const(c)) => c.name(ctx.completion.db)?.to_string(),
|
||||
ScopeDef::ModuleDef(ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db).to_string(),
|
||||
_ => import_edit.import.display_path().segments().last()?.to_string(),
|
||||
_ => item_name(ctx.db(), import_edit.import.item_to_display())?.to_string(),
|
||||
};
|
||||
Render::new(ctx).render_resolution(local_name, Some(import_edit), resolution).map(|mut item| {
|
||||
item.completion_kind = CompletionKind::Magic;
|
||||
|
|
|
@ -2,11 +2,19 @@
|
|||
pub mod insert_use;
|
||||
pub mod import_assets;
|
||||
|
||||
use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait};
|
||||
use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait};
|
||||
use syntax::ast::{self, make};
|
||||
|
||||
use crate::RootDatabase;
|
||||
|
||||
pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> {
|
||||
match item {
|
||||
ItemInNs::Types(module_def_id) => ModuleDef::from(module_def_id).name(db),
|
||||
ItemInNs::Values(module_def_id) => ModuleDef::from(module_def_id).name(db),
|
||||
ItemInNs::Macros(macro_def_id) => MacroDef::from(macro_def_id).name(db),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the mod path struct into its ast representation.
|
||||
pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
|
||||
let _p = profile::span("mod_path_to_ast");
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
//! Look up accessible paths for items.
|
||||
use either::Either;
|
||||
use hir::{
|
||||
AsAssocItem, AssocItem, Crate, ItemInNs, MacroDef, ModPath, Module, ModuleDef, Name,
|
||||
PrefixKind, Semantics,
|
||||
AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module,
|
||||
ModuleDef, PathResolution, PrefixKind, Semantics, Type,
|
||||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
use syntax::{ast, AstNode};
|
||||
|
@ -12,6 +12,8 @@ use crate::{
|
|||
RootDatabase,
|
||||
};
|
||||
|
||||
use super::item_name;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ImportCandidate {
|
||||
// A path, qualified (`std::collections::HashMap`) or not (`HashMap`).
|
||||
|
@ -28,7 +30,7 @@ pub enum ImportCandidate {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct TraitImportCandidate {
|
||||
pub receiver_ty: hir::Type,
|
||||
pub receiver_ty: Type,
|
||||
pub name: NameToImport,
|
||||
}
|
||||
|
||||
|
@ -62,7 +64,7 @@ impl NameToImport {
|
|||
#[derive(Debug)]
|
||||
pub struct ImportAssets {
|
||||
import_candidate: ImportCandidate,
|
||||
module_with_candidate: hir::Module,
|
||||
module_with_candidate: Module,
|
||||
}
|
||||
|
||||
impl ImportAssets {
|
||||
|
@ -104,7 +106,7 @@ impl ImportAssets {
|
|||
|
||||
pub fn for_fuzzy_method_call(
|
||||
module_with_method_call: Module,
|
||||
receiver_ty: hir::Type,
|
||||
receiver_ty: Type,
|
||||
fuzzy_method_name: String,
|
||||
) -> Option<Self> {
|
||||
Some(Self {
|
||||
|
@ -184,7 +186,7 @@ impl ImportAssets {
|
|||
fn search_for(
|
||||
&self,
|
||||
sema: &Semantics<RootDatabase>,
|
||||
prefixed: Option<hir::PrefixKind>,
|
||||
prefixed: Option<PrefixKind>,
|
||||
) -> Vec<LocatedImport> {
|
||||
let current_crate = self.module_with_candidate.krate();
|
||||
|
||||
|
@ -223,7 +225,7 @@ impl ImportAssets {
|
|||
fn applicable_defs(
|
||||
&self,
|
||||
db: &RootDatabase,
|
||||
prefixed: Option<hir::PrefixKind>,
|
||||
prefixed: Option<PrefixKind>,
|
||||
unfiltered_defs: impl Iterator<Item = Either<ModuleDef, MacroDef>>,
|
||||
) -> FxHashSet<LocatedImport> {
|
||||
let current_crate = self.module_with_candidate.krate();
|
||||
|
@ -266,10 +268,10 @@ fn path_applicable_imports(
|
|||
let (assoc_original, candidate) = match def {
|
||||
Either::Left(module_def) => match module_def.as_assoc_item(db) {
|
||||
Some(assoc_item) => match assoc_item.container(db) {
|
||||
hir::AssocItemContainer::Trait(trait_) => {
|
||||
AssocItemContainer::Trait(trait_) => {
|
||||
(Some(module_def), ItemInNs::from(ModuleDef::from(trait_)))
|
||||
}
|
||||
hir::AssocItemContainer::Impl(impl_) => (
|
||||
AssocItemContainer::Impl(impl_) => (
|
||||
Some(module_def),
|
||||
ItemInNs::from(ModuleDef::from(impl_.target_ty(db).as_adt()?)),
|
||||
),
|
||||
|
@ -296,6 +298,7 @@ fn path_applicable_imports(
|
|||
};
|
||||
|
||||
// TODO kb need to remove turbofish from the qualifier, maybe use the segments instead?
|
||||
// TODO kb sorting is changed now, return back?
|
||||
let unresolved_qualifier_string = unresolved_qualifier.to_string();
|
||||
let unresolved_first_segment_string = unresolved_first_segment.to_string();
|
||||
|
||||
|
@ -305,38 +308,35 @@ fn path_applicable_imports(
|
|||
candidate_path_string.contains(&unresolved_qualifier_string)
|
||||
&& candidate_path_string.contains(&unresolved_first_segment_string)
|
||||
})
|
||||
// TODO kb need to adjust the return type: I get the results rendered rather badly
|
||||
.filter_map(|(candidate_path, (assoc_original, candidate))| {
|
||||
if let Some(assoc_original) = assoc_original {
|
||||
if item_name(db, candidate)?.to_string() == unresolved_first_segment_string {
|
||||
return Some(LocatedImport::new(
|
||||
candidate_path.clone(),
|
||||
ItemInNs::from(assoc_original),
|
||||
Some((candidate_path, candidate)),
|
||||
));
|
||||
}
|
||||
}
|
||||
let found_segment_resolution = item_name(db, candidate)
|
||||
.map(|name| name.to_string() == unresolved_first_segment_string)
|
||||
.unwrap_or(false);
|
||||
let (import_path, item_to_import) = if found_segment_resolution {
|
||||
(candidate_path.clone(), candidate)
|
||||
} else {
|
||||
let matching_module =
|
||||
module_with_matching_name(db, &unresolved_first_segment_string, candidate)?;
|
||||
let module_item = ItemInNs::from(ModuleDef::from(matching_module));
|
||||
(import_path_locator(module_item)?, module_item)
|
||||
};
|
||||
|
||||
let matching_module =
|
||||
module_with_matching_name(db, &unresolved_first_segment_string, candidate)?;
|
||||
let item = ItemInNs::from(ModuleDef::from(matching_module));
|
||||
Some(LocatedImport::new(
|
||||
import_path_locator(item)?,
|
||||
item,
|
||||
Some((candidate_path, candidate)),
|
||||
))
|
||||
Some(match assoc_original {
|
||||
Some(assoc_original) => LocatedImport::new(
|
||||
import_path.clone(),
|
||||
item_to_import,
|
||||
Some((import_path, ItemInNs::from(assoc_original))),
|
||||
),
|
||||
None => LocatedImport::new(
|
||||
import_path,
|
||||
item_to_import,
|
||||
if found_segment_resolution { None } else { Some((candidate_path, candidate)) },
|
||||
),
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> {
|
||||
match item {
|
||||
ItemInNs::Types(module_def_id) => ModuleDef::from(module_def_id).name(db),
|
||||
ItemInNs::Values(module_def_id) => ModuleDef::from(module_def_id).name(db),
|
||||
ItemInNs::Macros(macro_def_id) => MacroDef::from(macro_def_id).name(db),
|
||||
}
|
||||
}
|
||||
|
||||
fn item_module(db: &RootDatabase, item: ItemInNs) -> Option<Module> {
|
||||
match item {
|
||||
ItemInNs::Types(module_def_id) => ModuleDef::from(module_def_id).module(db),
|
||||
|
@ -404,10 +404,20 @@ fn trait_applicable_items(
|
|||
}
|
||||
|
||||
let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
|
||||
let item_path = import_path_locator(item)?;
|
||||
|
||||
let assoc_item = assoc_to_item(assoc);
|
||||
let assoc_item_path = match assoc.container(db) {
|
||||
AssocItemContainer::Trait(_) => item_path.clone(),
|
||||
AssocItemContainer::Impl(impl_) => import_path_locator(ItemInNs::from(
|
||||
ModuleDef::from(impl_.target_ty(db).as_adt()?),
|
||||
))?,
|
||||
};
|
||||
|
||||
located_imports.insert(LocatedImport::new(
|
||||
import_path_locator(item)?,
|
||||
item_path,
|
||||
item,
|
||||
None,
|
||||
Some((assoc_item_path, assoc_item)),
|
||||
));
|
||||
}
|
||||
None::<()>
|
||||
|
@ -423,10 +433,20 @@ fn trait_applicable_items(
|
|||
let assoc = function.as_assoc_item(db)?;
|
||||
if required_assoc_items.contains(&assoc) {
|
||||
let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
|
||||
let item_path = import_path_locator(item)?;
|
||||
|
||||
let assoc_item = assoc_to_item(assoc);
|
||||
let assoc_item_path = match assoc.container(db) {
|
||||
AssocItemContainer::Trait(_) => item_path.clone(),
|
||||
AssocItemContainer::Impl(impl_) => import_path_locator(ItemInNs::from(
|
||||
ModuleDef::from(impl_.target_ty(db).as_adt()?),
|
||||
))?,
|
||||
};
|
||||
|
||||
located_imports.insert(LocatedImport::new(
|
||||
import_path_locator(item)?,
|
||||
item_path,
|
||||
item,
|
||||
None,
|
||||
Some((assoc_item_path, assoc_item)),
|
||||
));
|
||||
}
|
||||
None::<()>
|
||||
|
@ -437,11 +457,19 @@ fn trait_applicable_items(
|
|||
located_imports
|
||||
}
|
||||
|
||||
fn assoc_to_item(assoc: AssocItem) -> ItemInNs {
|
||||
match assoc {
|
||||
AssocItem::Function(f) => ItemInNs::from(ModuleDef::from(f)),
|
||||
AssocItem::Const(c) => ItemInNs::from(ModuleDef::from(c)),
|
||||
AssocItem::TypeAlias(t) => ItemInNs::from(ModuleDef::from(t)),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mod_path(
|
||||
db: &RootDatabase,
|
||||
item_to_search: ItemInNs,
|
||||
module_with_candidate: &Module,
|
||||
prefixed: Option<hir::PrefixKind>,
|
||||
prefixed: Option<PrefixKind>,
|
||||
) -> Option<ModPath> {
|
||||
if let Some(prefix_kind) = prefixed {
|
||||
module_with_candidate.find_use_path_prefixed(db, item_to_search, prefix_kind)
|
||||
|
@ -509,7 +537,7 @@ fn path_import_candidate(
|
|||
return None;
|
||||
}
|
||||
}
|
||||
Some(hir::PathResolution::Def(hir::ModuleDef::Adt(assoc_item_path))) => {
|
||||
Some(PathResolution::Def(ModuleDef::Adt(assoc_item_path))) => {
|
||||
ImportCandidate::TraitAssocItem(TraitImportCandidate {
|
||||
receiver_ty: assoc_item_path.ty(sema.db),
|
||||
name,
|
||||
|
|
Loading…
Reference in a new issue