Skip to content

Commit d2a05af

Browse files
committed
fix: rename and add import
Signed-off-by: Hayashi Mikihiro <[email protected]>
1 parent f8e7843 commit d2a05af

File tree

6 files changed

+262
-32
lines changed

6 files changed

+262
-32
lines changed

crates/hir/src/semantics.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ impl PathResolutionPerNs {
121121
pub fn any(&self) -> Option<PathResolution> {
122122
self.type_ns.or(self.value_ns).or(self.macro_ns)
123123
}
124+
pub fn to_small_vec(&self) -> SmallVec<[Option<PathResolution>; 3]> {
125+
smallvec![self.type_ns, self.value_ns, self.macro_ns,]
126+
}
124127
}
125128

126129
#[derive(Debug)]

crates/ide-db/src/rename.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use crate::{
2929
use base_db::AnchoredPathBuf;
3030
use either::Either;
3131
use hir::{EditionedFileId, FieldSource, FileRange, InFile, ModuleSource, Semantics};
32+
use itertools::Itertools;
3233
use span::{Edition, FileId, SyntaxContext};
3334
use stdx::{TupleExt, never};
3435
use syntax::{
@@ -316,7 +317,7 @@ fn rename_mod(
316317
let ref_edits = usages.iter().map(|(file_id, references)| {
317318
(
318319
file_id.file_id(sema.db),
319-
source_edit_from_references(references, def, new_name, file_id.edition(sema.db)),
320+
source_edit_from_references(sema, references, def, new_name, file_id.edition(sema.db)),
320321
)
321322
});
322323
source_change.extend(ref_edits);
@@ -363,7 +364,7 @@ fn rename_reference(
363364
source_change.extend(usages.iter().map(|(file_id, references)| {
364365
(
365366
file_id.file_id(sema.db),
366-
source_edit_from_references(references, def, new_name, file_id.edition(sema.db)),
367+
source_edit_from_references(sema, references, def, new_name, file_id.edition(sema.db)),
367368
)
368369
}));
369370

@@ -375,6 +376,7 @@ fn rename_reference(
375376
}
376377

377378
pub fn source_edit_from_references(
379+
sema: &Semantics<'_, RootDatabase>,
378380
references: &[FileReference],
379381
def: Definition,
380382
new_name: &str,
@@ -395,7 +397,7 @@ pub fn source_edit_from_references(
395397
// to make special rewrites like shorthand syntax and such, so just rename the node in
396398
// the macro input
397399
FileReferenceNode::NameRef(name_ref) if name_range == range => {
398-
source_edit_from_name_ref(&mut edit, name_ref, &new_name, def)
400+
source_edit_from_name_ref(&mut edit, sema, name_ref, &new_name, def)
399401
}
400402
FileReferenceNode::Name(name) if name_range == range => {
401403
source_edit_from_name(&mut edit, name, &new_name)
@@ -438,6 +440,7 @@ fn source_edit_from_name(edit: &mut TextEditBuilder, name: &ast::Name, new_name:
438440

439441
fn source_edit_from_name_ref(
440442
edit: &mut TextEditBuilder,
443+
sema: &Semantics<'_, RootDatabase>,
441444
name_ref: &ast::NameRef,
442445
new_name: &str,
443446
def: Definition,
@@ -525,6 +528,31 @@ fn source_edit_from_name_ref(
525528
}
526529
_ => (),
527530
}
531+
} else if let Some(res) = ast::UseTree::find_tail_use_tree_for_name_ref(name_ref)
532+
.and_then(|u| u.path())
533+
.and_then(|p| sema.resolve_path_per_ns(&p))
534+
{
535+
let res = res
536+
.to_small_vec()
537+
.into_iter()
538+
.flatten()
539+
.filter_map(|res| match res {
540+
hir::PathResolution::Def(def) => Some(Definition::from(def)),
541+
_ => None,
542+
})
543+
.unique()
544+
.collect::<Vec<_>>();
545+
546+
let range = name_ref.syntax().text_range();
547+
if res.iter().any(|res| res == &def) {
548+
if res.len() == 1 {
549+
edit.replace(range, new_name.to_owned());
550+
} else {
551+
edit.replace(range, format!("{{{}, {}}}", new_name, name_ref.text()));
552+
}
553+
}
554+
555+
return true;
528556
}
529557
false
530558
}

crates/ide-db/src/search.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,22 @@ impl<'a> FindUsages<'a> {
11701170
}
11711171
}
11721172

1173+
fn is_related_import(&self, name_ref: &ast::NameRef) -> bool {
1174+
ast::UseTree::find_tail_use_tree_for_name_ref(name_ref)
1175+
.and_then(|u| u.path())
1176+
.and_then(|path| self.sema.resolve_path_per_ns(&path))
1177+
.map(|res| {
1178+
res.to_small_vec()
1179+
.into_iter()
1180+
.filter_map(|res| match res {
1181+
Some(PathResolution::Def(def)) => Some(Definition::from(def)),
1182+
_ => None,
1183+
})
1184+
.any(|def| def == self.def)
1185+
})
1186+
== Some(true)
1187+
}
1188+
11731189
fn found_name_ref(
11741190
&self,
11751191
name_ref: &ast::NameRef,
@@ -1180,7 +1196,8 @@ impl<'a> FindUsages<'a> {
11801196
if self.def == def
11811197
// is our def a trait assoc item? then we want to find all assoc items from trait impls of our trait
11821198
|| matches!(self.assoc_item_container, Some(hir::AssocItemContainer::Trait(_)))
1183-
&& convert_to_def_in_trait(self.sema.db, def) == self.def =>
1199+
&& convert_to_def_in_trait(self.sema.db, def) == self.def
1200+
|| self.is_related_import(name_ref) =>
11841201
{
11851202
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
11861203
let reference = FileReference {

crates/ide/src/references.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,7 +1762,6 @@ trait Trait {
17621762
)
17631763
}
17641764

1765-
// FIXME: import is classified as function
17661765
#[test]
17671766
fn attr() {
17681767
check(
@@ -1776,6 +1775,7 @@ fn func() {}
17761775
expect![[r#"
17771776
identity Attribute FileId(1) 1..107 32..40
17781777
1778+
FileId(0) 17..25 import
17791779
FileId(0) 43..51
17801780
"#]],
17811781
);
@@ -1793,7 +1793,6 @@ fn func$0() {}
17931793
);
17941794
}
17951795

1796-
// FIXME: import is classified as function
17971796
#[test]
17981797
fn proc_macro() {
17991798
check(
@@ -1806,6 +1805,7 @@ mirror$0! {}
18061805
expect![[r#"
18071806
mirror ProcMacro FileId(1) 1..77 22..28
18081807
1808+
FileId(0) 17..23 import
18091809
FileId(0) 26..32
18101810
"#]],
18111811
)

0 commit comments

Comments
 (0)