Skip to content

Commit 74d03d5

Browse files
bors[bot]eulerdisk
andcommitted
Merge #814
814: auto_import: import in enclosing module by default r=matklad a=eulerdisk Simpler version of #795 Co-authored-by: Andrea Pretto <[email protected]>
2 parents 92faa22 + 6518fb2 commit 74d03d5

File tree

1 file changed

+82
-14
lines changed

1 file changed

+82
-14
lines changed

crates/ra_assists/src/auto_import.rs

+82-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use hir::db::HirDatabase;
22
use ra_syntax::{
3-
ast, AstNode, SyntaxNode, Direction, TextRange,
3+
ast::{ self, NameOwner }, AstNode, SyntaxNode, Direction, TextRange,
44
SyntaxKind::{ PATH, PATH_SEGMENT, COLONCOLON, COMMA }
55
};
66
use crate::assist_ctx::{AssistCtx, Assist, AssistBuilder};
@@ -345,9 +345,9 @@ fn best_action_for_target<'b, 'a: 'b>(
345345
match best_action {
346346
Some(action) => return action,
347347
None => {
348-
// We have no action we no use item was found in container so we find
348+
// We have no action and no UseItem was found in container so we find
349349
// another item and we use it as anchor.
350-
// If there are not items, we choose the target path itself as anchor.
350+
// If there are no items, we choose the target path itself as anchor.
351351
let anchor = container
352352
.children()
353353
.find_map(ast::ModuleItem::cast)
@@ -480,6 +480,24 @@ fn make_assist_add_nested_import(
480480
}
481481
}
482482

483+
fn apply_auto_import<'a>(
484+
container: &SyntaxNode,
485+
path: &ast::Path,
486+
target: &[&'a ast::PathSegment],
487+
edit: &mut AssistBuilder,
488+
) {
489+
let action = best_action_for_target(container, path, target);
490+
make_assist(&action, target, edit);
491+
if let (Some(first), Some(last)) = (target.first(), target.last()) {
492+
// Here we are assuming the assist will provide a correct use statement
493+
// so we can delete the path qualifier
494+
edit.delete(TextRange::from_to(
495+
first.syntax().range().start(),
496+
last.syntax().range().start(),
497+
));
498+
}
499+
}
500+
483501
pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
484502
let node = ctx.covering_node();
485503
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
495513
return None;
496514
}
497515

498-
ctx.add_action(format!("import {} in the current file", fmt_segments(&segments)), |edit| {
499-
let action = best_action_for_target(current_file.syntax(), path, &segments);
500-
make_assist(&action, segments.as_slice(), edit);
501-
if let Some(last_segment) = path.segment() {
502-
// Here we are assuming the assist will provide a correct use statement
503-
// so we can delete the path qualifier
504-
edit.delete(TextRange::from_to(
505-
path.syntax().range().start(),
506-
last_segment.syntax().range().start(),
507-
));
516+
if let Some(module) = path.syntax().ancestors().find_map(ast::Module::cast) {
517+
if let (Some(item_list), Some(name)) = (module.item_list(), module.name()) {
518+
ctx.add_action(
519+
format!("import {} in mod {}", fmt_segments(&segments), name.text()),
520+
|edit| {
521+
apply_auto_import(item_list.syntax(), path, &segments, edit);
522+
},
523+
);
508524
}
509-
});
525+
} else {
526+
ctx.add_action(format!("import {} in the current file", fmt_segments(&segments)), |edit| {
527+
apply_auto_import(current_file.syntax(), path, &segments, edit);
528+
});
529+
}
510530

511531
ctx.build()
512532
}
@@ -531,6 +551,21 @@ Debug<|>
531551
);
532552
}
533553

554+
#[test]
555+
fn test_auto_import_file_add_use_no_anchor_2seg() {
556+
check_assist(
557+
auto_import,
558+
"
559+
std::fmt<|>::Debug
560+
",
561+
"
562+
use std::fmt;
563+
564+
fmt<|>::Debug
565+
",
566+
);
567+
}
568+
534569
#[test]
535570
fn test_auto_import_file_add_use() {
536571
check_assist(
@@ -728,4 +763,37 @@ impl foo<|> for Foo {
728763
",
729764
);
730765
}
766+
767+
#[test]
768+
fn test_auto_import_not_applicable_in_use() {
769+
check_assist_not_applicable(
770+
auto_import,
771+
"
772+
use std::fmt<|>;
773+
",
774+
);
775+
}
776+
777+
#[test]
778+
fn test_auto_import_file_add_use_no_anchor_in_mod_mod() {
779+
check_assist(
780+
auto_import,
781+
"
782+
mod foo {
783+
mod bar {
784+
std::fmt::Debug<|>
785+
}
786+
}
787+
",
788+
"
789+
mod foo {
790+
mod bar {
791+
use std::fmt::Debug;
792+
793+
Debug<|>
794+
}
795+
}
796+
",
797+
);
798+
}
731799
}

0 commit comments

Comments
 (0)