Merge pull request #19745 from Veykril/push-rnqulnqvltro
minor: Add a mbe test for parsing negative literals
diff --git a/crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs b/crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs
new file mode 100644
index 0000000..7b5adc1
--- /dev/null
+++ b/crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs
@@ -0,0 +1,156 @@
+use ide_db::assists::AssistId;
+use syntax::{
+ AstNode,
+ ast::{self, GenericArg, HasGenericArgs},
+};
+
+use crate::{AssistContext, Assists};
+
+// Assist: unwrap_type_to_generic_arg
+//
+// This assist unwraps a type into its generic type argument.
+//
+// ```
+// fn foo() -> $0Option<i32> {
+// todo!()
+// }
+// ```
+// ->
+// ```
+// fn foo() -> i32 {
+// todo!()
+// }
+// ```
+pub(crate) fn unwrap_type_to_generic_arg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let path_type = ctx.find_node_at_offset::<ast::PathType>()?;
+ let path = path_type.path()?;
+ let segment = path.segment()?;
+ let args_list = segment.generic_arg_list()?;
+
+ let mut generic_arg = None;
+
+ for arg in args_list.generic_args() {
+ match arg {
+ GenericArg::ConstArg(_) | GenericArg::LifetimeArg(_) => (),
+ GenericArg::TypeArg(arg) if generic_arg.is_none() => {
+ generic_arg = Some(arg);
+ }
+ _ => return None,
+ }
+ }
+
+ let generic_arg = generic_arg?;
+
+ acc.add(
+ AssistId::refactor_extract("unwrap_type_to_generic_arg"),
+ format!("Unwrap type to type argument {generic_arg}"),
+ path_type.syntax().text_range(),
+ |builder| {
+ let mut editor = builder.make_editor(path_type.syntax());
+ editor.replace(path_type.syntax(), generic_arg.syntax());
+
+ builder.add_file_edits(ctx.vfs_file_id(), editor);
+ },
+ )
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tests::{check_assist, check_assist_not_applicable};
+
+ #[test]
+ fn test_unwrap_type_to_generic_arg() {
+ check_assist(
+ unwrap_type_to_generic_arg,
+ r#"
+//- minicore: option
+fn foo() -> $0Option<i32> {
+ todo!()
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ todo!()
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn unwrap_type_to_generic_arg_not_applicable_for_non_generic_arg_list() {
+ check_assist_not_applicable(
+ unwrap_type_to_generic_arg,
+ r#"
+fn foo() -> $0i32 {}
+"#,
+ );
+ }
+
+ #[test]
+ fn unwrap_type_to_generic_arg_not_applicable_for_multiple_generic_args() {
+ check_assist_not_applicable(
+ unwrap_type_to_generic_arg,
+ r#"
+//- minicore: result
+fn foo() -> $0Result<i32, ()> {
+ todo!()
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn unwrap_type_to_generic_arg_with_lifetime_and_const() {
+ check_assist(
+ unwrap_type_to_generic_arg,
+ r#"
+enum Foo<'a, T, const N: usize> {
+ Bar(T),
+ Baz(&'a [T; N]),
+}
+
+fn test<'a>() -> $0Foo<'a, i32, 3> {
+ todo!()
+}
+"#,
+ r#"
+enum Foo<'a, T, const N: usize> {
+ Bar(T),
+ Baz(&'a [T; N]),
+}
+
+fn test<'a>() -> i32 {
+ todo!()
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn unwrap_type_to_generic_arg_in_let_stmt() {
+ check_assist(
+ unwrap_type_to_generic_arg,
+ r#"
+enum Foo<T> {
+ Bar(T),
+ Baz,
+}
+
+fn test() {
+ let foo: $0Foo<i32> = todo!();
+}
+"#,
+ r#"
+enum Foo<T> {
+ Bar(T),
+ Baz,
+}
+
+fn test() {
+ let foo: i32 = todo!();
+}
+"#,
+ );
+ }
+}
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index 627ed37..2395091 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -229,6 +229,7 @@
mod unwrap_block;
mod unwrap_return_type;
mod unwrap_tuple;
+ mod unwrap_type_to_generic_arg;
mod wrap_return_type;
mod wrap_unwrap_cfg_attr;
@@ -369,6 +370,7 @@
unwrap_block::unwrap_block,
unwrap_return_type::unwrap_return_type,
unwrap_tuple::unwrap_tuple,
+ unwrap_type_to_generic_arg::unwrap_type_to_generic_arg,
wrap_return_type::wrap_return_type,
wrap_unwrap_cfg_attr::wrap_unwrap_cfg_attr,
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 01ab0be..76134ac 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -3482,6 +3482,23 @@
}
#[test]
+fn doctest_unwrap_type_to_generic_arg() {
+ check_doc_test(
+ "unwrap_type_to_generic_arg",
+ r#####"
+fn foo() -> $0Option<i32> {
+ todo!()
+}
+"#####,
+ r#####"
+fn foo() -> i32 {
+ todo!()
+}
+"#####,
+ )
+}
+
+#[test]
fn doctest_wrap_return_type_in_option() {
check_doc_test(
"wrap_return_type_in_option",