From 3bb20dd2bd10186b78149282596a39218e689875 Mon Sep 17 00:00:00 2001 From: Khanh Duong Quoc Date: Wed, 23 Oct 2024 22:11:08 +0900 Subject: [PATCH 1/3] fix: auto-complete import for aliased function and module --- .../crates/ide-completion/src/render.rs | 10 ++++- .../ide-completion/src/tests/flyimport.rs | 42 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 4dd171142f9..edaa82d88fb 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -281,8 +281,14 @@ pub(crate) fn render_resolution_with_import( import_edit: LocatedImport, ) -> Option { let resolution = ScopeDef::from(import_edit.original_item); - let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?; - //this now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead + // Use the last segment when `item_to_import` matches `original_item`, + // as it will take the aliased name into account. + let local_name = if import_edit.item_to_import == import_edit.original_item { + import_edit.import_path.segments().last()?.clone() + } else { + scope_def_to_name(resolution, &ctx, &import_edit)? + }; + // This now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead. let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution); let ctx = ctx.doc_aliases(doc_aliases); Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution)) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 0b532064fb2..1ca0116c793 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -1669,3 +1669,45 @@ mod module { "#]], ); } + +#[test] +fn re_export_aliased_function() { + check( + r#" +//- /lib.rs crate:bar +pub fn func(_: i32) -> i32 {} + +//- /lib.rs crate:foo deps:bar +pub use bar::func as my_func; + +//- /main.rs crate:main deps:foo +fn main() { + m$0 +} +"#, + expect![[r#" + fn my_func(…) (use foo::my_func) fn(i32) -> i32 + "#]], + ); +} + +#[test] +fn re_export_aliased_module() { + check( + r#" +//- /lib.rs crate:bar +pub mod baz {} + +//- /lib.rs crate:foo deps:bar +pub use bar::baz as my_baz; + +//- /main.rs crate:main deps:foo +fn main() { + m$0 +} +"#, + expect![[r#" + md my_baz (use foo::my_baz) + "#]], + ); +} From 75a659e4d271aee9ebb1371dab13ff2aabea3d65 Mon Sep 17 00:00:00 2001 From: Khanh Duong Quoc Date: Thu, 24 Oct 2024 19:56:24 +0900 Subject: [PATCH 2/3] refactor: separate function for getting import name --- .../crates/ide-completion/src/render.rs | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index edaa82d88fb..08a3450fda8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -281,13 +281,7 @@ pub(crate) fn render_resolution_with_import( import_edit: LocatedImport, ) -> Option { let resolution = ScopeDef::from(import_edit.original_item); - // Use the last segment when `item_to_import` matches `original_item`, - // as it will take the aliased name into account. - let local_name = if import_edit.item_to_import == import_edit.original_item { - import_edit.import_path.segments().last()?.clone() - } else { - scope_def_to_name(resolution, &ctx, &import_edit)? - }; + let local_name = get_import_name(resolution, &ctx, &import_edit)?; // This now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead. let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution); let ctx = ctx.doc_aliases(doc_aliases); @@ -363,6 +357,24 @@ pub(crate) fn render_expr( Some(item) } +fn get_import_name( + resolution: ScopeDef, + ctx: &RenderContext<'_>, + import_edit: &LocatedImport, +) -> Option { + // FIXME: Temporary workaround for handling aliased import. + // This should be removed after we have proper support for importing alias. + // + + // If `item_to_import` matches `original_item`, we are importing the item itself (not its parent module). + // In this case, we can use the last segment of `import_path`, as it accounts for the aliased name. + if import_edit.item_to_import == import_edit.original_item { + import_edit.import_path.segments().last().cloned() + } else { + scope_def_to_name(resolution, ctx, import_edit) + } +} + fn scope_def_to_name( resolution: ScopeDef, ctx: &RenderContext<'_>, From 1b699b5d6c9d1dd9f7d24b2065ef22afa81af04e Mon Sep 17 00:00:00 2001 From: Khanh Duong Quoc Date: Thu, 24 Oct 2024 20:17:24 +0900 Subject: [PATCH 3/3] fix: handle aliased pattern and simplify testcase --- .../crates/ide-completion/src/render.rs | 2 +- .../ide-completion/src/tests/flyimport.rs | 53 +++++++++++-------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 08a3450fda8..d146990c5a3 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -294,7 +294,7 @@ pub(crate) fn render_resolution_with_import_pat( import_edit: LocatedImport, ) -> Option { let resolution = ScopeDef::from(import_edit.original_item); - let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?; + let local_name = get_import_name(resolution, &ctx, &import_edit)?; Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution)) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 1ca0116c793..4b949e0d657 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -1671,43 +1671,52 @@ mod module { } #[test] -fn re_export_aliased_function() { +fn re_export_aliased() { check( r#" -//- /lib.rs crate:bar -pub fn func(_: i32) -> i32 {} - -//- /lib.rs crate:foo deps:bar -pub use bar::func as my_func; - -//- /main.rs crate:main deps:foo -fn main() { - m$0 +mod outer { + mod inner { + pub struct BarStruct; + pub fn bar_fun() {} + pub mod bar {} + } + pub use inner::bar as foo; + pub use inner::bar_fun as foo_fun; + pub use inner::BarStruct as FooStruct; +} +fn function() { + foo$0 } "#, expect![[r#" - fn my_func(…) (use foo::my_func) fn(i32) -> i32 + st FooStruct (use outer::FooStruct) BarStruct + md foo (use outer::foo) + fn foo_fun() (use outer::foo_fun) fn() "#]], ); } #[test] -fn re_export_aliased_module() { +fn re_export_aliased_pattern() { check( r#" -//- /lib.rs crate:bar -pub mod baz {} - -//- /lib.rs crate:foo deps:bar -pub use bar::baz as my_baz; - -//- /main.rs crate:main deps:foo -fn main() { - m$0 +mod outer { + mod inner { + pub struct BarStruct; + pub fn bar_fun() {} + pub mod bar {} + } + pub use inner::bar as foo; + pub use inner::bar_fun as foo_fun; + pub use inner::BarStruct as FooStruct; +} +fn function() { + let foo$0 } "#, expect![[r#" - md my_baz (use foo::my_baz) + st FooStruct (use outer::FooStruct) + md foo (use outer::foo) "#]], ); }