Unnamed repository; edit this file 'description' to name the repository.
extract_type_alias assist extracts inferred type when possible
When met with types with placeholders, this ensures this assist
extracts the inferred type instead of the type with placeholders.
For instance, when met with this code:
```
fn main() {
let vec: Vec<_> = vec![4];
}
```
selecting Vec<_> and extracting an alias will now yield `Vec<i32>`
instead of `Vec<_>`.
| -rw-r--r-- | crates/ide-assists/src/handlers/extract_type_alias.rs | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/crates/ide-assists/src/handlers/extract_type_alias.rs b/crates/ide-assists/src/handlers/extract_type_alias.rs index 59522458af..769bbd976a 100644 --- a/crates/ide-assists/src/handlers/extract_type_alias.rs +++ b/crates/ide-assists/src/handlers/extract_type_alias.rs @@ -1,4 +1,5 @@ use either::Either; +use hir::HirDisplay; use ide_db::syntax_helpers::node_ext::walk_ty; use syntax::{ ast::{self, AstNode, HasGenericArgs, HasGenericParams, HasName, edit::IndentLevel, make}, @@ -39,6 +40,15 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> ); let target = ty.syntax().text_range(); + let resolved_ty = ctx.sema.resolve_type(&ty)?; + let resolved_ty = if !resolved_ty.contains_unknown() { + let module = ctx.sema.scope(ty.syntax())?.module(); + let resolved_ty = resolved_ty.display_source_code(ctx.db(), module.into(), false).ok()?; + make::ty(&resolved_ty) + } else { + ty.clone() + }; + acc.add( AssistId::refactor_extract("extract_type_alias"), "Extract type as type alias", @@ -72,7 +82,7 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> // Insert new alias let ty_alias = - make::ty_alias(None, "Type", generic_params, None, None, Some((ty, None))) + make::ty_alias(None, "Type", generic_params, None, None, Some((resolved_ty, None))) .clone_for_update(); if let Some(cap) = ctx.config.snippet_cap @@ -391,4 +401,50 @@ where "#, ); } + + #[test] + fn inferred_generic_type_parameter() { + check_assist( + extract_type_alias, + r#" +struct Wrap<T>(T); + +fn main() { + let wrap: $0Wrap<_>$0 = Wrap::<_>(3i32); +} + "#, + r#" +struct Wrap<T>(T); + +type $0Type = Wrap<i32>; + +fn main() { + let wrap: Type = Wrap::<_>(3i32); +} + "#, + ) + } + + #[test] + fn inferred_type() { + check_assist( + extract_type_alias, + r#" +struct Wrap<T>(T); + +fn main() { + let wrap: Wrap<$0_$0> = Wrap::<_>(3i32); +} + "#, + r#" +struct Wrap<T>(T); + +type $0Type = i32; + +fn main() { + let wrap: Wrap<Type> = Wrap::<_>(3i32); +} + "#, + ) + } } |