mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Look for trait methods in expand glob import assist
This commit is contained in:
parent
bdb97756ca
commit
5214b4cdba
1 changed files with 65 additions and 13 deletions
|
@ -1,15 +1,17 @@
|
||||||
use hir::{MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope};
|
use hir::{AssocItem, MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope};
|
||||||
use ra_ide_db::{
|
use ra_ide_db::{
|
||||||
defs::{classify_name_ref, Definition, NameRefClass},
|
defs::{classify_name_ref, Definition, NameRefClass},
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
};
|
};
|
||||||
use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T};
|
use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assist_context::{AssistBuilder, AssistContext, Assists},
|
assist_context::{AssistBuilder, AssistContext, Assists},
|
||||||
AssistId, AssistKind,
|
AssistId, AssistKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use either::Either;
|
||||||
|
|
||||||
// Assist: expand_glob_import
|
// Assist: expand_glob_import
|
||||||
//
|
//
|
||||||
// Expands glob imports.
|
// Expands glob imports.
|
||||||
|
@ -122,7 +124,19 @@ fn find_used_names(
|
||||||
|
|
||||||
defs_in_mod
|
defs_in_mod
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|d| defs_in_source_file.contains(d))
|
.filter(|def| {
|
||||||
|
if let Def::ModuleDef(ModuleDef::Trait(tr)) = def {
|
||||||
|
for item in tr.items(ctx.db()) {
|
||||||
|
if let AssocItem::Function(f) = item {
|
||||||
|
if defs_in_source_file.contains(&Def::ModuleDef(ModuleDef::Function(f))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defs_in_source_file.contains(def)
|
||||||
|
})
|
||||||
.filter_map(|d| d.name(ctx.db()))
|
.filter_map(|d| d.name(ctx.db()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -133,28 +147,38 @@ fn replace_ast(
|
||||||
path: ast::Path,
|
path: ast::Path,
|
||||||
used_names: Vec<Name>,
|
used_names: Vec<Name>,
|
||||||
) {
|
) {
|
||||||
let new_use_tree_list = ast::make::use_tree_list(used_names.iter().map(|n| {
|
let replacement: Either<ast::UseTree, ast::UseTreeList> = if used_names.len() == 1 {
|
||||||
ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
|
Either::Left(ast::make::use_tree(
|
||||||
}));
|
ast::make::path_from_text(&format!("{}::{}", path, used_names.first().unwrap())),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Either::Right(ast::make::use_tree_list(used_names.iter().map(|n| {
|
||||||
|
ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
|
||||||
|
})))
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut replace_node = |replacement: Either<ast::UseTree, ast::UseTreeList>| {
|
||||||
|
algo::diff(node, &replacement.either(|u| u.syntax().clone(), |ut| ut.syntax().clone()))
|
||||||
|
.into_text_edit(builder.text_edit_builder());
|
||||||
|
};
|
||||||
|
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::UseTree(use_tree) => {
|
ast::UseTree(use_tree) => {
|
||||||
builder.replace_ast(use_tree, make_use_tree(path, new_use_tree_list));
|
replace_node(replacement);
|
||||||
},
|
},
|
||||||
ast::UseTreeList(use_tree_list) => {
|
ast::UseTreeList(use_tree_list) => {
|
||||||
builder.replace_ast(use_tree_list, new_use_tree_list);
|
replace_node(replacement);
|
||||||
},
|
},
|
||||||
ast::Use(use_item) => {
|
ast::Use(use_item) => {
|
||||||
builder.replace_ast(use_item, ast::make::use_item(make_use_tree(path, new_use_tree_list)));
|
builder.replace_ast(use_item, ast::make::use_item(replacement.left_or_else(|ut| ast::make::use_tree(path, Some(ut), None, false))));
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_use_tree(path: ast::Path, use_tree_list: ast::UseTreeList) -> ast::UseTree {
|
|
||||||
ast::make::use_tree(path, Some(use_tree_list), None, false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -320,6 +344,34 @@ fn main() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expanding_glob_import_with_trait_method_uses() {
|
||||||
|
check_assist(
|
||||||
|
expand_glob_import,
|
||||||
|
r"
|
||||||
|
//- /lib.rs crate:foo
|
||||||
|
pub trait Tr {
|
||||||
|
fn method(&self) {}
|
||||||
|
}
|
||||||
|
impl Tr for () {}
|
||||||
|
|
||||||
|
//- /main.rs crate:main deps:foo
|
||||||
|
use foo::*<|>;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
().method();
|
||||||
|
}
|
||||||
|
",
|
||||||
|
r"
|
||||||
|
use foo::Tr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
().method();
|
||||||
|
}
|
||||||
|
",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() {
|
fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() {
|
||||||
check_assist_not_applicable(
|
check_assist_not_applicable(
|
||||||
|
|
Loading…
Reference in a new issue