mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
Merge #814
814: auto_import: import in enclosing module by default r=matklad a=eulerdisk Simpler version of #795 Co-authored-by: Andrea Pretto <eulerdisk@gmail.com>
This commit is contained in:
commit
74d03d57e7
1 changed files with 82 additions and 14 deletions
|
@ -1,6 +1,6 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast, AstNode, SyntaxNode, Direction, TextRange,
|
||||
ast::{ self, NameOwner }, AstNode, SyntaxNode, Direction, TextRange,
|
||||
SyntaxKind::{ PATH, PATH_SEGMENT, COLONCOLON, COMMA }
|
||||
};
|
||||
use crate::assist_ctx::{AssistCtx, Assist, AssistBuilder};
|
||||
|
@ -345,9 +345,9 @@ fn best_action_for_target<'b, 'a: 'b>(
|
|||
match best_action {
|
||||
Some(action) => return action,
|
||||
None => {
|
||||
// We have no action we no use item was found in container so we find
|
||||
// We have no action and no UseItem was found in container so we find
|
||||
// another item and we use it as anchor.
|
||||
// If there are not items, we choose the target path itself as anchor.
|
||||
// If there are no items, we choose the target path itself as anchor.
|
||||
let anchor = container
|
||||
.children()
|
||||
.find_map(ast::ModuleItem::cast)
|
||||
|
@ -480,6 +480,24 @@ fn make_assist_add_nested_import(
|
|||
}
|
||||
}
|
||||
|
||||
fn apply_auto_import<'a>(
|
||||
container: &SyntaxNode,
|
||||
path: &ast::Path,
|
||||
target: &[&'a ast::PathSegment],
|
||||
edit: &mut AssistBuilder,
|
||||
) {
|
||||
let action = best_action_for_target(container, path, target);
|
||||
make_assist(&action, target, edit);
|
||||
if let (Some(first), Some(last)) = (target.first(), target.last()) {
|
||||
// Here we are assuming the assist will provide a correct use statement
|
||||
// so we can delete the path qualifier
|
||||
edit.delete(TextRange::from_to(
|
||||
first.syntax().range().start(),
|
||||
last.syntax().range().start(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
let node = ctx.covering_node();
|
||||
let current_file = node.ancestors().find_map(ast::SourceFile::cast)?;
|
||||
|
@ -495,18 +513,20 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
|
|||
return None;
|
||||
}
|
||||
|
||||
ctx.add_action(format!("import {} in the current file", fmt_segments(&segments)), |edit| {
|
||||
let action = best_action_for_target(current_file.syntax(), path, &segments);
|
||||
make_assist(&action, segments.as_slice(), edit);
|
||||
if let Some(last_segment) = path.segment() {
|
||||
// Here we are assuming the assist will provide a correct use statement
|
||||
// so we can delete the path qualifier
|
||||
edit.delete(TextRange::from_to(
|
||||
path.syntax().range().start(),
|
||||
last_segment.syntax().range().start(),
|
||||
));
|
||||
if let Some(module) = path.syntax().ancestors().find_map(ast::Module::cast) {
|
||||
if let (Some(item_list), Some(name)) = (module.item_list(), module.name()) {
|
||||
ctx.add_action(
|
||||
format!("import {} in mod {}", fmt_segments(&segments), name.text()),
|
||||
|edit| {
|
||||
apply_auto_import(item_list.syntax(), path, &segments, edit);
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ctx.add_action(format!("import {} in the current file", fmt_segments(&segments)), |edit| {
|
||||
apply_auto_import(current_file.syntax(), path, &segments, edit);
|
||||
});
|
||||
}
|
||||
|
||||
ctx.build()
|
||||
}
|
||||
|
@ -531,6 +551,21 @@ Debug<|>
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_auto_import_file_add_use_no_anchor_2seg() {
|
||||
check_assist(
|
||||
auto_import,
|
||||
"
|
||||
std::fmt<|>::Debug
|
||||
",
|
||||
"
|
||||
use std::fmt;
|
||||
|
||||
fmt<|>::Debug
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_auto_import_file_add_use() {
|
||||
check_assist(
|
||||
|
@ -728,4 +763,37 @@ impl foo<|> for Foo {
|
|||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_auto_import_not_applicable_in_use() {
|
||||
check_assist_not_applicable(
|
||||
auto_import,
|
||||
"
|
||||
use std::fmt<|>;
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_auto_import_file_add_use_no_anchor_in_mod_mod() {
|
||||
check_assist(
|
||||
auto_import,
|
||||
"
|
||||
mod foo {
|
||||
mod bar {
|
||||
std::fmt::Debug<|>
|
||||
}
|
||||
}
|
||||
",
|
||||
"
|
||||
mod foo {
|
||||
mod bar {
|
||||
use std::fmt::Debug;
|
||||
|
||||
Debug<|>
|
||||
}
|
||||
}
|
||||
",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue