Fix some tests
This commit is contained in:
parent
582cee2cdf
commit
d386481fac
@ -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)
|
.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|import| {
|
.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::Types(id) => ScopeDef::ModuleDef(id.into()),
|
||||||
hir::ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()),
|
hir::ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()),
|
||||||
hir::ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()),
|
hir::ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()),
|
||||||
@ -809,7 +809,7 @@ fn main() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn unresolved_assoc_item_container() {
|
fn unresolved_assoc_item_container() {
|
||||||
check_edit(
|
check_edit(
|
||||||
"Item",
|
"TEST_ASSOC",
|
||||||
r#"
|
r#"
|
||||||
mod foo {
|
mod foo {
|
||||||
pub struct Item;
|
pub struct Item;
|
||||||
@ -820,7 +820,7 @@ mod foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Item::TEST_A$0;
|
Item::TEST_A$0
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
r#"
|
r#"
|
||||||
@ -844,7 +844,7 @@ fn main() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn unresolved_assoc_item_container_with_path() {
|
fn unresolved_assoc_item_container_with_path() {
|
||||||
check_edit(
|
check_edit(
|
||||||
"Item",
|
"TEST_ASSOC",
|
||||||
r#"
|
r#"
|
||||||
mod foo {
|
mod foo {
|
||||||
pub mod bar {
|
pub mod bar {
|
||||||
@ -857,7 +857,7 @@ mod foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
bar::Item::TEST_A$0;
|
bar::Item::TEST_A$0
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
r#"
|
r#"
|
||||||
@ -876,6 +876,61 @@ mod foo {
|
|||||||
fn main() {
|
fn main() {
|
||||||
bar::Item::TEST_ASSOC
|
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::{
|
use hir::{
|
||||||
AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type,
|
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 syntax::TextRange;
|
||||||
|
|
||||||
use crate::{
|
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::Function(f)) => f.name(ctx.completion.db).to_string(),
|
||||||
ScopeDef::ModuleDef(ModuleDef::Const(c)) => c.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(),
|
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| {
|
Render::new(ctx).render_resolution(local_name, Some(import_edit), resolution).map(|mut item| {
|
||||||
item.completion_kind = CompletionKind::Magic;
|
item.completion_kind = CompletionKind::Magic;
|
||||||
|
@ -2,11 +2,19 @@
|
|||||||
pub mod insert_use;
|
pub mod insert_use;
|
||||||
pub mod import_assets;
|
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 syntax::ast::{self, make};
|
||||||
|
|
||||||
use crate::RootDatabase;
|
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.
|
/// Converts the mod path struct into its ast representation.
|
||||||
pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
|
pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
|
||||||
let _p = profile::span("mod_path_to_ast");
|
let _p = profile::span("mod_path_to_ast");
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
//! Look up accessible paths for items.
|
//! Look up accessible paths for items.
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{
|
use hir::{
|
||||||
AsAssocItem, AssocItem, Crate, ItemInNs, MacroDef, ModPath, Module, ModuleDef, Name,
|
AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module,
|
||||||
PrefixKind, Semantics,
|
ModuleDef, PathResolution, PrefixKind, Semantics, Type,
|
||||||
};
|
};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use syntax::{ast, AstNode};
|
use syntax::{ast, AstNode};
|
||||||
@ -12,6 +12,8 @@ use crate::{
|
|||||||
RootDatabase,
|
RootDatabase,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::item_name;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ImportCandidate {
|
pub enum ImportCandidate {
|
||||||
// A path, qualified (`std::collections::HashMap`) or not (`HashMap`).
|
// A path, qualified (`std::collections::HashMap`) or not (`HashMap`).
|
||||||
@ -28,7 +30,7 @@ pub enum ImportCandidate {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TraitImportCandidate {
|
pub struct TraitImportCandidate {
|
||||||
pub receiver_ty: hir::Type,
|
pub receiver_ty: Type,
|
||||||
pub name: NameToImport,
|
pub name: NameToImport,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ impl NameToImport {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImportAssets {
|
pub struct ImportAssets {
|
||||||
import_candidate: ImportCandidate,
|
import_candidate: ImportCandidate,
|
||||||
module_with_candidate: hir::Module,
|
module_with_candidate: Module,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportAssets {
|
impl ImportAssets {
|
||||||
@ -104,7 +106,7 @@ impl ImportAssets {
|
|||||||
|
|
||||||
pub fn for_fuzzy_method_call(
|
pub fn for_fuzzy_method_call(
|
||||||
module_with_method_call: Module,
|
module_with_method_call: Module,
|
||||||
receiver_ty: hir::Type,
|
receiver_ty: Type,
|
||||||
fuzzy_method_name: String,
|
fuzzy_method_name: String,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
Some(Self {
|
Some(Self {
|
||||||
@ -184,7 +186,7 @@ impl ImportAssets {
|
|||||||
fn search_for(
|
fn search_for(
|
||||||
&self,
|
&self,
|
||||||
sema: &Semantics<RootDatabase>,
|
sema: &Semantics<RootDatabase>,
|
||||||
prefixed: Option<hir::PrefixKind>,
|
prefixed: Option<PrefixKind>,
|
||||||
) -> Vec<LocatedImport> {
|
) -> Vec<LocatedImport> {
|
||||||
let current_crate = self.module_with_candidate.krate();
|
let current_crate = self.module_with_candidate.krate();
|
||||||
|
|
||||||
@ -223,7 +225,7 @@ impl ImportAssets {
|
|||||||
fn applicable_defs(
|
fn applicable_defs(
|
||||||
&self,
|
&self,
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
prefixed: Option<hir::PrefixKind>,
|
prefixed: Option<PrefixKind>,
|
||||||
unfiltered_defs: impl Iterator<Item = Either<ModuleDef, MacroDef>>,
|
unfiltered_defs: impl Iterator<Item = Either<ModuleDef, MacroDef>>,
|
||||||
) -> FxHashSet<LocatedImport> {
|
) -> FxHashSet<LocatedImport> {
|
||||||
let current_crate = self.module_with_candidate.krate();
|
let current_crate = self.module_with_candidate.krate();
|
||||||
@ -266,10 +268,10 @@ fn path_applicable_imports(
|
|||||||
let (assoc_original, candidate) = match def {
|
let (assoc_original, candidate) = match def {
|
||||||
Either::Left(module_def) => match module_def.as_assoc_item(db) {
|
Either::Left(module_def) => match module_def.as_assoc_item(db) {
|
||||||
Some(assoc_item) => match assoc_item.container(db) {
|
Some(assoc_item) => match assoc_item.container(db) {
|
||||||
hir::AssocItemContainer::Trait(trait_) => {
|
AssocItemContainer::Trait(trait_) => {
|
||||||
(Some(module_def), ItemInNs::from(ModuleDef::from(trait_)))
|
(Some(module_def), ItemInNs::from(ModuleDef::from(trait_)))
|
||||||
}
|
}
|
||||||
hir::AssocItemContainer::Impl(impl_) => (
|
AssocItemContainer::Impl(impl_) => (
|
||||||
Some(module_def),
|
Some(module_def),
|
||||||
ItemInNs::from(ModuleDef::from(impl_.target_ty(db).as_adt()?)),
|
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 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_qualifier_string = unresolved_qualifier.to_string();
|
||||||
let unresolved_first_segment_string = unresolved_first_segment.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_qualifier_string)
|
||||||
&& candidate_path_string.contains(&unresolved_first_segment_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))| {
|
.filter_map(|(candidate_path, (assoc_original, candidate))| {
|
||||||
if let Some(assoc_original) = assoc_original {
|
let found_segment_resolution = item_name(db, candidate)
|
||||||
if item_name(db, candidate)?.to_string() == unresolved_first_segment_string {
|
.map(|name| name.to_string() == unresolved_first_segment_string)
|
||||||
return Some(LocatedImport::new(
|
.unwrap_or(false);
|
||||||
candidate_path.clone(),
|
let (import_path, item_to_import) = if found_segment_resolution {
|
||||||
ItemInNs::from(assoc_original),
|
(candidate_path.clone(), candidate)
|
||||||
Some((candidate_path, 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 =
|
Some(match assoc_original {
|
||||||
module_with_matching_name(db, &unresolved_first_segment_string, candidate)?;
|
Some(assoc_original) => LocatedImport::new(
|
||||||
let item = ItemInNs::from(ModuleDef::from(matching_module));
|
import_path.clone(),
|
||||||
Some(LocatedImport::new(
|
item_to_import,
|
||||||
import_path_locator(item)?,
|
Some((import_path, ItemInNs::from(assoc_original))),
|
||||||
item,
|
),
|
||||||
Some((candidate_path, candidate)),
|
None => LocatedImport::new(
|
||||||
))
|
import_path,
|
||||||
|
item_to_import,
|
||||||
|
if found_segment_resolution { None } else { Some((candidate_path, candidate)) },
|
||||||
|
),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect()
|
.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> {
|
fn item_module(db: &RootDatabase, item: ItemInNs) -> Option<Module> {
|
||||||
match item {
|
match item {
|
||||||
ItemInNs::Types(module_def_id) => ModuleDef::from(module_def_id).module(db),
|
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 = 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(
|
located_imports.insert(LocatedImport::new(
|
||||||
import_path_locator(item)?,
|
item_path,
|
||||||
item,
|
item,
|
||||||
None,
|
Some((assoc_item_path, assoc_item)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
None::<()>
|
None::<()>
|
||||||
@ -423,10 +433,20 @@ fn trait_applicable_items(
|
|||||||
let assoc = function.as_assoc_item(db)?;
|
let assoc = function.as_assoc_item(db)?;
|
||||||
if required_assoc_items.contains(&assoc) {
|
if required_assoc_items.contains(&assoc) {
|
||||||
let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
|
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(
|
located_imports.insert(LocatedImport::new(
|
||||||
import_path_locator(item)?,
|
item_path,
|
||||||
item,
|
item,
|
||||||
None,
|
Some((assoc_item_path, assoc_item)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
None::<()>
|
None::<()>
|
||||||
@ -437,11 +457,19 @@ fn trait_applicable_items(
|
|||||||
located_imports
|
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(
|
fn get_mod_path(
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
item_to_search: ItemInNs,
|
item_to_search: ItemInNs,
|
||||||
module_with_candidate: &Module,
|
module_with_candidate: &Module,
|
||||||
prefixed: Option<hir::PrefixKind>,
|
prefixed: Option<PrefixKind>,
|
||||||
) -> Option<ModPath> {
|
) -> Option<ModPath> {
|
||||||
if let Some(prefix_kind) = prefixed {
|
if let Some(prefix_kind) = prefixed {
|
||||||
module_with_candidate.find_use_path_prefixed(db, item_to_search, prefix_kind)
|
module_with_candidate.find_use_path_prefixed(db, item_to_search, prefix_kind)
|
||||||
@ -509,7 +537,7 @@ fn path_import_candidate(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(hir::PathResolution::Def(hir::ModuleDef::Adt(assoc_item_path))) => {
|
Some(PathResolution::Def(ModuleDef::Adt(assoc_item_path))) => {
|
||||||
ImportCandidate::TraitAssocItem(TraitImportCandidate {
|
ImportCandidate::TraitAssocItem(TraitImportCandidate {
|
||||||
receiver_ty: assoc_item_path.ty(sema.db),
|
receiver_ty: assoc_item_path.ty(sema.db),
|
||||||
name,
|
name,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user