Consider import prefix config settings during flyimports

This commit is contained in:
Kirill Bulatov 2021-02-20 13:53:50 +02:00
parent 23f0d4baa1
commit 4fe5786c0c
3 changed files with 94 additions and 4 deletions

View File

@ -2076,7 +2076,7 @@ pub fn return_type(&self) -> Type {
} }
/// For IDE only /// For IDE only
#[derive(Debug)] #[derive(Debug, PartialEq, Eq, Hash)]
pub enum ScopeDef { pub enum ScopeDef {
ModuleDef(ModuleDef), ModuleDef(ModuleDef),
MacroDef(MacroDef), MacroDef(MacroDef),

View File

@ -53,6 +53,7 @@
import_assets::{ImportAssets, ImportCandidate}, import_assets::{ImportAssets, ImportCandidate},
insert_use::ImportScope, insert_use::ImportScope,
}; };
use rustc_hash::FxHashSet;
use syntax::{AstNode, SyntaxNode, T}; use syntax::{AstNode, SyntaxNode, T};
use test_utils::mark; use test_utils::mark;
@ -91,8 +92,10 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
position_for_import(ctx, Some(import_assets.import_candidate()))?, position_for_import(ctx, Some(import_assets.import_candidate()))?,
&ctx.sema, &ctx.sema,
)?; )?;
let scope_definitions = scope_definitions(ctx);
let mut all_mod_paths = import_assets let mut all_mod_paths = import_assets
.search_for_relative_paths(&ctx.sema) .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
.into_iter() .into_iter()
.map(|(mod_path, item_in_ns)| { .map(|(mod_path, item_in_ns)| {
let scope_item = match item_in_ns { let scope_item = match item_in_ns {
@ -102,6 +105,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
}; };
(mod_path, scope_item) (mod_path, scope_item)
}) })
.filter(|(_, proposed_def)| !scope_definitions.contains(proposed_def))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
all_mod_paths.sort_by_cached_key(|(mod_path, _)| { all_mod_paths.sort_by_cached_key(|(mod_path, _)| {
compute_fuzzy_completion_order_key(mod_path, &user_input_lowercased) compute_fuzzy_completion_order_key(mod_path, &user_input_lowercased)
@ -125,6 +129,14 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
Some(()) Some(())
} }
fn scope_definitions(ctx: &CompletionContext) -> FxHashSet<ScopeDef> {
let mut scope_definitions = FxHashSet::default();
ctx.scope.process_all_names(&mut |_, scope_def| {
scope_definitions.insert(scope_def);
});
scope_definitions
}
pub(crate) fn position_for_import<'a>( pub(crate) fn position_for_import<'a>(
ctx: &'a CompletionContext, ctx: &'a CompletionContext,
import_candidate: Option<&ImportCandidate>, import_candidate: Option<&ImportCandidate>,
@ -192,7 +204,7 @@ mod tests {
use crate::{ use crate::{
item::CompletionKind, item::CompletionKind,
test_utils::{check_edit, completion_list}, test_utils::{check_edit, check_edit_with_config, completion_list, TEST_CONFIG},
}; };
fn check(ra_fixture: &str, expect: Expect) { fn check(ra_fixture: &str, expect: Expect) {
@ -685,4 +697,82 @@ fn main() {}
expect![[]], expect![[]],
); );
} }
#[test]
fn prefix_config_usage() {
let fixture = r#"
mod foo {
pub mod bar {
pub struct Item;
}
}
use crate::foo::bar;
fn main() {
Ite$0
}"#;
let mut config = TEST_CONFIG;
config.insert_use.prefix_kind = hir::PrefixKind::ByCrate;
check_edit_with_config(
config.clone(),
"Item",
fixture,
r#"
mod foo {
pub mod bar {
pub struct Item;
}
}
use crate::foo::bar::{self, Item};
fn main() {
Item
}"#,
);
config.insert_use.prefix_kind = hir::PrefixKind::BySelf;
check_edit_with_config(
config.clone(),
"Item",
fixture,
r#"
mod foo {
pub mod bar {
pub struct Item;
}
}
use crate::foo::bar;
use self::foo::bar::Item;
fn main() {
Item
}"#,
);
config.insert_use.prefix_kind = hir::PrefixKind::Plain;
check_edit_with_config(
config,
"Item",
fixture,
r#"
mod foo {
pub mod bar {
pub struct Item;
}
}
use foo::bar::Item;
use crate::foo::bar;
fn main() {
Item
}"#,
);
}
} }

View File

@ -151,7 +151,7 @@ pub fn resolve_completion_edits(
let import_path = imports_locator::find_exact_imports(&ctx.sema, current_crate, imported_name) let import_path = imports_locator::find_exact_imports(&ctx.sema, current_crate, imported_name)
.filter_map(|candidate| { .filter_map(|candidate| {
let item: hir::ItemInNs = candidate.either(Into::into, Into::into); let item: hir::ItemInNs = candidate.either(Into::into, Into::into);
current_module.find_use_path(db, item) current_module.find_use_path_prefixed(db, item, config.insert_use.prefix_kind)
}) })
.find(|mod_path| mod_path.to_string() == full_import_path)?; .find(|mod_path| mod_path.to_string() == full_import_path)?;